Skip to content

Commit bd37fce

Browse files
committed
Fix partNumber path traversal warnings
This doesn't change the logic but makes static code analysis happy.
1 parent 53b9529 commit bd37fce

File tree

4 files changed

+37
-27
lines changed

4 files changed

+37
-27
lines changed

server/src/main/java/com/adobe/testing/s3mock/MultipartController.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -229,14 +229,14 @@ public ResponseEntity<Void> uploadPart(
229229
@PathVariable String bucketName,
230230
@PathVariable ObjectKey key,
231231
@RequestParam UUID uploadId,
232-
@RequestParam Integer partNumber,
232+
@RequestParam String partNumber,
233233
@RequestHeader HttpHeaders httpHeaders,
234234
InputStream inputStream) {
235235

236236
final var tempFileAndChecksum = multipartService.toTempFile(inputStream, httpHeaders);
237237
bucketService.verifyBucketExists(bucketName);
238238
multipartService.verifyMultipartUploadExists(bucketName, uploadId);
239-
multipartService.verifyPartNumberLimits(partNumber);
239+
var partNum = multipartService.verifyPartNumberLimits(partNumber);
240240

241241
String checksum = null;
242242
ChecksumAlgorithm checksumAlgorithm = null;
@@ -260,7 +260,7 @@ public ResponseEntity<Void> uploadPart(
260260
var etag = multipartService.putPart(bucketName,
261261
key.key(),
262262
uploadId,
263-
partNumber,
263+
partNum,
264264
tempFile,
265265
encryptionHeadersFrom(httpHeaders));
266266

@@ -299,10 +299,10 @@ public ResponseEntity<CopyPartResult> uploadPartCopy(
299299
@RequestHeader(value = X_AMZ_COPY_SOURCE_IF_MODIFIED_SINCE, required = false) List<Instant> ifModifiedSince,
300300
@RequestHeader(value = X_AMZ_COPY_SOURCE_IF_UNMODIFIED_SINCE, required = false) List<Instant> ifUnmodifiedSince,
301301
@RequestParam UUID uploadId,
302-
@RequestParam Integer partNumber,
302+
@RequestParam String partNumber,
303303
@RequestHeader HttpHeaders httpHeaders) {
304304
var bucket = bucketService.verifyBucketExists(bucketName);
305-
multipartService.verifyPartNumberLimits(partNumber);
305+
var partNum = multipartService.verifyPartNumberLimits(partNumber);
306306
var s3ObjectMetadata = objectService.verifyObjectExists(copySource.bucket(), copySource.key(),
307307
copySource.versionId());
308308
objectService.verifyObjectMatchingForCopy(match, noneMatch,
@@ -312,7 +312,7 @@ public ResponseEntity<CopyPartResult> uploadPartCopy(
312312
var result = multipartService.copyPart(copySource.bucket(),
313313
copySource.key(),
314314
copyRange,
315-
partNumber,
315+
partNum,
316316
bucketName,
317317
key.key(),
318318
uploadId,

server/src/main/java/com/adobe/testing/s3mock/service/MultipartService.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -310,11 +310,13 @@ public ListMultipartUploadsResult listMultipartUploads(
310310
);
311311
}
312312

313-
public void verifyPartNumberLimits(Integer partNumber) {
314-
if (partNumber < 1 || partNumber > 10000) {
313+
public int verifyPartNumberLimits(String partNumber) {
314+
int number = Integer.parseInt(partNumber);
315+
if (number < 1 || number > 10000) {
315316
LOG.error("Multipart part number invalid. partNumber={}", partNumber);
316317
throw INVALID_PART_NUMBER;
317318
}
319+
return number;
318320
}
319321

320322
public void verifyMultipartParts(
@@ -364,7 +366,7 @@ public void verifyMultipartParts(
364366
if (!uploadedParts.isEmpty()) {
365367
for (int i = 0; i < uploadedParts.size() - 1; i++) {
366368
var part = uploadedParts.get(i);
367-
verifyPartNumberLimits(part.partNumber());
369+
verifyPartNumberLimits(part.partNumber().toString());
368370
if (part.size() < MINIMUM_PART_SIZE) {
369371
LOG.error("Multipart part size too small. bucket={}, id={}, uploadId={}, size={}",
370372
bucketMetadata, id, uploadId, part.size());

server/src/test/kotlin/com/adobe/testing/s3mock/MultipartControllerTest.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,7 @@ internal class MultipartControllerTest : BaseControllerTest() {
10471047
fun testUploadPart_Ok_EtagReturned() {
10481048
val bucketMeta = bucketMetadata()
10491049
whenever(bucketService.verifyBucketExists(TEST_BUCKET_NAME)).thenReturn(bucketMeta)
1050+
whenever(multipartService.verifyPartNumberLimits("1")).thenReturn(1)
10501051
val uploadId = UUID.randomUUID()
10511052

10521053
val temp = java.nio.file.Files.createTempFile("junie", "part")
@@ -1080,6 +1081,7 @@ internal class MultipartControllerTest : BaseControllerTest() {
10801081
)
10811082
val bucketMeta = bucketMetadata(versioningConfiguration = versioningConfiguration)
10821083
whenever(bucketService.verifyBucketExists(TEST_BUCKET_NAME)).thenReturn(bucketMeta)
1084+
whenever(multipartService.verifyPartNumberLimits("1")).thenReturn(1)
10831085

10841086
val s3meta = s3ObjectMetadata(
10851087
key = "source/key.txt",
@@ -1161,10 +1163,11 @@ internal class MultipartControllerTest : BaseControllerTest() {
11611163
fun testUploadPartCopy_InvalidPartNumber_BadRequest() {
11621164
val bucketMeta = bucketMetadata()
11631165
whenever(bucketService.verifyBucketExists(TEST_BUCKET_NAME)).thenReturn(bucketMeta)
1166+
whenever(multipartService.verifyPartNumberLimits("1")).thenReturn(1)
11641167

11651168
doThrow(S3Exception.INVALID_PART_NUMBER)
11661169
.whenever(multipartService)
1167-
.verifyPartNumberLimits(1)
1170+
.verifyPartNumberLimits("1")
11681171

11691172
val headers = HttpHeaders().apply {
11701173
add("x-amz-copy-source", "/source-bucket/source/key.txt")
@@ -1190,6 +1193,7 @@ internal class MultipartControllerTest : BaseControllerTest() {
11901193
fun testUploadPartCopy_SourceObjectNotFound() {
11911194
val bucketMeta = bucketMetadata()
11921195
whenever(bucketService.verifyBucketExists(TEST_BUCKET_NAME)).thenReturn(bucketMeta)
1196+
whenever(multipartService.verifyPartNumberLimits("1")).thenReturn(1)
11931197

11941198
doThrow(S3Exception.NO_SUCH_KEY)
11951199
.whenever(objectService)
@@ -1219,6 +1223,7 @@ internal class MultipartControllerTest : BaseControllerTest() {
12191223
fun testUploadPartCopy_PreconditionFailed() {
12201224
val bucketMeta = bucketMetadata()
12211225
whenever(bucketService.verifyBucketExists(TEST_BUCKET_NAME)).thenReturn(bucketMeta)
1226+
whenever(multipartService.verifyPartNumberLimits("1")).thenReturn(1)
12221227

12231228
val s3meta = s3ObjectMetadata("source/key.txt", UUID.randomUUID().toString())
12241229
whenever(objectService.verifyObjectExists(eq("source-bucket"), eq("source/key.txt"), anyOrNull()))
@@ -1260,6 +1265,7 @@ internal class MultipartControllerTest : BaseControllerTest() {
12601265
fun testUploadPartCopy_NoVersionHeaderWhenNotVersioned() {
12611266
val bucketMeta = bucketMetadata()
12621267
whenever(bucketService.verifyBucketExists(TEST_BUCKET_NAME)).thenReturn(bucketMeta)
1268+
whenever(multipartService.verifyPartNumberLimits("1")).thenReturn(1)
12631269

12641270
val s3meta = s3ObjectMetadata(
12651271
key = "source/key.txt",
@@ -1300,6 +1306,7 @@ internal class MultipartControllerTest : BaseControllerTest() {
13001306
fun testUploadPartCopy_EncryptionHeadersEchoed() {
13011307
val bucketMeta = bucketMetadata()
13021308
whenever(bucketService.verifyBucketExists(TEST_BUCKET_NAME)).thenReturn(bucketMeta)
1309+
whenever(multipartService.verifyPartNumberLimits("1")).thenReturn(1)
13031310

13041311
val s3meta = s3ObjectMetadata("source/key.txt", UUID.randomUUID().toString())
13051312
whenever(objectService.verifyObjectExists(eq("source-bucket"), eq("source/key.txt"), anyOrNull()))
@@ -1348,6 +1355,7 @@ internal class MultipartControllerTest : BaseControllerTest() {
13481355
fun testUploadPart_WithHeaderChecksum_VerifiedAndReturned() {
13491356
val bucketMeta = bucketMetadata()
13501357
whenever(bucketService.verifyBucketExists(TEST_BUCKET_NAME)).thenReturn(bucketMeta)
1358+
whenever(multipartService.verifyPartNumberLimits("1")).thenReturn(1)
13511359
val uploadId = UUID.randomUUID()
13521360

13531361
val temp = java.nio.file.Files.createTempFile("junie", "part")
@@ -1395,7 +1403,7 @@ internal class MultipartControllerTest : BaseControllerTest() {
13951403
// Simulate invalid part number
13961404
doThrow(S3Exception.INVALID_PART_NUMBER)
13971405
.whenever(multipartService)
1398-
.verifyPartNumberLimits(1)
1406+
.verifyPartNumberLimits("1")
13991407

14001408
val uri = UriComponentsBuilder
14011409
.fromUriString("/${TEST_BUCKET_NAME}/my/key.txt")

server/src/test/kotlin/com/adobe/testing/s3mock/service/MultipartServiceTest.kt

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,33 @@ internal class MultipartServiceTest : ServiceTestBase() {
4444

4545
@Test
4646
fun testVerifyPartNumberLimits_success() {
47-
val partNumber = 1
47+
val partNumber = "1"
4848
iut.verifyPartNumberLimits(partNumber)
4949
}
5050

5151
@Test
5252
fun testVerifyPartNumberLimits_tooSmallFailure() {
53-
val partNumber = 0
53+
val partNumber = "0"
5454
assertThatThrownBy { iut.verifyPartNumberLimits(partNumber) }
5555
.isEqualTo(S3Exception.INVALID_PART_NUMBER)
5656
}
5757

5858
@Test
5959
fun testVerifyPartNumberLimits_tooLargeFailure() {
60-
val partNumber = 10001
60+
val partNumber = "10001"
61+
assertThatThrownBy { iut.verifyPartNumberLimits(partNumber) }
62+
.isEqualTo(S3Exception.INVALID_PART_NUMBER)
63+
}
64+
65+
@Test
66+
fun testVerifyPartNumberLimits_boundaryMax_success() {
67+
val partNumber = "10000"
68+
iut.verifyPartNumberLimits(partNumber)
69+
}
70+
71+
@Test
72+
fun testVerifyPartNumberLimits_negativeNumberFailure() {
73+
val partNumber = "-1"
6174
assertThatThrownBy { iut.verifyPartNumberLimits(partNumber) }
6275
.isEqualTo(S3Exception.INVALID_PART_NUMBER)
6376
}
@@ -203,19 +216,6 @@ internal class MultipartServiceTest : ServiceTestBase() {
203216
iut.verifyMultipartUploadExists(bucketName, uploadId)
204217
}
205218

206-
@Test
207-
fun testVerifyPartNumberLimits_boundaryMax_success() {
208-
val partNumber = 10000
209-
iut.verifyPartNumberLimits(partNumber)
210-
}
211-
212-
@Test
213-
fun testVerifyPartNumberLimits_negativeNumberFailure() {
214-
val partNumber = -1
215-
assertThatThrownBy { iut.verifyPartNumberLimits(partNumber) }
216-
.isEqualTo(S3Exception.INVALID_PART_NUMBER)
217-
}
218-
219219
@Test
220220
fun testVerifyMultipartParts_withRequestedParts_keyNotFoundFailure() {
221221
val bucketName = "bucketName"

0 commit comments

Comments
 (0)