mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8308549
: Classfile API should fail to generate over-sized Code attribute
Reviewed-by: mchung
This commit is contained in:
parent
2a18e537d6
commit
bfcae68ed1
6 changed files with 50 additions and 5 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, 2023, 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
|
||||||
|
@ -311,6 +311,13 @@ public final class DirectCodeBuilder
|
||||||
buf.setLabelContext(DirectCodeBuilder.this);
|
buf.setLabelContext(DirectCodeBuilder.this);
|
||||||
|
|
||||||
int codeLength = curPc();
|
int codeLength = curPc();
|
||||||
|
if (codeLength == 0 || codeLength >= 65536) {
|
||||||
|
throw new IllegalArgumentException(String.format(
|
||||||
|
"Code length %d is outside the allowed range in %s%s",
|
||||||
|
codeLength,
|
||||||
|
methodInfo.methodName().stringValue(),
|
||||||
|
methodInfo.methodTypeSymbol().displayDescriptor()));
|
||||||
|
}
|
||||||
int maxStack, maxLocals;
|
int maxStack, maxLocals;
|
||||||
Attribute<? extends StackMapTableAttribute> stackMapAttr;
|
Attribute<? extends StackMapTableAttribute> stackMapAttr;
|
||||||
boolean canReuseStackmaps = codeAndExceptionsMatch(codeLength);
|
boolean canReuseStackmaps = codeAndExceptionsMatch(codeLength);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, 2023, 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
|
||||||
|
@ -194,6 +194,9 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(BufWriter buf) {
|
public void writeTo(BufWriter buf) {
|
||||||
int writeFrom = 1;
|
int writeFrom = 1;
|
||||||
|
if (entryCount() >= 65536) {
|
||||||
|
throw new IllegalArgumentException(String.format("Constant pool is too large %d", entryCount()));
|
||||||
|
}
|
||||||
buf.writeU2(entryCount());
|
buf.writeU2(entryCount());
|
||||||
if (parent != null && buf.constantPool().canWriteDirect(this)) {
|
if (parent != null && buf.constantPool().canWriteDirect(this)) {
|
||||||
parent.writeConstantPoolEntries(buf);
|
parent.writeConstantPoolEntries(buf);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, 2023, 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
|
||||||
|
@ -67,7 +67,7 @@ public final class VerifierImpl {
|
||||||
JVM_CONSTANT_Package = 20,
|
JVM_CONSTANT_Package = 20,
|
||||||
JVM_CONSTANT_ExternalMax = 20;
|
JVM_CONSTANT_ExternalMax = 20;
|
||||||
|
|
||||||
static final char JVM_SIGNATURE_SPECIAL = '<',
|
static final char JVM_SIGNATURE_SPECIAL = '<',
|
||||||
JVM_SIGNATURE_ARRAY = '[',
|
JVM_SIGNATURE_ARRAY = '[',
|
||||||
JVM_SIGNATURE_BYTE = 'B',
|
JVM_SIGNATURE_BYTE = 'B',
|
||||||
JVM_SIGNATURE_CHAR = 'C',
|
JVM_SIGNATURE_CHAR = 'C',
|
||||||
|
@ -102,6 +102,7 @@ static final char JVM_SIGNATURE_SPECIAL = '<',
|
||||||
static final int STACKMAP_ATTRIBUTE_MAJOR_VERSION = 50;
|
static final int STACKMAP_ATTRIBUTE_MAJOR_VERSION = 50;
|
||||||
static final int INVOKEDYNAMIC_MAJOR_VERSION = 51;
|
static final int INVOKEDYNAMIC_MAJOR_VERSION = 51;
|
||||||
static final int NOFAILOVER_MAJOR_VERSION = 51;
|
static final int NOFAILOVER_MAJOR_VERSION = 51;
|
||||||
|
static final int MAX_CODE_SIZE = 65535;
|
||||||
|
|
||||||
public static List<VerifyError> verify(ClassModel classModel, Consumer<String> logger) {
|
public static List<VerifyError> verify(ClassModel classModel, Consumer<String> logger) {
|
||||||
return verify(classModel, ClassHierarchyResolver.DEFAULT_CLASS_HIERARCHY_RESOLVER, logger);
|
return verify(classModel, ClassHierarchyResolver.DEFAULT_CLASS_HIERARCHY_RESOLVER, logger);
|
||||||
|
@ -299,6 +300,9 @@ static final char JVM_SIGNATURE_SPECIAL = '<',
|
||||||
VerificationType return_type = current_frame.set_locals_from_arg(m, current_type());
|
VerificationType return_type = current_frame.set_locals_from_arg(m, current_type());
|
||||||
int stackmap_index = 0;
|
int stackmap_index = 0;
|
||||||
int code_length = m.codeLength();
|
int code_length = m.codeLength();
|
||||||
|
if (code_length < 1 || code_length > MAX_CODE_SIZE) {
|
||||||
|
verifyError(String.format("Invalid method Code length %d", code_length));
|
||||||
|
}
|
||||||
var code = ByteBuffer.wrap(_method.codeArray(), 0, _method.codeLength());
|
var code = ByteBuffer.wrap(_method.codeArray(), 0, _method.codeLength());
|
||||||
byte[] code_data = generate_code_data(code, code_length);
|
byte[] code_data = generate_code_data(code, code_length);
|
||||||
int ex_minmax[] = new int[] {code_length, -1};
|
int ex_minmax[] = new int[] {code_length, -1};
|
||||||
|
|
|
@ -255,6 +255,7 @@ class BuilderBlockTest {
|
||||||
assertEquals(slot1, 4);
|
assertEquals(slot1, 4);
|
||||||
assertEquals(slot2, 5);
|
assertEquals(slot2, 5);
|
||||||
assertEquals(slot3, 7);
|
assertEquals(slot3, 7);
|
||||||
|
xb.return_();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -275,6 +276,7 @@ class BuilderBlockTest {
|
||||||
});
|
});
|
||||||
int slot4 = xb.allocateLocal(TypeKind.IntType);
|
int slot4 = xb.allocateLocal(TypeKind.IntType);
|
||||||
assertEquals(slot4, 4);
|
assertEquals(slot4, 4);
|
||||||
|
xb.return_();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ class BuilderParamTest {
|
||||||
assertEquals(xb.parameterSlot(0), 1);
|
assertEquals(xb.parameterSlot(0), 1);
|
||||||
assertEquals(xb.parameterSlot(1), 2);
|
assertEquals(xb.parameterSlot(1), 2);
|
||||||
assertEquals(xb.parameterSlot(2), 4);
|
assertEquals(xb.parameterSlot(2), 4);
|
||||||
|
xb.return_();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -61,6 +62,7 @@ class BuilderParamTest {
|
||||||
assertEquals(xb.parameterSlot(0), 0);
|
assertEquals(xb.parameterSlot(0), 0);
|
||||||
assertEquals(xb.parameterSlot(1), 1);
|
assertEquals(xb.parameterSlot(1), 1);
|
||||||
assertEquals(xb.parameterSlot(2), 3);
|
assertEquals(xb.parameterSlot(2), 3);
|
||||||
|
xb.return_();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, 2023, 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
|
||||||
|
@ -30,8 +30,10 @@
|
||||||
*/
|
*/
|
||||||
import java.lang.constant.ClassDesc;
|
import java.lang.constant.ClassDesc;
|
||||||
import java.lang.constant.ConstantDescs;
|
import java.lang.constant.ConstantDescs;
|
||||||
|
import java.lang.constant.MethodTypeDesc;
|
||||||
import jdk.internal.classfile.Classfile;
|
import jdk.internal.classfile.Classfile;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
class LimitsTest {
|
class LimitsTest {
|
||||||
|
|
||||||
|
@ -44,4 +46,29 @@ class LimitsTest {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCPOverLimit() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> Classfile.build(ClassDesc.of("BigClass"), cb -> {
|
||||||
|
for (int i = 1; i < 66000; i++) {
|
||||||
|
cb.withField("field" + i, ConstantDescs.CD_int, fb -> {});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCodeOverLimit() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> Classfile.build(ClassDesc.of("BigClass"), cb -> cb.withMethodBody(
|
||||||
|
"bigMethod", MethodTypeDesc.of(ConstantDescs.CD_void), 0, cob -> {
|
||||||
|
for (int i = 0; i < 65535; i++) {
|
||||||
|
cob.nop();
|
||||||
|
}
|
||||||
|
cob.return_();
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testEmptyCode() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> Classfile.build(ClassDesc.of("EmptyClass"), cb -> cb.withMethodBody(
|
||||||
|
"emptyMethod", MethodTypeDesc.of(ConstantDescs.CD_void), 0, cob -> {})));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue