Home | History | Annotate | Download | only in dex
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "descriptors_names.h"
     18 
     19 #include "android-base/stringprintf.h"
     20 #include "android-base/strings.h"
     21 
     22 #include "dex/utf-inl.h"
     23 
     24 namespace art {
     25 
     26 using android::base::StringAppendF;
     27 using android::base::StringPrintf;
     28 
     29 void AppendPrettyDescriptor(const char* descriptor, std::string* result) {
     30   // Count the number of '['s to get the dimensionality.
     31   const char* c = descriptor;
     32   size_t dim = 0;
     33   while (*c == '[') {
     34     dim++;
     35     c++;
     36   }
     37 
     38   // Reference or primitive?
     39   if (*c == 'L') {
     40     // "[[La/b/C;" -> "a.b.C[][]".
     41     c++;  // Skip the 'L'.
     42   } else {
     43     // "[[B" -> "byte[][]".
     44     // To make life easier, we make primitives look like unqualified
     45     // reference types.
     46     switch (*c) {
     47       case 'B': c = "byte;"; break;
     48       case 'C': c = "char;"; break;
     49       case 'D': c = "double;"; break;
     50       case 'F': c = "float;"; break;
     51       case 'I': c = "int;"; break;
     52       case 'J': c = "long;"; break;
     53       case 'S': c = "short;"; break;
     54       case 'Z': c = "boolean;"; break;
     55       case 'V': c = "void;"; break;  // Used when decoding return types.
     56       default: result->append(descriptor); return;
     57     }
     58   }
     59 
     60   // At this point, 'c' is a string of the form "fully/qualified/Type;"
     61   // or "primitive;". Rewrite the type with '.' instead of '/':
     62   const char* p = c;
     63   while (*p != ';') {
     64     char ch = *p++;
     65     if (ch == '/') {
     66       ch = '.';
     67     }
     68     result->push_back(ch);
     69   }
     70   // ...and replace the semicolon with 'dim' "[]" pairs:
     71   for (size_t i = 0; i < dim; ++i) {
     72     result->append("[]");
     73   }
     74 }
     75 
     76 std::string PrettyDescriptor(const char* descriptor) {
     77   std::string result;
     78   AppendPrettyDescriptor(descriptor, &result);
     79   return result;
     80 }
     81 
     82 std::string GetJniShortName(const std::string& class_descriptor, const std::string& method) {
     83   // Remove the leading 'L' and trailing ';'...
     84   std::string class_name(class_descriptor);
     85   CHECK_EQ(class_name[0], 'L') << class_name;
     86   CHECK_EQ(class_name[class_name.size() - 1], ';') << class_name;
     87   class_name.erase(0, 1);
     88   class_name.erase(class_name.size() - 1, 1);
     89 
     90   std::string short_name;
     91   short_name += "Java_";
     92   short_name += MangleForJni(class_name);
     93   short_name += "_";
     94   short_name += MangleForJni(method);
     95   return short_name;
     96 }
     97 
     98 // See http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/design.html#wp615 for the full rules.
     99 std::string MangleForJni(const std::string& s) {
    100   std::string result;
    101   size_t char_count = CountModifiedUtf8Chars(s.c_str());
    102   const char* cp = &s[0];
    103   for (size_t i = 0; i < char_count; ++i) {
    104     uint32_t ch = GetUtf16FromUtf8(&cp);
    105     if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) {
    106       result.push_back(ch);
    107     } else if (ch == '.' || ch == '/') {
    108       result += "_";
    109     } else if (ch == '_') {
    110       result += "_1";
    111     } else if (ch == ';') {
    112       result += "_2";
    113     } else if (ch == '[') {
    114       result += "_3";
    115     } else {
    116       const uint16_t leading = GetLeadingUtf16Char(ch);
    117       const uint32_t trailing = GetTrailingUtf16Char(ch);
    118 
    119       StringAppendF(&result, "_0%04x", leading);
    120       if (trailing != 0) {
    121         StringAppendF(&result, "_0%04x", trailing);
    122       }
    123     }
    124   }
    125   return result;
    126 }
    127 
    128 std::string DotToDescriptor(const char* class_name) {
    129   std::string descriptor(class_name);
    130   std::replace(descriptor.begin(), descriptor.end(), '.', '/');
    131   if (descriptor.length() > 0 && descriptor[0] != '[') {
    132     descriptor = "L" + descriptor + ";";
    133   }
    134   return descriptor;
    135 }
    136 
    137 std::string DescriptorToDot(const char* descriptor) {
    138   size_t length = strlen(descriptor);
    139   if (length > 1) {
    140     if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
    141       // Descriptors have the leading 'L' and trailing ';' stripped.
    142       std::string result(descriptor + 1, length - 2);
    143       std::replace(result.begin(), result.end(), '/', '.');
    144       return result;
    145     } else {
    146       // For arrays the 'L' and ';' remain intact.
    147       std::string result(descriptor);
    148       std::replace(result.begin(), result.end(), '/', '.');
    149       return result;
    150     }
    151   }
    152   // Do nothing for non-class/array descriptors.
    153   return descriptor;
    154 }
    155 
    156 std::string DescriptorToName(const char* descriptor) {
    157   size_t length = strlen(descriptor);
    158   if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
    159     std::string result(descriptor + 1, length - 2);
    160     return result;
    161   }
    162   return descriptor;
    163 }
    164 
    165 // Helper for IsValidPartOfMemberNameUtf8(), a bit vector indicating valid low ascii.
    166 static uint32_t DEX_MEMBER_VALID_LOW_ASCII[4] = {
    167   0x00000000,  // 00..1f low control characters; nothing valid
    168   0x03ff2010,  // 20..3f digits and symbols; valid: '0'..'9', '$', '-'
    169   0x87fffffe,  // 40..5f uppercase etc.; valid: 'A'..'Z', '_'
    170   0x07fffffe   // 60..7f lowercase etc.; valid: 'a'..'z'
    171 };
    172 
    173 // Helper for IsValidPartOfMemberNameUtf8(); do not call directly.
    174 static bool IsValidPartOfMemberNameUtf8Slow(const char** pUtf8Ptr) {
    175   /*
    176    * It's a multibyte encoded character. Decode it and analyze. We
    177    * accept anything that isn't (a) an improperly encoded low value,
    178    * (b) an improper surrogate pair, (c) an encoded '\0', (d) a high
    179    * control character, or (e) a high space, layout, or special
    180    * character (U+00a0, U+2000..U+200f, U+2028..U+202f,
    181    * U+fff0..U+ffff). This is all specified in the dex format
    182    * document.
    183    */
    184 
    185   const uint32_t pair = GetUtf16FromUtf8(pUtf8Ptr);
    186   const uint16_t leading = GetLeadingUtf16Char(pair);
    187 
    188   // We have a surrogate pair resulting from a valid 4 byte UTF sequence.
    189   // No further checks are necessary because 4 byte sequences span code
    190   // points [U+10000, U+1FFFFF], which are valid codepoints in a dex
    191   // identifier. Furthermore, GetUtf16FromUtf8 guarantees that each of
    192   // the surrogate halves are valid and well formed in this instance.
    193   if (GetTrailingUtf16Char(pair) != 0) {
    194     return true;
    195   }
    196 
    197 
    198   // We've encountered a one, two or three byte UTF-8 sequence. The
    199   // three byte UTF-8 sequence could be one half of a surrogate pair.
    200   switch (leading >> 8) {
    201     case 0x00:
    202       // It's only valid if it's above the ISO-8859-1 high space (0xa0).
    203       return (leading > 0x00a0);
    204     case 0xd8:
    205     case 0xd9:
    206     case 0xda:
    207     case 0xdb:
    208       {
    209         // We found a three byte sequence encoding one half of a surrogate.
    210         // Look for the other half.
    211         const uint32_t pair2 = GetUtf16FromUtf8(pUtf8Ptr);
    212         const uint16_t trailing = GetLeadingUtf16Char(pair2);
    213 
    214         return (GetTrailingUtf16Char(pair2) == 0) && (0xdc00 <= trailing && trailing <= 0xdfff);
    215       }
    216     case 0xdc:
    217     case 0xdd:
    218     case 0xde:
    219     case 0xdf:
    220       // It's a trailing surrogate, which is not valid at this point.
    221       return false;
    222     case 0x20:
    223     case 0xff:
    224       // It's in the range that has spaces, controls, and specials.
    225       switch (leading & 0xfff8) {
    226         case 0x2000:
    227         case 0x2008:
    228         case 0x2028:
    229         case 0xfff0:
    230         case 0xfff8:
    231           return false;
    232       }
    233       return true;
    234     default:
    235       return true;
    236   }
    237 
    238   UNREACHABLE();
    239 }
    240 
    241 /* Return whether the pointed-at modified-UTF-8 encoded character is
    242  * valid as part of a member name, updating the pointer to point past
    243  * the consumed character. This will consume two encoded UTF-16 code
    244  * points if the character is encoded as a surrogate pair. Also, if
    245  * this function returns false, then the given pointer may only have
    246  * been partially advanced.
    247  */
    248 static bool IsValidPartOfMemberNameUtf8(const char** pUtf8Ptr) {
    249   uint8_t c = (uint8_t) **pUtf8Ptr;
    250   if (LIKELY(c <= 0x7f)) {
    251     // It's low-ascii, so check the table.
    252     uint32_t wordIdx = c >> 5;
    253     uint32_t bitIdx = c & 0x1f;
    254     (*pUtf8Ptr)++;
    255     return (DEX_MEMBER_VALID_LOW_ASCII[wordIdx] & (1 << bitIdx)) != 0;
    256   }
    257 
    258   // It's a multibyte encoded character. Call a non-inline function
    259   // for the heavy lifting.
    260   return IsValidPartOfMemberNameUtf8Slow(pUtf8Ptr);
    261 }
    262 
    263 bool IsValidMemberName(const char* s) {
    264   bool angle_name = false;
    265 
    266   switch (*s) {
    267     case '\0':
    268       // The empty string is not a valid name.
    269       return false;
    270     case '<':
    271       angle_name = true;
    272       s++;
    273       break;
    274   }
    275 
    276   while (true) {
    277     switch (*s) {
    278       case '\0':
    279         return !angle_name;
    280       case '>':
    281         return angle_name && s[1] == '\0';
    282     }
    283 
    284     if (!IsValidPartOfMemberNameUtf8(&s)) {
    285       return false;
    286     }
    287   }
    288 }
    289 
    290 enum ClassNameType { kName, kDescriptor };
    291 template<ClassNameType kType, char kSeparator>
    292 static bool IsValidClassName(const char* s) {
    293   int arrayCount = 0;
    294   while (*s == '[') {
    295     arrayCount++;
    296     s++;
    297   }
    298 
    299   if (arrayCount > 255) {
    300     // Arrays may have no more than 255 dimensions.
    301     return false;
    302   }
    303 
    304   ClassNameType type = kType;
    305   if (type != kDescriptor && arrayCount != 0) {
    306     /*
    307      * If we're looking at an array of some sort, then it doesn't
    308      * matter if what is being asked for is a class name; the
    309      * format looks the same as a type descriptor in that case, so
    310      * treat it as such.
    311      */
    312     type = kDescriptor;
    313   }
    314 
    315   if (type == kDescriptor) {
    316     /*
    317      * We are looking for a descriptor. Either validate it as a
    318      * single-character primitive type, or continue on to check the
    319      * embedded class name (bracketed by "L" and ";").
    320      */
    321     switch (*(s++)) {
    322     case 'B':
    323     case 'C':
    324     case 'D':
    325     case 'F':
    326     case 'I':
    327     case 'J':
    328     case 'S':
    329     case 'Z':
    330       // These are all single-character descriptors for primitive types.
    331       return (*s == '\0');
    332     case 'V':
    333       // Non-array void is valid, but you can't have an array of void.
    334       return (arrayCount == 0) && (*s == '\0');
    335     case 'L':
    336       // Class name: Break out and continue below.
    337       break;
    338     default:
    339       // Oddball descriptor character.
    340       return false;
    341     }
    342   }
    343 
    344   /*
    345    * We just consumed the 'L' that introduces a class name as part
    346    * of a type descriptor, or we are looking for an unadorned class
    347    * name.
    348    */
    349 
    350   bool sepOrFirst = true;  // first character or just encountered a separator.
    351   for (;;) {
    352     uint8_t c = (uint8_t) *s;
    353     switch (c) {
    354     case '\0':
    355       /*
    356        * Premature end for a type descriptor, but valid for
    357        * a class name as long as we haven't encountered an
    358        * empty component (including the degenerate case of
    359        * the empty string "").
    360        */
    361       return (type == kName) && !sepOrFirst;
    362     case ';':
    363       /*
    364        * Invalid character for a class name, but the
    365        * legitimate end of a type descriptor. In the latter
    366        * case, make sure that this is the end of the string
    367        * and that it doesn't end with an empty component
    368        * (including the degenerate case of "L;").
    369        */
    370       return (type == kDescriptor) && !sepOrFirst && (s[1] == '\0');
    371     case '/':
    372     case '.':
    373       if (c != kSeparator) {
    374         // The wrong separator character.
    375         return false;
    376       }
    377       if (sepOrFirst) {
    378         // Separator at start or two separators in a row.
    379         return false;
    380       }
    381       sepOrFirst = true;
    382       s++;
    383       break;
    384     default:
    385       if (!IsValidPartOfMemberNameUtf8(&s)) {
    386         return false;
    387       }
    388       sepOrFirst = false;
    389       break;
    390     }
    391   }
    392 }
    393 
    394 bool IsValidBinaryClassName(const char* s) {
    395   return IsValidClassName<kName, '.'>(s);
    396 }
    397 
    398 bool IsValidJniClassName(const char* s) {
    399   return IsValidClassName<kName, '/'>(s);
    400 }
    401 
    402 bool IsValidDescriptor(const char* s) {
    403   return IsValidClassName<kDescriptor, '/'>(s);
    404 }
    405 
    406 void Split(const std::string& s, char separator, std::vector<std::string>* result) {
    407   const char* p = s.data();
    408   const char* end = p + s.size();
    409   while (p != end) {
    410     if (*p == separator) {
    411       ++p;
    412     } else {
    413       const char* start = p;
    414       while (++p != end && *p != separator) {
    415         // Skip to the next occurrence of the separator.
    416       }
    417       result->push_back(std::string(start, p - start));
    418     }
    419   }
    420 }
    421 
    422 std::string PrettyDescriptor(Primitive::Type type) {
    423   return PrettyDescriptor(Primitive::Descriptor(type));
    424 }
    425 
    426 }  // namespace art
    427