From 83b143103c53c040964b9694dd24b44254bdc2c5 Mon Sep 17 00:00:00 2001 From: Rohit Behera <126186063+r0h1tb@users.noreply.github.com> Date: Sat, 22 Aug 2026 03:39:32 +0530 Subject: [PATCH] huaweidrive: fix truncated files being uploaded successfully when the source ends early The multipart upload copied the source into the request buffer without checking how many bytes it had read, so a source that supplied fewer bytes than its declared size was accepted by the server and reported as a success with a truncated file stored. Count the bytes actually read and fail the upload if they do not match the declared size. Signed-off-by: Rohit Behera <126186063+r0h1tb@users.noreply.github.com> --- backend/huaweidrive/huaweidrive.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/backend/huaweidrive/huaweidrive.go b/backend/huaweidrive/huaweidrive.go index e9e46367a..4fa1ebdd8 100644 --- a/backend/huaweidrive/huaweidrive.go +++ b/backend/huaweidrive/huaweidrive.go @@ -33,6 +33,7 @@ import ( "github.com/rclone/rclone/lib/encoder" "github.com/rclone/rclone/lib/oauthutil" "github.com/rclone/rclone/lib/pacer" + "github.com/rclone/rclone/lib/readers" "github.com/rclone/rclone/lib/rest" "golang.org/x/oauth2" ) @@ -1771,11 +1772,18 @@ func (o *Object) uploadMultipart(ctx context.Context, in io.Reader, leaf, direct } // Read and write file content - _, err = io.Copy(fileWriter, in) + counter := readers.NewCountingReader(in) + _, err = io.Copy(fileWriter, counter) if err != nil { return fmt.Errorf("failed to copy file content: %w", err) } + // Check the source supplied the number of bytes it declared + // otherwise a truncated file would be stored as a good upload. + if int64(counter.BytesRead()) != size { + return fmt.Errorf("expected %d bytes in input, but got %d: %w", size, counter.BytesRead(), io.ErrUnexpectedEOF) + } + err = writer.Close() if err != nil { return fmt.Errorf("failed to close multipart writer: %w", err)