Skip to content

Commit 77c7997

Browse files
committed
Correct handling of references to invalid constant pool index 0.
Ensure that references to a constant pool entry with index zero trigger a ClassFormatException, not a NullPointerException.
1 parent 50afad5 commit 77c7997

4 files changed

Lines changed: 11 additions & 6 deletions

File tree

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ The <action> type attribute can be add,update,fix,remove.
6666
<!-- ADD -->
6767
<!-- FIX -->
6868
<action type="fix" dev="markt" due-to="OSS-Fuzz">When parsing an class with an invalid constant reference, ensure ClassParser.parse() throws ClassFormatException, not NullPointerException.</action>
69+
<action type="fix" dev="markt" due-to="OSS-Fuzz">Ensure that references to a constant pool entry with index zero trigger a ClassFormatException, not a NullPointerException.</action>
6970
<!-- UPDATE -->
7071
</release>
7172
<release version="6.7.0" date="2022-11-28" description="Maintenance and bug fix release.">

src/main/java/org/apache/bcel/classfile/ConstantPool.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public ConstantPool(final DataInput input) throws IOException {
8383
constantPool = new Constant[constantPoolCount];
8484
/*
8585
* constantPool[0] is unused by the compiler and may be used freely by the implementation.
86+
* constantPool[0] is currently unused by the implementation.
8687
*/
8788
for (int i = 1; i < constantPoolCount; i++) {
8889
constantPool[i] = Constant.readConstant(input);
@@ -300,7 +301,7 @@ public <T extends Constant> T getConstant(final int index, final byte tag, final
300301
* @since 6.6.0
301302
*/
302303
public <T extends Constant> T getConstant(final int index, final Class<T> castTo) throws ClassFormatException {
303-
if (index >= constantPool.length || index < 0) {
304+
if (index >= constantPool.length || index < 1) {
304305
throw new ClassFormatException("Invalid constant pool reference using index: " + index + ". Constant pool size is: " + constantPool.length);
305306
}
306307
if (constantPool[index] != null && !castTo.isAssignableFrom(constantPool[index].getClass())) {
@@ -309,9 +310,7 @@ public <T extends Constant> T getConstant(final int index, final Class<T> castTo
309310
}
310311
// Previous check ensures this won't throw a ClassCastException
311312
final T c = castTo.cast(constantPool[index]);
312-
if (c == null
313-
// the 0th element is always null
314-
&& index != 0) {
313+
if (c == null) {
315314
final Constant prev = constantPool[index - 1];
316315
if (prev == null || prev.getTag() != Const.CONSTANT_Double && prev.getTag() != Const.CONSTANT_Long) {
317316
throw new ClassFormatException("Constant pool at index " + index + " is null.");

src/test/java/org/apache/bcel/OssFuzzTestCase.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ public void testIssue53676() throws Exception {
6666
testOssFuzzReproducer("53676");
6767
}
6868

69+
@Test
70+
public void testIssue54119() throws Exception {
71+
testOssFuzzReproducer("54119");
72+
}
73+
6974
private void testOssFuzzReproducer(final String issue) throws Exception {
7075
final File reproducerFile = new File("target/test-classes/ossfuzz/issue" + issue + "/Test.class");
7176
try (final FileInputStream reproducerInputStream = new FileInputStream(reproducerFile)) {

src/test/java/org/apache/bcel/classfile/ConstantPoolTestCase.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public void testClassWithDoubleConstantPoolItem() throws ClassNotFoundException,
5959
assertEquals(1, fields.length);
6060
assertEquals(ClassWithDoubleConstantPoolItem.class.getDeclaredFields()[0].getName(), fields[0].getName());
6161
final ConstantPool pool = c.getConstantPool();
62-
IntStream.range(0, pool.getLength()).forEach(i -> assertDoesNotThrow(() -> {
62+
IntStream.range(1, pool.getLength()).forEach(i -> assertDoesNotThrow(() -> {
6363
final Constant constant = pool.getConstant(i);
6464
if (constant instanceof ConstantDouble) {
6565
assertEquals(classWithDoubleConstantPoolItem.d, ((ConstantDouble) constant).getBytes());
@@ -79,7 +79,7 @@ public void testClassWithLongConstantPoolItem() throws ClassNotFoundException, I
7979
assertEquals(1, fields.length);
8080
assertEquals(ClassWithLongConstantPoolItem.class.getDeclaredFields()[0].getName(), fields[0].getName());
8181
final ConstantPool pool = c.getConstantPool();
82-
IntStream.range(0, pool.getLength()).forEach(i -> assertDoesNotThrow(() -> {
82+
IntStream.range(1, pool.getLength()).forEach(i -> assertDoesNotThrow(() -> {
8383
final Constant constant = pool.getConstant(i);
8484
if (constant instanceof ConstantLong) {
8585
assertEquals(classWithLongConstantPoolItem.l, ((ConstantLong) constant).getBytes());

0 commit comments

Comments
 (0)