From 0deb2ef70b24ec5bb386a20ea831ffd84833432f Mon Sep 17 00:00:00 2001 From: Thomas Carmet <8408330+tcarmet@users.noreply.github.com> Date: Wed, 27 May 2026 17:32:44 -0700 Subject: [PATCH 1/3] CLDSRV-909: Reject CopyObject when source exceeds 5 GiB --- lib/api/objectCopy.js | 10 ++++++++ tests/unit/api/objectCopy.js | 47 +++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/lib/api/objectCopy.js b/lib/api/objectCopy.js index 02b0a31d5b..b504e1d9f6 100644 --- a/lib/api/objectCopy.js +++ b/lib/api/objectCopy.js @@ -351,6 +351,16 @@ function objectCopy(authInfo, request, sourceBucket, request.sourceServerAccessLog && (request.sourceServerAccessLog.error = err); return next(err, destBucketMD); } + const sourceSize = parseInt(sourceObjMD['content-length'], 10); + if (sourceSize > constants.maximumAllowedUploadSize) { + log.debug('copy source object too large', { sourceSize }); + const err = errorInstances.InvalidRequest.customizeDescription( + 'The specified copy source is larger than the maximum ' + + `allowable size for a copy source: ${constants.maximumAllowedUploadSize}`); + // eslint-disable-next-line no-param-reassign + request.sourceServerAccessLog && (request.sourceServerAccessLog.error = err); + return next(err, destBucketMD); + } const headerValResult = validateHeaders(request.headers, sourceObjMD['last-modified'], diff --git a/tests/unit/api/objectCopy.js b/tests/unit/api/objectCopy.js index 2448f3276f..533cbb038f 100644 --- a/tests/unit/api/objectCopy.js +++ b/tests/unit/api/objectCopy.js @@ -14,7 +14,8 @@ const { cleanup, DummyRequestLogger, makeAuthInfo, versioningTestUtils } const mpuUtils = require('../utils/mpuUtils'); const metadata = require('../metadataswitch'); const { data } = require('../../../lib/data/wrapper'); -const { objectLocationConstraintHeader } = require('../../../constants'); +const constants = require('../../../constants'); +const { objectLocationConstraintHeader } = constants; const { fakeMetadataArchive } = require('../../functional/aws-node-sdk/test/utils/init'); const { config } = require('../../../lib/Config'); @@ -640,3 +641,47 @@ describe('objectCopy with objectKeyByteLimit', () => { }); }); }); + +describe('objectCopy source size limit', () => { + const testPutObjectRequest = versioningTestUtils.createPutObjectRequest(sourceBucketName, objectKey, objData[0]); + const sourceSize = objData[0].length; + let originalMaximumUploadSize; + + before(done => { + cleanup(); + originalMaximumUploadSize = constants.maximumAllowedUploadSize; + async.series([ + callback => bucketPut(authInfo, putDestBucketRequest, log, callback), + callback => bucketPut(authInfo, putSourceBucketRequest, log, callback), + callback => objectPut(authInfo, testPutObjectRequest, undefined, log, callback), + ], done); + }); + + after(() => { + constants.maximumAllowedUploadSize = originalMaximumUploadSize; + cleanup(); + }); + + it('should allow CopyObject when source size equals the limit', done => { + constants.maximumAllowedUploadSize = sourceSize; + const testObjectCopyRequest = _createObjectCopyRequest(destBucketName); + objectCopy(authInfo, testObjectCopyRequest, sourceBucketName, objectKey, + undefined, log, err => { + assert.ifError(err); + done(); + }); + }); + + it('should reject CopyObject when source size exceeds the limit', done => { + constants.maximumAllowedUploadSize = sourceSize - 1; + const testObjectCopyRequest = _createObjectCopyRequest(destBucketName); + objectCopy(authInfo, testObjectCopyRequest, sourceBucketName, objectKey, + undefined, log, err => { + assert(err); + assert.strictEqual(err.is.InvalidRequest, true); + assert.match(err.description, + /The specified copy source is larger than the maximum allowable size for a copy source/); + done(); + }); + }); +}); From 5cec64fd9377cabb53c9f9d410a7919dd0404ce9 Mon Sep 17 00:00:00 2001 From: Thomas Carmet <8408330+tcarmet@users.noreply.github.com> Date: Mon, 1 Jun 2026 15:32:20 -0700 Subject: [PATCH 2/3] CLDSRV-909: Honor bypassMaxPutObjectSize flag on CopyObject size limit --- lib/api/objectCopy.js | 2 +- tests/unit/api/objectCopy.js | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/api/objectCopy.js b/lib/api/objectCopy.js index b504e1d9f6..b2133e3163 100644 --- a/lib/api/objectCopy.js +++ b/lib/api/objectCopy.js @@ -352,7 +352,7 @@ function objectCopy(authInfo, request, sourceBucket, return next(err, destBucketMD); } const sourceSize = parseInt(sourceObjMD['content-length'], 10); - if (sourceSize > constants.maximumAllowedUploadSize) { + if (sourceSize > constants.maximumAllowedUploadSize && !config.bypassMaxPutObjectSize) { log.debug('copy source object too large', { sourceSize }); const err = errorInstances.InvalidRequest.customizeDescription( 'The specified copy source is larger than the maximum ' + diff --git a/tests/unit/api/objectCopy.js b/tests/unit/api/objectCopy.js index 533cbb038f..2caa6ae894 100644 --- a/tests/unit/api/objectCopy.js +++ b/tests/unit/api/objectCopy.js @@ -659,6 +659,7 @@ describe('objectCopy source size limit', () => { after(() => { constants.maximumAllowedUploadSize = originalMaximumUploadSize; + config.bypassMaxPutObjectSize = false; cleanup(); }); @@ -684,4 +685,15 @@ describe('objectCopy source size limit', () => { done(); }); }); + + it('should allow CopyObject when source size exceeds the limit but bypass flag is set', done => { + constants.maximumAllowedUploadSize = sourceSize - 1; + config.bypassMaxPutObjectSize = true; + const testObjectCopyRequest = _createObjectCopyRequest(destBucketName); + objectCopy(authInfo, testObjectCopyRequest, sourceBucketName, objectKey, + undefined, log, err => { + assert.ifError(err); + done(); + }); + }); }); From 636984c3521b314a927dcae45e4e9316770bc2b7 Mon Sep 17 00:00:00 2001 From: Thomas Carmet <8408330+tcarmet@users.noreply.github.com> Date: Fri, 5 Jun 2026 12:34:55 -0700 Subject: [PATCH 3/3] CLDSRV-909: Use plain if for sourceServerAccessLog error assignment --- lib/api/objectCopy.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/api/objectCopy.js b/lib/api/objectCopy.js index b2133e3163..a3026385e3 100644 --- a/lib/api/objectCopy.js +++ b/lib/api/objectCopy.js @@ -357,8 +357,10 @@ function objectCopy(authInfo, request, sourceBucket, const err = errorInstances.InvalidRequest.customizeDescription( 'The specified copy source is larger than the maximum ' + `allowable size for a copy source: ${constants.maximumAllowedUploadSize}`); - // eslint-disable-next-line no-param-reassign - request.sourceServerAccessLog && (request.sourceServerAccessLog.error = err); + if (request.sourceServerAccessLog) { + // eslint-disable-next-line no-param-reassign + request.sourceServerAccessLog.error = err; + } return next(err, destBucketMD); } const headerValResult =