-
Notifications
You must be signed in to change notification settings - Fork 747
/
Copy pathchverify.c
183 lines (169 loc) · 5.2 KB
/
chverify.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*******************************************************************************
* Copyright IBM Corp. and others 1991
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*******************************************************************************/
#include <string.h>
#include "cfreader.h"
#include "bcverify_api.h"
/**
* Method responsible for checking name validity according to the following rules.
* Methods, fields, local variables can not contain: '.', ';', '[' '/'.
* Methods, other than <init> and <clinit> cannot contain '<' or '>'.
* Classes can contain '[' only at the front if they are array classes.
* Classes can end with ';' only if they are array classes
* Classes can contain '/'
* if not the first character,
* if not the last character,
* if not back to back (ie: //),
*
* @return -1 if invalid. 0 or class arity if valid.
*/
static VMINLINE I_32
checkNameImpl (J9CfrConstantPoolInfo * info, BOOLEAN isClass, BOOLEAN isMethod, BOOLEAN isLoading)
{
/* The separator is '.' in loading classes.
* The separator is '/' in verifying classes.
*/
BOOLEAN separator = FALSE;
I_32 arity = 0;
U_32 length = info->slot1;
U_8 *c = info->bytes;
U_8 *end = c + info->slot1;
if (isClass) {
/* strip leading ['s for array classes */
for (; ('[' == *c) && (c < end); c++) {
arity++;
}
length -= arity;
}
if (c >= end){
/* Name must be more than just [s. Also catches empty string case */
return -1;
}
while (c < end) {
/* check for illegal characters: 46(.) 47(/) 59(;) 60(<) 70(>) 91([) */
switch(*c) {
case '.':
/* Only valid for the loading classes */
if (!isClass || !isLoading) {
return -1;
}
/* FALLTHRU */
case '/':
if (isClass) {
/* Only valid between identifiers and not at end if not in loading classes */
if ((isLoading && ('/' == *c)) || separator) {
return -1;
}
separator = TRUE;
break;
}
return -1;
case ';':
/* Valid at the end of array classes */
if (isClass && arity && ((c + 1) == end)) {
break;
}
return -1;
case '<': /* Fall through */
case '>':
if (isMethod){
return -1;
}
separator = FALSE; /* allow /<>/ as a pattern, per test suites */
break;
case '[': return -1;
default:
/* Do Nothing */
separator = FALSE;
}
if (length < 1) return -1;
length--;
c++;
}
/* the separator shouldn't exist at the end of name, regardless of class and method */
if (separator) {
return -1;
}
return arity;
}
static VMINLINE I_32
isInitOrClinitImpl (J9CfrConstantPoolInfo * info)
{
U_8 *name = info->bytes;
/* Handle <init>/<clinit> cases */
if (*name == '<') {
if (J9UTF8_DATA_EQUALS("<init>", 6, name, info->slot1)) {
return CFR_METHOD_NAME_INIT;
}
if (J9UTF8_DATA_EQUALS("<clinit>", 8, name, info->slot1)) {
return CFR_METHOD_NAME_CLINIT;
}
return CFR_METHOD_NAME_INVALID;
}
return 0; /* not <init> or <clinit> */
}
/**
* Determine if this name is "<init>" or "<clinit>".
*
* @returns 0 if name is a normal name, CFR_METHOD_NAME_INIT if '<init>', CFR_METHOD_NAME_CLINIT if '<clinit>', and -1 if it starts with '<' but is not a valid class name.
* @note result is positive if the name is "<init>" or "<clinit>", result is negative if the name is illegal
*/
I_32
bcvIsInitOrClinit (J9CfrConstantPoolInfo * info)
{
return isInitOrClinitImpl(info);
}
/**
* Determine if this a valid name for Methods.
*
* @returns CFR_METHOD_NAME_INIT if '<init>' or CFR_METHOD_NAME_CLINIT if '<clinit>', otherwise 0 if a valid name; negative value if class name is invalid
*/
I_32
bcvCheckMethodName (J9CfrConstantPoolInfo * info)
{
U_8 *c = info->bytes;
I_32 nameStatus = isInitOrClinitImpl(info);
if (0 == nameStatus) {
nameStatus = checkNameImpl(info, FALSE, TRUE, FALSE);
}
return nameStatus;
}
/**
* Determine if this a valid name for Classes.
*
* @returns The arity of the class if valid, -1 otherwise
*/
I_32
bcvCheckClassName (J9CfrConstantPoolInfo * info)
{
/* Class checks, not method checks */
return checkNameImpl(info, TRUE, FALSE, FALSE);
}
/**
* Determine if this a valid name for fields, local variables, etc. Can be used
* to check anything except method names and class names.
*
* @returns 0 if valid, -1 otherwise.
*/
I_32
bcvCheckName (J9CfrConstantPoolInfo * info) {
return checkNameImpl(info, FALSE, FALSE, FALSE);
}