Skip to content

Commit 4b8922f

Browse files
committed
8308842: Consolidate exceptions thrown from Class-File API
Reviewed-by: briangoetz
1 parent 2b38343 commit 4b8922f

15 files changed

+147
-64
lines changed

src/java.base/share/classes/jdk/internal/classfile/ClassReader.java

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import jdk.internal.classfile.constantpool.ClassEntry;
2828
import jdk.internal.classfile.constantpool.ConstantPool;
29+
import jdk.internal.classfile.constantpool.ConstantPoolException;
2930
import jdk.internal.classfile.constantpool.MethodHandleEntry;
3031
import jdk.internal.classfile.constantpool.ModuleEntry;
3132
import jdk.internal.classfile.constantpool.NameAndTypeEntry;
@@ -96,7 +97,7 @@ public sealed interface ClassReader extends ConstantPool
9697
* {@return the constant pool entry whose index is given at the specified
9798
* offset within the classfile}
9899
* @param offset the offset of the index within the classfile
99-
* @throws IndexOutOfBoundsException if the index is out of range of the
100+
* @throws ConstantPoolException if the index is out of range of the
100101
* constant pool size, or zero
101102
*/
102103
PoolEntry readEntry(int offset);
@@ -106,7 +107,7 @@ public sealed interface ClassReader extends ConstantPool
106107
* offset within the classfile, or null if the index at the specified
107108
* offset is zero}
108109
* @param offset the offset of the index within the classfile
109-
* @throws IndexOutOfBoundsException if the index is out of range of the
110+
* @throws ConstantPoolException if the index is out of range of the
110111
* constant pool size
111112
*/
112113
PoolEntry readEntryOrNull(int offset);
@@ -115,9 +116,8 @@ public sealed interface ClassReader extends ConstantPool
115116
* {@return the UTF8 entry whose index is given at the specified
116117
* offset within the classfile}
117118
* @param offset the offset of the index within the classfile
118-
* @throws IndexOutOfBoundsException if the index is out of range of the
119-
* constant pool size, or zero
120-
* @throws IllegalArgumentException if the index does not correspond to
119+
* @throws ConstantPoolException if the index is out of range of the
120+
* constant pool size, or zero, or the index does not correspond to
121121
* a UTF8 entry
122122
*/
123123
Utf8Entry readUtf8Entry(int offset);
@@ -127,9 +127,8 @@ public sealed interface ClassReader extends ConstantPool
127127
* offset within the classfile, or null if the index at the specified
128128
* offset is zero}
129129
* @param offset the offset of the index within the classfile
130-
* @throws IndexOutOfBoundsException if the index is out of range of the
131-
* constant pool size
132-
* @throws IllegalArgumentException if the index does not correspond to
130+
* @throws ConstantPoolException if the index is out of range of the
131+
* constant pool size, or the index does not correspond to
133132
* a UTF8 entry
134133
*/
135134
Utf8Entry readUtf8EntryOrNull(int offset);
@@ -138,9 +137,8 @@ public sealed interface ClassReader extends ConstantPool
138137
* {@return the module entry whose index is given at the specified
139138
* offset within the classfile}
140139
* @param offset the offset of the index within the classfile
141-
* @throws IndexOutOfBoundsException if the index is out of range of the
142-
* constant pool size, or zero
143-
* @throws IllegalArgumentException if the index does not correspond to
140+
* @throws ConstantPoolException if the index is out of range of the
141+
* constant pool size, or zero, or the index does not correspond to
144142
* a module entry
145143
*/
146144
ModuleEntry readModuleEntry(int offset);
@@ -149,9 +147,8 @@ public sealed interface ClassReader extends ConstantPool
149147
* {@return the package entry whose index is given at the specified
150148
* offset within the classfile}
151149
* @param offset the offset of the index within the classfile
152-
* @throws IndexOutOfBoundsException if the index is out of range of the
153-
* constant pool size, or zero
154-
* @throws IllegalArgumentException if the index does not correspond to
150+
* @throws ConstantPoolException if the index is out of range of the
151+
* constant pool size, or zero, or the index does not correspond to
155152
* a package entry
156153
*/
157154
PackageEntry readPackageEntry(int offset);
@@ -160,9 +157,8 @@ public sealed interface ClassReader extends ConstantPool
160157
* {@return the class entry whose index is given at the specified
161158
* offset within the classfile}
162159
* @param offset the offset of the index within the classfile
163-
* @throws IndexOutOfBoundsException if the index is out of range of the
164-
* constant pool size, or zero
165-
* @throws IllegalArgumentException if the index does not correspond to
160+
* @throws ConstantPoolException if the index is out of range of the
161+
* constant pool size, or zero, or the index does not correspond to
166162
* a class entry
167163
*/
168164
ClassEntry readClassEntry(int offset);
@@ -171,9 +167,8 @@ public sealed interface ClassReader extends ConstantPool
171167
* {@return the name-and-type entry whose index is given at the specified
172168
* offset within the classfile}
173169
* @param offset the offset of the index within the classfile
174-
* @throws IndexOutOfBoundsException if the index is out of range of the
175-
* constant pool size, or zero
176-
* @throws IllegalArgumentException if the index does not correspond to
170+
* @throws ConstantPoolException if the index is out of range of the
171+
* constant pool size, or zero, or the index does not correspond to
177172
* a name-and-type entry
178173
*/
179174
NameAndTypeEntry readNameAndTypeEntry(int offset);
@@ -182,9 +177,8 @@ public sealed interface ClassReader extends ConstantPool
182177
* {@return the method handle entry whose index is given at the specified
183178
* offset within the classfile}
184179
* @param offset the offset of the index within the classfile
185-
* @throws IndexOutOfBoundsException if the index is out of range of the
186-
* constant pool size, or zero
187-
* @throws IllegalArgumentException if the index does not correspond to
180+
* @throws ConstantPoolException if the index is out of range of the
181+
* constant pool size, or zero, or the index does not correspond to
188182
* a method handle entry
189183
*/
190184
MethodHandleEntry readMethodHandleEntry(int offset);

src/java.base/share/classes/jdk/internal/classfile/Classfile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ public sealed interface Option permits Options.OptionValue {
143143

144144
/**
145145
* {@return an option describing whether or not to filter unresolved labels}
146-
* Default is to throw IllegalStateException when any {@link ExceptionCatch},
146+
* Default is to throw IllegalArgumentException when any {@link ExceptionCatch},
147147
* {@link LocalVariableInfo}, {@link LocalVariableTypeInfo}, or {@link CharacterRangeInfo}
148148
* reference to unresolved {@link Label} during bytecode serialization.
149149
* Setting this option to true filters the above elements instead.

src/java.base/share/classes/jdk/internal/classfile/CodeBuilder.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ default CodeBuilder ifThen(Consumer<BlockCodeBuilder> thenHandler) {
234234
* @param thenHandler handler that receives a {@linkplain BlockCodeBuilder} to
235235
* generate the body of the {@code if}
236236
* @return this builder
237-
* @throws java.lang.IllegalArgumentException if the operation code is not for a branch instruction that accepts
237+
* @throws IllegalArgumentException if the operation code is not for a branch instruction that accepts
238238
* one or two operands
239239
*/
240240
default CodeBuilder ifThen(Opcode opcode,
@@ -284,7 +284,7 @@ default CodeBuilder ifThenElse(Consumer<BlockCodeBuilder> thenHandler,
284284
* @param elseHandler handler that receives a {@linkplain BlockCodeBuilder} to
285285
* generate the body of the {@code else}
286286
* @return this builder
287-
* @throws java.lang.IllegalArgumentException if the operation code is not for a branch instruction that accepts
287+
* @throws IllegalArgumentException if the operation code is not for a branch instruction that accepts
288288
* one or two operands
289289
*/
290290
default CodeBuilder ifThenElse(Opcode opcode,
@@ -327,7 +327,7 @@ sealed interface CatchBuilder permits CatchBuilderImpl {
327327
* @param catchHandler handler that receives a {@linkplain CodeBuilder} to
328328
* generate the body of the catch block.
329329
* @return this builder
330-
* @throws java.lang.IllegalArgumentException if an existing catch block catches an exception of the given type.
330+
* @throws IllegalArgumentException if an existing catch block catches an exception of the given type.
331331
* @see #catchingMulti
332332
* @see #catchingAll
333333
*/
@@ -344,7 +344,7 @@ sealed interface CatchBuilder permits CatchBuilderImpl {
344344
* @param catchHandler handler that receives a {@linkplain CodeBuilder} to
345345
* generate the body of the catch block.
346346
* @return this builder
347-
* @throws java.lang.IllegalArgumentException if an existing catch block catches one or more exceptions of the given types.
347+
* @throws IllegalArgumentException if an existing catch block catches one or more exceptions of the given types.
348348
* @see #catching
349349
* @see #catchingAll
350350
*/
@@ -357,7 +357,7 @@ sealed interface CatchBuilder permits CatchBuilderImpl {
357357
*
358358
* @param catchAllHandler handler that receives a {@linkplain CodeBuilder} to
359359
* generate the body of the catch block
360-
* @throws java.lang.IllegalArgumentException if an existing catch block catches all exceptions.
360+
* @throws IllegalArgumentException if an existing catch block catches all exceptions.
361361
* @see #catching
362362
* @see #catchingMulti
363363
*/
@@ -373,6 +373,7 @@ sealed interface CatchBuilder permits CatchBuilderImpl {
373373
* @param catchesHandler a handler that receives a {@linkplain CatchBuilder}
374374
* to generate bodies of catch blocks.
375375
* @return this builder
376+
* @throws IllegalArgumentException if the try block is empty.
376377
* @see CatchBuilder
377378
*/
378379
default CodeBuilder trying(Consumer<BlockCodeBuilder> tryHandler,
@@ -386,7 +387,7 @@ default CodeBuilder trying(Consumer<BlockCodeBuilder> tryHandler,
386387

387388
// Check for empty try block
388389
if (tryBlock.isEmpty()) {
389-
throw new IllegalStateException("The body of the try block is empty");
390+
throw new IllegalArgumentException("The body of the try block is empty");
390391
}
391392

392393
var catchBuilder = new CatchBuilderImpl(this, tryBlock, tryCatchEnd);
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.internal.classfile.constantpool;
26+
27+
/**
28+
* Thrown to indicate that requested entry cannot be obtained from the constant
29+
* pool.
30+
*/
31+
public class ConstantPoolException extends IllegalArgumentException {
32+
33+
@java.io.Serial
34+
private static final long serialVersionUID = 7245472922409094120L;
35+
36+
/**
37+
* Constructs a {@code ConstantPoolException} with no detail message.
38+
*/
39+
public ConstantPoolException() {
40+
super();
41+
}
42+
43+
/**
44+
* Constructs a {@code ConstantPoolException} with the specified detail
45+
* message.
46+
*
47+
* @param message the detail message.
48+
*/
49+
public ConstantPoolException(String message) {
50+
super(message);
51+
}
52+
53+
/**
54+
* Constructs a {@code ConstantPoolException} with the specified cause and
55+
* a detail message of {@code (cause==null ? null : cause.toString())}.
56+
* @param cause the cause (which is saved for later retrieval by the
57+
* {@link Throwable#getCause()} method). (A {@code null} value is
58+
* permitted, and indicates that the cause is nonexistent or
59+
* unknown.)
60+
*/
61+
public ConstantPoolException(Throwable cause) {
62+
super(cause);
63+
}
64+
65+
/**
66+
* Constructs a {@code ConstantPoolException} with the specified detail
67+
* message and cause.
68+
*
69+
* @param message the detail message (which is saved for later retrieval
70+
* by the {@link Throwable#getMessage()} method).
71+
* @param cause the cause (which is saved for later retrieval by the
72+
* {@link Throwable#getCause()} method). (A {@code null} value
73+
* is permitted, and indicates that the cause is nonexistent or
74+
* unknown.)
75+
*/
76+
public ConstantPoolException(String message, Throwable cause) {
77+
super(message, cause);
78+
}
79+
}

src/java.base/share/classes/jdk/internal/classfile/impl/BoundAttribute.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,14 @@ public static List<Attribute<?>> readAttributes(AttributedElement enclosing, Cla
129129
int size = reader.readU2(pos);
130130
var filled = new Object[size];
131131
int p = pos + 2;
132+
int cfLen = reader.classfileLength();
132133
for (int i = 0; i < size; ++i) {
133134
Utf8Entry name = reader.readUtf8Entry(p);
134135
int len = reader.readInt(p + 2);
135136
p += 6;
137+
if (len < 0 || len > cfLen - p) {
138+
throw new IllegalArgumentException("attribute " + name.stringValue() + " too big to handle");
139+
}
136140

137141
var mapper = Attributes.standardAttribute(name);
138142
if (mapper == null) {

src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import jdk.internal.classfile.*;
3636
import jdk.internal.classfile.attribute.BootstrapMethodsAttribute;
3737
import jdk.internal.classfile.constantpool.ClassEntry;
38+
import jdk.internal.classfile.constantpool.ConstantPoolException;
3839
import jdk.internal.classfile.constantpool.LoadableConstantEntry;
3940
import jdk.internal.classfile.constantpool.MethodHandleEntry;
4041
import jdk.internal.classfile.constantpool.ModuleEntry;
@@ -91,7 +92,7 @@ public final class ClassReaderImpl
9192
this.options = new Options(options);
9293
this.attributeMapper = this.options.attributeMapper;
9394
if (classfileLength < 4 || readInt(0) != 0xCAFEBABE) {
94-
throw new IllegalStateException("Bad magic number");
95+
throw new IllegalArgumentException("Bad magic number");
9596
}
9697
int constantPoolCount = readU2(8);
9798
int[] cpOffset = new int[constantPoolCount];
@@ -118,7 +119,7 @@ public final class ClassReaderImpl
118119
++i;
119120
}
120121
case TAG_UTF8 -> p += 2 + readU2(p);
121-
default -> throw new IllegalStateException(
122+
default -> throw new ConstantPoolException(
122123
"Bad tag (" + tag + ") at index (" + i + ") position (" + p + ")");
123124
}
124125
}
@@ -306,7 +307,7 @@ void writeConstantPoolEntries(BufWriter buf) {
306307
@Override
307308
public PoolEntry entryByIndex(int index) {
308309
if (index <= 0 || index >= constantPoolCount) {
309-
throw new IndexOutOfBoundsException("Bad CP index: " + index);
310+
throw new ConstantPoolException("Bad CP index: " + index);
310311
}
311312
PoolEntry info = cp[index];
312313
if (info == null) {
@@ -336,7 +337,7 @@ public PoolEntry entryByIndex(int index) {
336337
case TAG_INVOKEDYNAMIC -> new AbstractPoolEntry.InvokeDynamicEntryImpl(this, index, readU2(q), (AbstractPoolEntry.NameAndTypeEntryImpl) readNameAndTypeEntry(q + 2));
337338
case TAG_MODULE -> new AbstractPoolEntry.ModuleEntryImpl(this, index, (AbstractPoolEntry.Utf8EntryImpl) readUtf8Entry(q));
338339
case TAG_PACKAGE -> new AbstractPoolEntry.PackageEntryImpl(this, index, (AbstractPoolEntry.Utf8EntryImpl) readUtf8Entry(q));
339-
default -> throw new IllegalStateException(
340+
default -> throw new ConstantPoolException(
340341
"Bad tag (" + tag + ") at index (" + index + ") position (" + offset + ")");
341342
};
342343
cp[index] = info;
@@ -347,14 +348,14 @@ public PoolEntry entryByIndex(int index) {
347348
@Override
348349
public AbstractPoolEntry.Utf8EntryImpl utf8EntryByIndex(int index) {
349350
if (index <= 0 || index >= constantPoolCount) {
350-
throw new IndexOutOfBoundsException("Bad CP UTF8 index: " + index);
351+
throw new ConstantPoolException("Bad CP UTF8 index: " + index);
351352
}
352353
PoolEntry info = cp[index];
353354
if (info == null) {
354355
int offset = cpOffset[index];
355356
int tag = readU1(offset);
356357
final int q = offset + 1;
357-
if (tag != TAG_UTF8) throw new IllegalArgumentException("Not a UTF8 - index: " + index);
358+
if (tag != TAG_UTF8) throw new ConstantPoolException("Not a UTF8 - index: " + index);
358359
AbstractPoolEntry.Utf8EntryImpl uinfo
359360
= new AbstractPoolEntry.Utf8EntryImpl(this, index, buffer, q + 2, readU2(q));
360361
cp[index] = uinfo;
@@ -370,7 +371,11 @@ public int skipAttributeHolder(int offset) {
370371
p += 2;
371372
for (int i = 0; i < cnt; ++i) {
372373
int len = readInt(p + 2);
373-
p += 6 + len;
374+
p += 6;
375+
if (len < 0 || len > classfileLength - p) {
376+
throw new IllegalArgumentException("attribute " + readUtf8Entry(p - 6).stringValue() + " too big to handle");
377+
}
378+
p += len;
374379
}
375380
return p;
376381
}
@@ -407,31 +412,31 @@ public Utf8Entry readUtf8EntryOrNull(int pos) {
407412
@Override
408413
public ModuleEntry readModuleEntry(int pos) {
409414
if (readEntry(pos) instanceof ModuleEntry me) return me;
410-
throw new IllegalArgumentException("Not a module entry at pos: " + pos);
415+
throw new ConstantPoolException("Not a module entry at pos: " + pos);
411416
}
412417

413418
@Override
414419
public PackageEntry readPackageEntry(int pos) {
415420
if (readEntry(pos) instanceof PackageEntry pe) return pe;
416-
throw new IllegalArgumentException("Not a package entry at pos: " + pos);
421+
throw new ConstantPoolException("Not a package entry at pos: " + pos);
417422
}
418423

419424
@Override
420425
public ClassEntry readClassEntry(int pos) {
421426
if (readEntry(pos) instanceof ClassEntry ce) return ce;
422-
throw new IllegalArgumentException("Not a class entry at pos: " + pos);
427+
throw new ConstantPoolException("Not a class entry at pos: " + pos);
423428
}
424429

425430
@Override
426431
public NameAndTypeEntry readNameAndTypeEntry(int pos) {
427432
if (readEntry(pos) instanceof NameAndTypeEntry nate) return nate;
428-
throw new IllegalArgumentException("Not a name and type entry at pos: " + pos);
433+
throw new ConstantPoolException("Not a name and type entry at pos: " + pos);
429434
}
430435

431436
@Override
432437
public MethodHandleEntry readMethodHandleEntry(int pos) {
433438
if (readEntry(pos) instanceof MethodHandleEntry mhe) return mhe;
434-
throw new IllegalArgumentException("Not a method handle entry at pos: " + pos);
439+
throw new ConstantPoolException("Not a method handle entry at pos: " + pos);
435440
}
436441

437442
@Override

0 commit comments

Comments
 (0)