HADOOP-18896. NegativeArraySizeException thrown in FSOutputSummer.jav…#8622
HADOOP-18896. NegativeArraySizeException thrown in FSOutputSummer.jav…#8622anshuksi282-ksolves wants to merge 2 commits into
Conversation
…a given large file.bytes-per-checksum
|
Hi all, I'm new to contributing to Hadoop, so please let me know if any changes are needed. Thanks in advance! cc: @ayushtkn @dineshchitlangia @brahmareddybattula @pjfanning @slfan1989 |
| protected FSOutputSummer(DataChecksum sum) { | ||
| this.sum = sum; | ||
| Preconditions.checkArgument( | ||
| sum.getBytesPerChecksum() * BUFFER_NUM_CHUNKS > 0, |
There was a problem hiding this comment.
I would do something like:
int bufArraySize;
try {
bufArraySize = Math.multiplyExact(sum.getBytesPerChecksum(), BUFFER_NUM_CHUNKS);
} catch (ArithmeticException ae) {
throw new IllegalArgumentException("The calculated buffer array size for FSOutputSummer is too large", ae);
}
if (bufArraySize < 0) {
throw new IllegalArgumentException("The calculated buffer array size for FSOutputSummer is negative");
}
this.buf = new byte[bufArraySize];
I would suggest that you also check the array size in a similar way for this.checksum.
There was a problem hiding this comment.
Thanks for the review @pjfanning!
Updated to use Math.multiplyExact for both buf and checksum buffer size checks, as suggested.
I did try adding a dedicated test for the checksum buffer overflow path, but getChecksumSize() returns a fixed value from DataChecksum.Type (e.g. 4 for CRC32), so it can never actually be large enough to overflow — that path isn't reachable in practice, just defensive. So I've kept the existing unit test covering the buf overflow case, and re-ran TestFSOutputSummer, TestChecksumFileSystem, and TestChecksumFs to confirm no regressions.
|
🎊 +1 overall
This message was automatically generated. |
|
🎊 +1 overall
This message was automatically generated. |
Description of PR
This PR fixes HADOOP-18896.
The buffer size in
FSOutputSummeris computed assum.getBytesPerChecksum() * BUFFER_NUM_CHUNKS. Whenfile.bytes-per-checksumis configured to a very large value (e.g. 238609295), this multiplication overflows a signed 32-bit int and wraps around to a negative number, causing aNegativeArraySizeExceptionwhen allocating the internal buffer array.This PR adds a
Preconditions.checkArgumentcheck in theFSOutputSummerconstructor to validate that the computed buffer size is positive, failing fast with a clearIllegalArgumentExceptioninstead of an obscureNegativeArraySizeException.This continues the work started in #6064 by @teamconfx, which went stale. This PR additionally adds a unit test, as the original PR's
test4testscheck had failed for not including one.How was this patch tested?
TestFSOutputSummerinhadoop-commonwithtestLargeBytesPerChecksumOverflow, using a minimal concrete subclass ofFSOutputSummerto verify the constructor fails withIllegalArgumentException(rather thanNegativeArraySizeException) whenbytesPerChecksum * BUFFER_NUM_CHUNKSoverflows.NegativeArraySizeExceptionwhen the fix is reverted, and passes with the fix applied.mvn -pl hadoop-common-project/hadoop-common test -Dtest=TestFSOutputSummerpasses.Note: the JIRA's original reproduction steps reference an HDFS test (
TestDecommissionWithStriped), but since the buffer overflow bug lives entirely inhadoop-common'sFSOutputSummerclass, this PR adds a focused unit test inhadoop-commoninstead, avoiding an unnecessary cross-module HDFS test dependency.AI Tooling
Contains content generated by Claude (Anthropic). Used to help investigate the root cause, draft the fix, and write/verify the accompanying unit test.