/
niceSOFT
/
openjdk21
Обзор
Документация
Войти
/
niceSOFT
/
openjdk21
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationSignature.java
319 строк
10 KB
Adam Sotona
8294982: Implementation of Classfile API
09 мар 2023, 18:23
09 мар 2023, 18:23
4655b79
Код
Авторство
О чём код?
/* * Copyright (c) 2022, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.internal.classfile.impl.verifier; final class VerificationSignature { enum BasicType { T_BOOLEAN(4), T_CHAR(5), T_FLOAT(6), T_DOUBLE(7), T_BYTE(8), T_SHORT(9), T_INT(10), T_LONG(11), T_OBJECT(12), T_ARRAY(13), T_VOID(14), T_ADDRESS(15), T_NARROWOOP(16), T_METADATA(17), T_NARROWKLASS(18), T_CONFLICT(19), T_ILLEGAL(99); final int type; BasicType(int type) { this.type = type; } static BasicType fromSignature(char ch) { return switch (ch) { case JVM_SIGNATURE_BOOLEAN -> T_BOOLEAN; case JVM_SIGNATURE_CHAR -> T_CHAR; case JVM_SIGNATURE_FLOAT -> T_FLOAT; case JVM_SIGNATURE_DOUBLE -> T_DOUBLE; case JVM_SIGNATURE_BYTE -> T_BYTE; case JVM_SIGNATURE_SHORT -> T_SHORT; case JVM_SIGNATURE_INT -> T_INT; case JVM_SIGNATURE_LONG -> T_LONG; case JVM_SIGNATURE_CLASS -> T_OBJECT; case JVM_SIGNATURE_ARRAY -> T_ARRAY; case JVM_SIGNATURE_VOID -> T_VOID; default -> throw new IllegalArgumentException("Not a valid type: '" + ch + "'"); }; } } static final char JVM_SIGNATURE_DOT = '.', JVM_SIGNATURE_ARRAY = '[', JVM_SIGNATURE_BYTE = 'B', JVM_SIGNATURE_CHAR = 'C', JVM_SIGNATURE_CLASS = 'L', JVM_SIGNATURE_ENDCLASS = ';', JVM_SIGNATURE_FLOAT = 'F', JVM_SIGNATURE_DOUBLE = 'D', JVM_SIGNATURE_FUNC = '(', JVM_SIGNATURE_ENDFUNC = ')', JVM_SIGNATURE_INT = 'I', JVM_SIGNATURE_LONG = 'J', JVM_SIGNATURE_SHORT = 'S', JVM_SIGNATURE_VOID = 'V', JVM_SIGNATURE_BOOLEAN = 'Z'; static boolean isReferenceType(BasicType t) { return t == BasicType.T_OBJECT || t == BasicType.T_ARRAY; } private static final char TYPE2CHAR_TAB[] = new char[]{ 0, 0, 0, 0, JVM_SIGNATURE_BOOLEAN, JVM_SIGNATURE_CHAR, JVM_SIGNATURE_FLOAT, JVM_SIGNATURE_DOUBLE, JVM_SIGNATURE_BYTE, JVM_SIGNATURE_SHORT, JVM_SIGNATURE_INT, JVM_SIGNATURE_LONG, JVM_SIGNATURE_CLASS, JVM_SIGNATURE_ARRAY, JVM_SIGNATURE_VOID, 0, 0, 0, 0, 0 }; static boolean hasEnvelope(char signature_char) { return signature_char == JVM_SIGNATURE_CLASS; } private BasicType type; private final String signature; private final int limit; private int begin, end, arrayPrefix, state; private static final int S_FIELD = 0, S_METHOD = 1, S_METHOD_RETURN = 3; boolean atReturnType() { return state == S_METHOD_RETURN; } boolean isReference() { return isReferenceType(type); } BasicType type() { return type; } private int rawSymbolBegin() { return begin + (hasEnvelope() ? 1 : 0); } private int rawSymbolEnd() { return end - (hasEnvelope() ? 1 : 0); } private boolean hasEnvelope() { return hasEnvelope(signature.charAt(begin)); } String asSymbol() { int begin = rawSymbolBegin(); int end = rawSymbolEnd(); return signature.substring(begin, end); } int skipArrayPrefix(int max_skip_length) { if (type != BasicType.T_ARRAY) { return 0; } if (arrayPrefix > max_skip_length) { // strip some but not all levels of T_ARRAY arrayPrefix -= max_skip_length; begin += max_skip_length; return max_skip_length; } return skipWholeArrayPrefix(); } static BasicType decodeSignatureChar(char ch) { return BasicType.fromSignature(ch); } private final VerifierImpl context; VerificationSignature(String signature, boolean is_method, VerifierImpl context) { this.signature = signature; this.limit = signature.length(); int oz = is_method ? S_METHOD : S_FIELD; this.state = oz; this.begin = this.end = oz; this.arrayPrefix = 0; this.context = context; next(); } private int scanType(BasicType type) { int e = end; int tem; switch (type) { case T_OBJECT: tem = signature.indexOf(JVM_SIGNATURE_ENDCLASS, e); return tem < 0 ? limit : tem + 1; case T_ARRAY: while (e < limit && signature.charAt(e) == JVM_SIGNATURE_ARRAY) { e++; } arrayPrefix = e - end; if (hasEnvelope(signature.charAt(e))) { tem = signature.indexOf(JVM_SIGNATURE_ENDCLASS, e); return tem < 0 ? limit : tem + 1; } return e + 1; default: return e + 1; } } void next() { final String sig = signature; int len = limit; testLen(len); begin = end; char ch = sig.charAt(begin); if (ch == JVM_SIGNATURE_ENDFUNC) { state = S_METHOD_RETURN; begin = ++end; testLen(len); ch = sig.charAt(begin); } try { BasicType bt = decodeSignatureChar(ch); type = bt; end = scanType(bt); } catch (IllegalArgumentException iae) { throw new IllegalArgumentException("Not a valid signature: '" + signature + "'", iae); } } private void testLen(int len) { if (end >= len) { if (context == null) { throw new IllegalArgumentException("Invalid signature " + signature); } else { context.verifyError("Invalid signature " + signature); } } } int skipWholeArrayPrefix() { int whole_array_prefix = arrayPrefix; int new_begin = begin + whole_array_prefix; begin = new_begin; char ch = signature.charAt(new_begin); BasicType bt = decodeSignatureChar(ch); type = bt; return whole_array_prefix; } @SuppressWarnings("fallthrough") static int isValidType(String type, int limit) { int index = 0; // Iterate over any number of array dimensions while (index < limit && type.charAt(index) == JVM_SIGNATURE_ARRAY) { ++index; } if (index >= limit) { return -1; } switch (type.charAt(index)) { case JVM_SIGNATURE_BYTE: case JVM_SIGNATURE_CHAR: case JVM_SIGNATURE_FLOAT: case JVM_SIGNATURE_DOUBLE: case JVM_SIGNATURE_INT: case JVM_SIGNATURE_LONG: case JVM_SIGNATURE_SHORT: case JVM_SIGNATURE_BOOLEAN: case JVM_SIGNATURE_VOID: return index + 1; case JVM_SIGNATURE_CLASS: for (index = index + 1; index < limit; ++index) { char c = type.charAt(index); switch (c) { case JVM_SIGNATURE_ENDCLASS: return index + 1; case '\0': case JVM_SIGNATURE_DOT: case JVM_SIGNATURE_ARRAY: return -1; default: ; // fall through } } // fall through default: ; // fall through } return -1; } static boolean isValidMethodSignature(String method_sig) { if (method_sig != null) { int len = method_sig.length(); int index = 0; if (len > 1 && method_sig.charAt(index) == JVM_SIGNATURE_FUNC) { ++index; while (index < len && method_sig.charAt(index) != JVM_SIGNATURE_ENDFUNC) { int res = isValidType(method_sig.substring(index), len - index); if (res == -1) { return false; } else { index += res; } } if (index < len && method_sig.charAt(index) == JVM_SIGNATURE_ENDFUNC) { // check the return type ++index; return (isValidType(method_sig.substring(index), len - index) == (len - index)); } } } return false; } static boolean isValidTypeSignature(String sig) { if (sig == null) return false; int len = sig.length(); return (len >= 1 && (isValidType(sig, len) == len)); } }