Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/common/check_format.c
38825 views
/*1* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <setjmp.h>26#include <stdlib.h>27#include <string.h>2829#include "jni.h"30#include "jvm.h"3132typedef unsigned short unicode;3334static char *35skip_over_fieldname(char *name, jboolean slash_okay,36unsigned int len);37static char *38skip_over_field_signature(char *name, jboolean void_okay,39unsigned int len);4041/*42* Return non-zero if the character is a valid in JVM class name, zero43* otherwise. The only characters currently disallowed from JVM class44* names are given in the table below:45*46* Character Hex Decimal47* '.' 0x2e 4648* '/' 0x2f 4749* ';' 0x3b 5950* '[' 0x5b 9151*52* (Method names have further restrictions dealing with the '<' and53* '>' characters.)54*/55static int isJvmIdentifier(unicode ch) {56if( ch > 91 || ch < 46 )57return 1; /* Lowercase ASCII letters are > 91 */58else { /* 46 <= ch <= 91 */59if (ch <= 90 && ch >= 60) {60return 1; /* Uppercase ASCII recognized here */61} else { /* ch == 91 || 46 <= ch <= 59 */62if (ch == 91 || ch == 59 || ch <= 47)63return 0;64else65return 1;66}67}68}6970static unicode71next_utf2unicode(char **utfstring_ptr, int * valid)72{73unsigned char *ptr = (unsigned char *)(*utfstring_ptr);74unsigned char ch, ch2, ch3;75int length = 1; /* default length */76unicode result = 0x80; /* default bad result; */77*valid = 1;78switch ((ch = ptr[0]) >> 4) {79default:80result = ch;81break;8283case 0x8: case 0x9: case 0xA: case 0xB: case 0xF:84/* Shouldn't happen. */85*valid = 0;86break;8788case 0xC: case 0xD:89/* 110xxxxx 10xxxxxx */90if (((ch2 = ptr[1]) & 0xC0) == 0x80) {91unsigned char high_five = ch & 0x1F;92unsigned char low_six = ch2 & 0x3F;93result = (high_five << 6) + low_six;94length = 2;95}96break;9798case 0xE:99/* 1110xxxx 10xxxxxx 10xxxxxx */100if (((ch2 = ptr[1]) & 0xC0) == 0x80) {101if (((ch3 = ptr[2]) & 0xC0) == 0x80) {102unsigned char high_four = ch & 0x0f;103unsigned char mid_six = ch2 & 0x3f;104unsigned char low_six = ch3 & 0x3f;105result = (((high_four << 6) + mid_six) << 6) + low_six;106length = 3;107} else {108length = 2;109}110}111break;112} /* end of switch */113114*utfstring_ptr = (char *)(ptr + length);115return result;116}117118/* Take pointer to a string. Skip over the longest part of the string that119* could be taken as a fieldname. Allow '/' if slash_okay is JNI_TRUE.120*121* Return a pointer to just past the fieldname. Return NULL if no fieldname122* at all was found, or in the case of slash_okay being true, we saw123* consecutive slashes (meaning we were looking for a qualified path but124* found something that was badly-formed).125*/126static char *127skip_over_fieldname(char *name, jboolean slash_okay,128unsigned int length)129{130char *p;131unicode ch;132unicode last_ch = 0;133int valid = 1;134/* last_ch == 0 implies we are looking at the first char. */135for (p = name; p != name + length; last_ch = ch) {136char *old_p = p;137ch = *p;138if (ch < 128) {139p++;140if (isJvmIdentifier(ch)) {141continue;142}143} else {144char *tmp_p = p;145ch = next_utf2unicode(&tmp_p, &valid);146if (valid == 0)147return 0;148p = tmp_p;149if (isJvmIdentifier(ch)) {150continue;151}152}153154if (slash_okay && ch == '/' && last_ch) {155if (last_ch == '/') {156return 0; /* Don't permit consecutive slashes */157}158} else if (ch == '_' || ch == '$') {159} else {160return last_ch ? old_p : 0;161}162}163return last_ch ? p : 0;164}165166/* Take pointer to a string. Skip over the longest part of the string that167* could be taken as a field signature. Allow "void" if void_okay.168*169* Return a pointer to just past the signature. Return NULL if no legal170* signature is found.171*/172173static char *174skip_over_field_signature(char *name, jboolean void_okay,175unsigned int length)176{177unsigned int array_dim = 0;178for (;length > 0;) {179switch (name[0]) {180case JVM_SIGNATURE_VOID:181if (!void_okay) return 0;182/* FALL THROUGH */183case JVM_SIGNATURE_BOOLEAN:184case JVM_SIGNATURE_BYTE:185case JVM_SIGNATURE_CHAR:186case JVM_SIGNATURE_SHORT:187case JVM_SIGNATURE_INT:188case JVM_SIGNATURE_FLOAT:189case JVM_SIGNATURE_LONG:190case JVM_SIGNATURE_DOUBLE:191return name + 1;192193case JVM_SIGNATURE_CLASS: {194/* Skip over the classname, if one is there. */195char *p =196skip_over_fieldname(name + 1, JNI_TRUE, --length);197/* The next character better be a semicolon. */198if (p && p - name - 1 > 0 && p[0] == ';')199return p + 1;200return 0;201}202203case JVM_SIGNATURE_ARRAY:204array_dim++;205/* JVMS 2nd ed. 4.10 */206/* The number of dimensions in an array is limited to 255 ... */207if (array_dim > 255) {208return 0;209}210/* The rest of what's there better be a legal signature. */211name++;212length--;213void_okay = JNI_FALSE;214break;215216default:217return 0;218}219}220return 0;221}222223224/* Used in java/lang/Class.c */225/* Determine if the specified name is legal226* UTF name for a classname.227*228* Note that this routine expects the internal form of qualified classes:229* the dots should have been replaced by slashes.230*/231JNIEXPORT jboolean232VerifyClassname(char *name, jboolean allowArrayClass)233{234unsigned int length = strlen(name);235char *p;236237if (length > 0 && name[0] == JVM_SIGNATURE_ARRAY) {238if (!allowArrayClass) {239return JNI_FALSE;240} else {241/* Everything that's left better be a field signature */242p = skip_over_field_signature(name, JNI_FALSE, length);243}244} else {245/* skip over the fieldname. Slashes are okay */246p = skip_over_fieldname(name, JNI_TRUE, length);247}248return (p != 0 && p - name == (ptrdiff_t)length);249}250251/*252* Translates '.' to '/'. Returns JNI_TRUE is any / were present.253*/254JNIEXPORT jboolean255VerifyFixClassname(char *name)256{257char *p = name;258jboolean slashesFound = JNI_FALSE;259int valid = 1;260261while (valid != 0 && *p != '\0') {262if (*p == '/') {263slashesFound = JNI_TRUE;264p++;265} else if (*p == '.') {266*p++ = '/';267} else {268next_utf2unicode(&p, &valid);269}270}271272return slashesFound && valid != 0;273}274275276