diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java index 67bdaa481d3..9b6c7d7ad4c 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java @@ -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. * * 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); } + private static IllegalArgumentException outOfBoundsError(IndexOutOfBoundsException cause) { + return new IllegalArgumentException("Reading beyond classfile bounds", cause); + } + @Override public int readU1(int p) { - return buffer[p] & 0xFF; + try { + return buffer[p] & 0xFF; + } catch (IndexOutOfBoundsException e) { + throw outOfBoundsError(e); + } } @Override public int readU2(int p) { - int b1 = buffer[p] & 0xFF; - int b2 = buffer[p + 1] & 0xFF; - return (b1 << 8) + b2; + try { + int b1 = buffer[p] & 0xFF; + int b2 = buffer[p + 1] & 0xFF; + return (b1 << 8) + b2; + } catch (IndexOutOfBoundsException e) { + throw outOfBoundsError(e); + } } @Override public int readS1(int p) { - return buffer[p]; + try { + return buffer[p]; + } catch (IndexOutOfBoundsException e) { + throw outOfBoundsError(e); + } } @Override public int readS2(int p) { - int b1 = buffer[p]; - int b2 = buffer[p + 1] & 0xFF; - return (b1 << 8) + b2; + try { + int b1 = buffer[p]; + int b2 = buffer[p + 1] & 0xFF; + return (b1 << 8) + b2; + } catch (IndexOutOfBoundsException e) { + throw outOfBoundsError(e); + } } @Override public int readInt(int p) { - int ch1 = buffer[p] & 0xFF; - int ch2 = buffer[p + 1] & 0xFF; - int ch3 = buffer[p + 2] & 0xFF; - int ch4 = buffer[p + 3] & 0xFF; - return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4; + try { + int ch1 = buffer[p] & 0xFF; + int ch2 = buffer[p + 1] & 0xFF; + int ch3 = buffer[p + 2] & 0xFF; + int ch4 = buffer[p + 3] & 0xFF; + return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4; + } catch (IndexOutOfBoundsException e) { + throw outOfBoundsError(e); + } } @Override public long readLong(int p) { - 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 + 4] & 255) << 24) + ((buffer[p + 5] & 255) << 16) + ((buffer[p + 6] & 255) << 8) + - (buffer[p + 7] & 255); + try { + 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 + 4] & 255) << 24) + ((buffer[p + 5] & 255) << 16) + ((buffer[p + 6] & 255) << 8) + + (buffer[p + 7] & 255); + } catch (IndexOutOfBoundsException e) { + throw outOfBoundsError(e); + } } @Override @@ -242,12 +270,20 @@ public final class ClassReaderImpl @Override public byte[] readBytes(int p, int len) { - return Arrays.copyOfRange(buffer, p, p + len); + try { + return Arrays.copyOfRange(buffer, p, p + len); + } catch (IndexOutOfBoundsException e) { + throw outOfBoundsError(e); + } } @Override public void copyBytesTo(BufWriter buf, int p, int len) { - buf.writeBytes(buffer, p, len); + try { + buf.writeBytes(buffer, p, len); + } catch (IndexOutOfBoundsException e) { + throw outOfBoundsError(e); + } } BootstrapMethodsAttribute bootstrapMethodsAttribute() { @@ -446,8 +482,12 @@ public final class ClassReaderImpl int bufWriterOffset, int classReaderOffset, int length) { - return Arrays.equals(((BufWriterImpl) bufWriter).elems, - bufWriterOffset, bufWriterOffset + length, - buffer, classReaderOffset, classReaderOffset + length); + try { + return Arrays.equals(((BufWriterImpl) bufWriter).elems, + bufWriterOffset, bufWriterOffset + length, + buffer, classReaderOffset, classReaderOffset + length); + } catch (IndexOutOfBoundsException e) { + throw outOfBoundsError(e); + } } } diff --git a/test/jdk/jdk/classfile/LimitsTest.java b/test/jdk/jdk/classfile/LimitsTest.java index b89a312a67f..d23a948fe9f 100644 --- a/test/jdk/jdk/classfile/LimitsTest.java +++ b/test/jdk/jdk/classfile/LimitsTest.java @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 8320360 * @summary Testing ClassFile limits. * @run junit LimitsTest */ @@ -85,4 +86,10 @@ class LimitsTest { var cf = ClassFile.of(); 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"); + } }