Skip to content

Commit 77d38b7

Browse files
martinuygnu-andrew
authored andcommitted
8314295: Enhance verification of verifier
Reviewed-by: yan, andrew Backport-of: 08980a0a60bc48c17eacd57fd2d7065ac2d986a8
1 parent 5e0e2bf commit 77d38b7

File tree

3 files changed

+26
-12
lines changed

3 files changed

+26
-12
lines changed

hotspot/src/share/vm/classfile/verifier.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2081,11 +2081,12 @@ void ClassVerifier::verify_switch(
20812081
"low must be less than or equal to high in tableswitch");
20822082
return;
20832083
}
2084-
keys = high - low + 1;
2085-
if (keys < 0) {
2084+
int64_t keys64 = ((int64_t)high - low) + 1;
2085+
if (keys64 > 65535) { // Max code length
20862086
verify_error(ErrorContext::bad_code(bci), "too many keys in tableswitch");
20872087
return;
20882088
}
2089+
keys = (int)keys64;
20892090
delta = 1;
20902091
} else {
20912092
keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize);

hotspot/src/share/vm/interpreter/bytecodes.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,18 @@ int Bytecodes::special_length_at(Bytecodes::Code code, address bcp, address end)
114114
if (end != NULL && aligned_bcp + 3*jintSize >= end) {
115115
return -1; // don't read past end of code buffer
116116
}
117+
// Promote calculation to signed 64 bits to do range checks, used by the verifier.
117118
jlong lo = (jint)Bytes::get_Java_u4(aligned_bcp + 1*jintSize);
118119
jlong hi = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize);
119120
jlong len = (aligned_bcp - bcp) + (3 + hi - lo + 1)*jintSize;
120-
// only return len if it can be represented as a positive int;
121-
// return -1 otherwise
122-
return (len > 0 && len == (int)len) ? len : -1;
121+
// Only return len if it can be represented as a positive int and lo <= hi.
122+
// The caller checks for bytecode stream overflow.
123+
if (lo <= hi && len == (int)len) {
124+
assert(len > 0, "must be");
125+
return (int)len;
126+
} else {
127+
return -1;
128+
}
123129
}
124130

125131
case _lookupswitch: // fall through
@@ -131,9 +137,13 @@ int Bytecodes::special_length_at(Bytecodes::Code code, address bcp, address end)
131137
}
132138
jlong npairs = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize);
133139
jlong len = (aligned_bcp - bcp) + (2 + 2*npairs)*jintSize;
134-
// only return len if it can be represented as a positive int;
135-
// return -1 otherwise
136-
return (len > 0 && len == (int)len) ? len : -1;
140+
// Only return len if it can be represented as a positive int and npairs >= 0.
141+
if (npairs >= 0 && len == (int)len) {
142+
assert(len > 0, "must be");
143+
return (int)len;
144+
} else {
145+
return -1;
146+
}
137147
}
138148
}
139149
// Note: Length functions must return <=0 for invalid bytecodes.

jdk/src/share/native/common/check_code.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -84,6 +84,7 @@
8484
#include <assert.h>
8585
#include <limits.h>
8686
#include <stdlib.h>
87+
#include <stdint.h>
8788

8889
#include "jni.h"
8990
#include "jvm.h"
@@ -1202,7 +1203,7 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset)
12021203
}
12031204
}
12041205
if (opcode == JVM_OPC_tableswitch) {
1205-
keys = _ck_ntohl(lpc[2]) - _ck_ntohl(lpc[1]) + 1;
1206+
keys = _ck_ntohl(lpc[2]) - _ck_ntohl(lpc[1]) + 1;
12061207
delta = 1;
12071208
} else {
12081209
keys = _ck_ntohl(lpc[1]); /* number of pairs */
@@ -1682,11 +1683,13 @@ static int instruction_length(unsigned char *iptr, unsigned char *end)
16821683
switch (instruction) {
16831684
case JVM_OPC_tableswitch: {
16841685
int *lpc = (int *)UCALIGN(iptr + 1);
1685-
int index;
16861686
if (lpc + 2 >= (int *)end) {
16871687
return -1; /* do not read pass the end */
16881688
}
1689-
index = _ck_ntohl(lpc[2]) - _ck_ntohl(lpc[1]);
1689+
int64_t low = _ck_ntohl(lpc[1]);
1690+
int64_t high = _ck_ntohl(lpc[2]);
1691+
int64_t index = high - low;
1692+
// The value of low must be less than or equal to high - i.e. index >= 0
16901693
if ((index < 0) || (index > 65535)) {
16911694
return -1; /* illegal */
16921695
} else {

0 commit comments

Comments
 (0)