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. |
Hi @dineshchitlangia @pjfanning, thanks for the reviews and the approval! Since the CI is completely green and the requested changes have been addressed, could you please help get this merged? Let me know if there is anything else required from my end. |
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.