8320360: ClassFile.parse: Some defect class files cause unexpected exceptions to be thrown

Reviewed-by: jpai
This commit is contained in:
Adam Sotona 2024-01-02 12:58:53 +00:00
parent f9aec02f3c
commit a5cf4210cd
2 changed files with 71 additions and 24 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -189,45 +189,73 @@ public final class ClassReaderImpl
return bsmEntries().get(index); return bsmEntries().get(index);
} }
private static IllegalArgumentException outOfBoundsError(IndexOutOfBoundsException cause) {
return new IllegalArgumentException("Reading beyond classfile bounds", cause);
}
@Override @Override
public int readU1(int p) { public int readU1(int p) {
try {
return buffer[p] & 0xFF; return buffer[p] & 0xFF;
} catch (IndexOutOfBoundsException e) {
throw outOfBoundsError(e);
}
} }
@Override @Override
public int readU2(int p) { public int readU2(int p) {
try {
int b1 = buffer[p] & 0xFF; int b1 = buffer[p] & 0xFF;
int b2 = buffer[p + 1] & 0xFF; int b2 = buffer[p + 1] & 0xFF;
return (b1 << 8) + b2; return (b1 << 8) + b2;
} catch (IndexOutOfBoundsException e) {
throw outOfBoundsError(e);
}
} }
@Override @Override
public int readS1(int p) { public int readS1(int p) {
try {
return buffer[p]; return buffer[p];
} catch (IndexOutOfBoundsException e) {
throw outOfBoundsError(e);
}
} }
@Override @Override
public int readS2(int p) { public int readS2(int p) {
try {
int b1 = buffer[p]; int b1 = buffer[p];
int b2 = buffer[p + 1] & 0xFF; int b2 = buffer[p + 1] & 0xFF;
return (b1 << 8) + b2; return (b1 << 8) + b2;
} catch (IndexOutOfBoundsException e) {
throw outOfBoundsError(e);
}
} }
@Override @Override
public int readInt(int p) { public int readInt(int p) {
try {
int ch1 = buffer[p] & 0xFF; int ch1 = buffer[p] & 0xFF;
int ch2 = buffer[p + 1] & 0xFF; int ch2 = buffer[p + 1] & 0xFF;
int ch3 = buffer[p + 2] & 0xFF; int ch3 = buffer[p + 2] & 0xFF;
int ch4 = buffer[p + 3] & 0xFF; int ch4 = buffer[p + 3] & 0xFF;
return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4; return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4;
} catch (IndexOutOfBoundsException e) {
throw outOfBoundsError(e);
}
} }
@Override @Override
public long readLong(int p) { public long readLong(int p) {
try {
return ((long) buffer[p + 0] << 56) + ((long) (buffer[p + 1] & 255) << 48) + return ((long) buffer[p + 0] << 56) + ((long) (buffer[p + 1] & 255) << 48) +
((long) (buffer[p + 2] & 255) << 40) + ((long) (buffer[p + 3] & 255) << 32) + ((long) (buffer[p + 2] & 255) << 40) + ((long) (buffer[p + 3] & 255) << 32) +
((long) (buffer[p + 4] & 255) << 24) + ((buffer[p + 5] & 255) << 16) + ((buffer[p + 6] & 255) << 8) + ((long) (buffer[p + 4] & 255) << 24) + ((buffer[p + 5] & 255) << 16) + ((buffer[p + 6] & 255) << 8) +
(buffer[p + 7] & 255); (buffer[p + 7] & 255);
} catch (IndexOutOfBoundsException e) {
throw outOfBoundsError(e);
}
} }
@Override @Override
@ -242,12 +270,20 @@ public final class ClassReaderImpl
@Override @Override
public byte[] readBytes(int p, int len) { public byte[] readBytes(int p, int len) {
try {
return Arrays.copyOfRange(buffer, p, p + len); return Arrays.copyOfRange(buffer, p, p + len);
} catch (IndexOutOfBoundsException e) {
throw outOfBoundsError(e);
}
} }
@Override @Override
public void copyBytesTo(BufWriter buf, int p, int len) { public void copyBytesTo(BufWriter buf, int p, int len) {
try {
buf.writeBytes(buffer, p, len); buf.writeBytes(buffer, p, len);
} catch (IndexOutOfBoundsException e) {
throw outOfBoundsError(e);
}
} }
BootstrapMethodsAttribute bootstrapMethodsAttribute() { BootstrapMethodsAttribute bootstrapMethodsAttribute() {
@ -446,8 +482,12 @@ public final class ClassReaderImpl
int bufWriterOffset, int bufWriterOffset,
int classReaderOffset, int classReaderOffset,
int length) { int length) {
try {
return Arrays.equals(((BufWriterImpl) bufWriter).elems, return Arrays.equals(((BufWriterImpl) bufWriter).elems,
bufWriterOffset, bufWriterOffset + length, bufWriterOffset, bufWriterOffset + length,
buffer, classReaderOffset, classReaderOffset + length); buffer, classReaderOffset, classReaderOffset + length);
} catch (IndexOutOfBoundsException e) {
throw outOfBoundsError(e);
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,6 +23,7 @@
/* /*
* @test * @test
* @bug 8320360
* @summary Testing ClassFile limits. * @summary Testing ClassFile limits.
* @run junit LimitsTest * @run junit LimitsTest
*/ */
@ -85,4 +86,10 @@ class LimitsTest {
var cf = ClassFile.of(); var cf = ClassFile.of();
assertThrows(IllegalArgumentException.class, () -> cf.parse(cf.build(ClassDesc.of("ClassFromFuture"), cb -> cb.withVersion(ClassFile.latestMajorVersion() + 1, 0)))); assertThrows(IllegalArgumentException.class, () -> cf.parse(cf.build(ClassDesc.of("ClassFromFuture"), cb -> cb.withVersion(ClassFile.latestMajorVersion() + 1, 0))));
} }
@Test
void testReadingOutOfBounds() {
assertThrows(IllegalArgumentException.class, () -> ClassFile.of().parse(new byte[]{(byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE}), "reading magic only");
assertThrows(IllegalArgumentException.class, () -> ClassFile.of().parse(new byte[]{(byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE, 0, 0, 0, 0, 0, 2}), "reading invalid CP size");
}
} }