src/java.base/share/classes/java/lang/constant/ConstantUtils.java
changeset 53224 bae765528fcc
parent 53019 4ddd3c410a85
equal deleted inserted replaced
53223:df6cbf676c70 53224:bae765528fcc
     1 /*
     1 /*
     2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    63      *
    63      *
    64      * @param name the name of the member
    64      * @param name the name of the member
    65      * @return the name passed if valid
    65      * @return the name passed if valid
    66      * @throws IllegalArgumentException if the member name is invalid
    66      * @throws IllegalArgumentException if the member name is invalid
    67      */
    67      */
    68     public static String validateMemberName(String name) {
    68     public static String validateMemberName(String name, boolean method) {
    69         requireNonNull(name);
    69         requireNonNull(name);
    70         if (name.length() == 0)
    70         if (name.length() == 0)
    71             throw new IllegalArgumentException("zero-length member name");
    71             throw new IllegalArgumentException("zero-length member name");
    72         for (int i=0; i<name.length(); i++) {
    72         for (int i=0; i<name.length(); i++) {
    73             char ch = name.charAt(i);
    73             char ch = name.charAt(i);
    74             if (ch == '.' || ch == ';' || ch == '[' || ch == '/')
    74             if (ch == '.' || ch == ';' || ch == '[' || ch == '/')
    75                 throw new IllegalArgumentException("Invalid member name: " + name);
    75                 throw new IllegalArgumentException("Invalid member name: " + name);
    76             if (ch == '<' || ch == '>') {
    76             if (method && (ch == '<' || ch == '>')) {
    77                 if (!pointyNames.contains(name))
    77                 if (!pointyNames.contains(name))
    78                     throw new IllegalArgumentException("Invalid member name: " + name);
    78                     throw new IllegalArgumentException("Invalid member name: " + name);
    79             }
    79             }
    80         }
    80         }
    81         return name;
    81         return name;
   124         if (cur >= end || descriptor.charAt(cur) != '(')
   124         if (cur >= end || descriptor.charAt(cur) != '(')
   125             throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
   125             throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
   126 
   126 
   127         ++cur;  // skip '('
   127         ++cur;  // skip '('
   128         while (cur < end && descriptor.charAt(cur) != ')') {
   128         while (cur < end && descriptor.charAt(cur) != ')') {
   129             int len = matchSig(descriptor, cur, end);
   129             int len = skipOverFieldSignature(descriptor, cur, end, false);
   130             if (len == 0 || descriptor.charAt(cur) == 'V')
   130             if (len == 0)
   131                 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
   131                 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
   132             ptypes.add(descriptor.substring(cur, cur + len));
   132             ptypes.add(descriptor.substring(cur, cur + len));
   133             cur += len;
   133             cur += len;
   134         }
   134         }
   135         if (cur >= end)
   135         if (cur >= end)
   136             throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
   136             throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
   137         ++cur;  // skip ')'
   137         ++cur;  // skip ')'
   138 
   138 
   139         int rLen = matchSig(descriptor, cur, end);
   139         int rLen = skipOverFieldSignature(descriptor, cur, end, true);
   140         if (rLen == 0 || cur + rLen != end)
   140         if (rLen == 0 || cur + rLen != end)
   141             throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
   141             throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
   142         ptypes.add(0, descriptor.substring(cur, cur + rLen));
   142         ptypes.add(0, descriptor.substring(cur, cur + rLen));
   143         return ptypes;
   143         return ptypes;
   144     }
   144     }
   145 
   145 
       
   146     private static final char JVM_SIGNATURE_ARRAY = '[';
       
   147     private static final char JVM_SIGNATURE_BYTE = 'B';
       
   148     private static final char JVM_SIGNATURE_CHAR = 'C';
       
   149     private static final char JVM_SIGNATURE_CLASS = 'L';
       
   150     private static final char JVM_SIGNATURE_ENDCLASS = ';';
       
   151     private static final char JVM_SIGNATURE_ENUM = 'E';
       
   152     private static final char JVM_SIGNATURE_FLOAT = 'F';
       
   153     private static final char JVM_SIGNATURE_DOUBLE = 'D';
       
   154     private static final char JVM_SIGNATURE_FUNC = '(';
       
   155     private static final char JVM_SIGNATURE_ENDFUNC = ')';
       
   156     private static final char JVM_SIGNATURE_INT = 'I';
       
   157     private static final char JVM_SIGNATURE_LONG = 'J';
       
   158     private static final char JVM_SIGNATURE_SHORT = 'S';
       
   159     private static final char JVM_SIGNATURE_VOID = 'V';
       
   160     private static final char JVM_SIGNATURE_BOOLEAN = 'Z';
       
   161 
   146     /**
   162     /**
   147      * Validates that the characters at [start, end) within the provided string
   163      * Validates that the characters at [start, end) within the provided string
   148      * describe a valid field type descriptor.
   164      * describe a valid field type descriptor.
   149      *
   165      * @param descriptor the descriptor string
   150      * @param str the descriptor string
       
   151      * @param start the starting index into the string
   166      * @param start the starting index into the string
   152      * @param end the ending index within the string
   167      * @param end the ending index within the string
       
   168      * @param voidOK is void acceptable?
   153      * @return the length of the descriptor, or 0 if it is not a descriptor
   169      * @return the length of the descriptor, or 0 if it is not a descriptor
   154      * @throws IllegalArgumentException if the descriptor string is not valid
   170      * @throws IllegalArgumentException if the descriptor string is not valid
   155      */
   171      */
   156     static int matchSig(String str, int start, int end) {
   172     @SuppressWarnings("fallthrough")
   157         if (start >= end || start >= str.length() || end > str.length())
   173     static int skipOverFieldSignature(String descriptor, int start, int end, boolean voidOK) {
   158             return 0;
   174         int arrayDim = 0;
   159         char c = str.charAt(start);
   175         int index = start;
   160         if (c == 'L') {
   176         while (index < end) {
   161             int endc = str.indexOf(';', start);
   177             switch (descriptor.charAt(index)) {
   162             int badc = str.indexOf('.', start);
   178                 case JVM_SIGNATURE_VOID: if (!voidOK) { return index; }
   163             if (badc >= 0 && badc < endc)
   179                 case JVM_SIGNATURE_BOOLEAN:
   164                 return 0;
   180                 case JVM_SIGNATURE_BYTE:
   165             badc = str.indexOf('[', start);
   181                 case JVM_SIGNATURE_CHAR:
   166             if (badc >= 0 && badc < endc)
   182                 case JVM_SIGNATURE_SHORT:
   167                 return 0;
   183                 case JVM_SIGNATURE_INT:
   168             return (endc < 0) ? 0 : endc - start + 1;
   184                 case JVM_SIGNATURE_FLOAT:
   169         } else if (c == '[') {
   185                 case JVM_SIGNATURE_LONG:
   170             int t = matchSig(str, start+1, end);
   186                 case JVM_SIGNATURE_DOUBLE:
   171             return (t > 0) ? t + 1 : 0;
   187                     return index - start + 1;
   172         } else {
   188                 case JVM_SIGNATURE_CLASS:
   173             return ("IJCSBFDZV".indexOf(c) >= 0) ? 1 : 0;
   189                     // Skip leading 'L' and ignore first appearance of ';'
   174         }
   190                     index++;
       
   191                     int indexOfSemi = descriptor.indexOf(';', index);
       
   192                     if (indexOfSemi != -1) {
       
   193                         String unqualifiedName = descriptor.substring(index, indexOfSemi);
       
   194                         boolean legal = verifyUnqualifiedClassName(unqualifiedName);
       
   195                         if (!legal) {
       
   196                             return 0;
       
   197                         }
       
   198                         return index - start + unqualifiedName.length() + 1;
       
   199                     }
       
   200                     return 0;
       
   201                 case JVM_SIGNATURE_ARRAY:
       
   202                     arrayDim++;
       
   203                     if (arrayDim > MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
       
   204                         throw new IllegalArgumentException(String.format("Cannot create an array type descriptor with more than %d dimensions",
       
   205                                 ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS));
       
   206                     }
       
   207                     // The rest of what's there better be a legal descriptor
       
   208                     index++;
       
   209                     voidOK = false;
       
   210                     break;
       
   211                 default:
       
   212                     return 0;
       
   213             }
       
   214         }
       
   215         return 0;
       
   216     }
       
   217 
       
   218     static boolean verifyUnqualifiedClassName(String name) {
       
   219         for (int index = 0; index < name.length(); index++) {
       
   220             char ch = name.charAt(index);
       
   221             if (ch < 128) {
       
   222                 if (ch == '.' || ch == ';' || ch == '[' ) {
       
   223                     return false;   // do not permit '.', ';', or '['
       
   224                 }
       
   225                 if (ch == '/') {
       
   226                     // check for '//' or leading or trailing '/' which are not legal
       
   227                     // unqualified name must not be empty
       
   228                     if (index == 0 || index + 1 >= name.length() || name.charAt(index + 1) == '/') {
       
   229                         return false;
       
   230                     }
       
   231                 }
       
   232             } else {
       
   233                 index ++;
       
   234             }
       
   235         }
       
   236         return true;
   175     }
   237     }
   176 }
   238 }