diff --git a/server/go.mod b/server/go.mod index ecfccd2..dacf2ae 100644 --- a/server/go.mod +++ b/server/go.mod @@ -8,6 +8,6 @@ require ( ) require ( - github.com/tus/tusd/v2 v2.10.0 + github.com/tus/tusd/v2 v2.10.1 golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa ) diff --git a/server/go.sum b/server/go.sum index 1458bdc..3b99858 100644 --- a/server/go.sum +++ b/server/go.sum @@ -1,22 +1,18 @@ github.com/Acconut/go-httptest-recorder v1.0.0 h1:TAv2dfnqp/l+SUvIaMAUK4GeN4+wqb6KZsFFFTGhoJg= github.com/Acconut/go-httptest-recorder v1.0.0/go.mod h1:CwQyhTH1kq/gLyWiRieo7c0uokpu3PXeyF/nZjUNtmM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-chi/chi/v5 v5.3.2 h1:5YQkICvTCSZ25hoRsyJazN0scjzKGiu4VAUc7H1o1nY= github.com/go-chi/chi/v5 v5.3.2/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/tus/tusd/v2 v2.10.0 h1:2yOGmkrDl9RQmRIt/00DR2WvYWOoiEu3CoygILb+WRw= -github.com/tus/tusd/v2 v2.10.0/go.mod h1:T/OuJHIAC2NHpkEUyQyyaoWyDNRDcQVpJzWl8tX5GY4= +github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= +github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= +github.com/tus/tusd/v2 v2.10.1 h1:hO312j4rT0unhaF4Ga7izNaYGbPOKI2kVIXbKgtv1W8= +github.com/tus/tusd/v2 v2.10.1/go.mod h1:33RsdwtbXdqb3esrge+95TT7XUHl45uSO1vvA96fNbc= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa h1:QSyA8ishJCyT21kER9KwNt0b7BM3iRK4x9QXhjN5Fdk= golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa/go.mod h1:zeBbvyFKDaLwa7CH/zI8KXt7gTl14SF7sO08Pl5jBCM= -golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= -golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= +golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/server/vendor/github.com/tus/tusd/v2/pkg/handler/unrouted_handler.go b/server/vendor/github.com/tus/tusd/v2/pkg/handler/unrouted_handler.go index 3053c7d..d9289f9 100644 --- a/server/vendor/github.com/tus/tusd/v2/pkg/handler/unrouted_handler.go +++ b/server/vendor/github.com/tus/tusd/v2/pkg/handler/unrouted_handler.go @@ -341,8 +341,8 @@ func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request) } // Test whether the size is still allowed - if handler.config.MaxSize > 0 && size > handler.config.MaxSize { - handler.sendError(c, ErrMaxSizeExceeded) + if err := handler.validateMaxSize(size); err != nil { + handler.sendError(c, err) return } @@ -484,6 +484,13 @@ func (handler *UnroutedHandler) PostFileV2(w http.ResponseWriter, r *http.Reques return } + // Enforce MaxSize for known lengths. Deferred uploads (size 0 here) are + // bounded later in writeChunk. + if err := handler.validateMaxSize(size); err != nil { + handler.sendError(c, err) + return + } + if !sizeIsDeferred { info.Size = size } else { @@ -815,8 +822,10 @@ func (handler *UnroutedHandler) PatchFile(w http.ResponseWriter, r *http.Request handler.sendError(c, ErrInvalidUploadLength) return } - uploadLength, err := strconv.ParseInt(r.Header.Get("Upload-Length"), 10, 64) - if err != nil || uploadLength < 0 || uploadLength < info.Offset || (handler.config.MaxSize > 0 && uploadLength > handler.config.MaxSize) { + uploadLength, err := parseUploadLength(r.Header.Get("Upload-Length")) + if err != nil || uploadLength < info.Offset || handler.validateMaxSize(uploadLength) != nil { + // Keep ErrInvalidUploadLength for PATCH length declaration failures, + // including MaxSize violations, to preserve existing client-facing behavior. handler.sendError(c, ErrInvalidUploadLength) return } @@ -893,8 +902,10 @@ func (handler *UnroutedHandler) writeChunk(c *httpContext, resp HTTPResponse, up maxSize = math.MaxInt64 } } + // Cap by Content-Length when present, but never raise the limit above the + // MaxSize/remaining-size clamp computed above (see #1032). if length > 0 { - maxSize = length + maxSize = min(maxSize, length) } c.log.InfoContext(c, "ChunkWriteStart", "maxSize", maxSize, "offset", offset) @@ -1416,6 +1427,23 @@ func (handler *UnroutedHandler) sizeOfUploads(ctx context.Context, ids []string) return } +// parseUploadLength parses an Upload-Length header value and rejects negative lengths. +func parseUploadLength(header string) (int64, error) { + uploadLength, err := strconv.ParseInt(header, 10, 64) + if err != nil || uploadLength < 0 { + return 0, ErrInvalidUploadLength + } + return uploadLength, nil +} + +// validateMaxSize returns ErrMaxSizeExceeded if size is larger than the configured maximum. +func (handler *UnroutedHandler) validateMaxSize(size int64) error { + if handler.config.MaxSize > 0 && size > handler.config.MaxSize { + return ErrMaxSizeExceeded + } + return nil +} + // Verify that the Upload-Length and Upload-Defer-Length headers are acceptable for creating a // new upload func (handler *UnroutedHandler) validateNewUploadLengthHeaders(uploadLengthHeader string, uploadDeferLengthHeader string) (uploadLength int64, uploadLengthDeferred bool, err error) { @@ -1432,10 +1460,7 @@ func (handler *UnroutedHandler) validateNewUploadLengthHeaders(uploadLengthHeade } else if lengthIsDeferred { uploadLengthDeferred = true } else { - uploadLength, err = strconv.ParseInt(uploadLengthHeader, 10, 64) - if err != nil || uploadLength < 0 { - err = ErrInvalidUploadLength - } + uploadLength, err = parseUploadLength(uploadLengthHeader) } return @@ -1549,9 +1574,9 @@ func getIETFDraftUploadLength(r *http.Request) (length int64, lengthIsDeferred b uploadLengthStr := r.Header.Get("Upload-Length") if uploadLengthStr != "" { var err error - lengthFromUploadLength, err = strconv.ParseInt(uploadLengthStr, 10, 64) + lengthFromUploadLength, err = parseUploadLength(uploadLengthStr) if err != nil { - return 0, false, ErrInvalidUploadLength + return 0, false, err } hasLengthFromUploadLength = true diff --git a/server/vendor/modules.txt b/server/vendor/modules.txt index 8756066..042cd2a 100644 --- a/server/vendor/modules.txt +++ b/server/vendor/modules.txt @@ -1,8 +1,8 @@ # github.com/go-chi/chi/v5 v5.3.2 ## explicit; go 1.23 github.com/go-chi/chi/v5 -# github.com/tus/tusd/v2 v2.10.0 -## explicit; go 1.25.8 +# github.com/tus/tusd/v2 v2.10.1 +## explicit; go 1.25.14 github.com/tus/tusd/v2/internal/uid github.com/tus/tusd/v2/pkg/filestore github.com/tus/tusd/v2/pkg/handler