/* Return whether the given string is a valid field or method name. */ bool dexIsValidMemberName(const char* s) { bool angleName = false; switch (*s) { case '\0': { // The empty string is not a valid name. return false; } case '<': { /* * '<' is allowed only at the start of a name, and if present, * means that the name must end with '>'. */ angleName = true; s++; break; } } for (;;) { switch (*s) { case '\0': { return !angleName; } case '>': { return angleName && s[1] == '\0'; } } if (!dexIsValidMemberNameUtf8(&s)) { return false; } } }
/* Return whether the given string is a valid type descriptor. */ bool dexIsValidTypeDescriptor(const char* s) { int arrayCount = 0; while (*s == '[') { arrayCount++; s++; } if (arrayCount > 255) { // Arrays may have no more than 255 dimensions. return false; } switch (*(s++)) { case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': case 'Z': { // These are all single-character descriptors for primitive types. return (*s == '\0'); } case 'V': { // You can't have an array of void. return (arrayCount == 0) && (*s == '\0'); } case 'L': { // Break out and continue below. break; } default: { // Oddball descriptor character. return false; } } // We just consumed the 'L' that introduces a class name. bool slashOrFirst = true; // first character or just encountered a slash for (;;) { u1 c = (u1) *s; switch (c) { case '\0': { // Premature end. return false; } case ';': { /* * Make sure that this is the end of the string and that * it doesn't end with an empty component (including the * degenerate case of "L;"). */ return (s[1] == '\0') && !slashOrFirst; } case '/': { if (slashOrFirst) { // Slash at start or two slashes in a row. return false; } slashOrFirst = true; s++; break; } default: { if (!dexIsValidMemberNameUtf8(&s)) { return false; } slashOrFirst = false; break; } } } }
/* Helper for validating type descriptors and class names, which is parametric * with respect to type vs. class and dot vs. slash. */ static bool isValidTypeDescriptorOrClassName(const char* s, bool isClassName, bool dotSeparator) { int arrayCount = 0; while (*s == '[') { arrayCount++; s++; } if (arrayCount > 255) { // Arrays may have no more than 255 dimensions. return false; } if (arrayCount != 0) { /* * If we're looking at an array of some sort, then it doesn't * matter if what is being asked for is a class name; the * format looks the same as a type descriptor in that case, so * treat it as such. */ isClassName = false; } if (!isClassName) { /* * We are looking for a descriptor. Either validate it as a * single-character primitive type, or continue on to check the * embedded class name (bracketed by "L" and ";"). */ switch (*(s++)) { case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': case 'Z': { // These are all single-character descriptors for primitive types. return (*s == '\0'); } case 'V': { // Non-array void is valid, but you can't have an array of void. return (arrayCount == 0) && (*s == '\0'); } case 'L': { // Class name: Break out and continue below. break; } default: { // Oddball descriptor character. return false; } } } /* * We just consumed the 'L' that introduces a class name as part * of a type descriptor, or we are looking for an unadorned class * name. */ bool sepOrFirst = true; // first character or just encountered a separator. for (;;) { u1 c = (u1) *s; switch (c) { case '\0': { /* * Premature end for a type descriptor, but valid for * a class name as long as we haven't encountered an * empty component (including the degenerate case of * the empty string ""). */ return isClassName && !sepOrFirst; } case ';': { /* * Invalid character for a class name, but the * legitimate end of a type descriptor. In the latter * case, make sure that this is the end of the string * and that it doesn't end with an empty component * (including the degenerate case of "L;"). */ return !isClassName && !sepOrFirst && (s[1] == '\0'); } case '/': case '.': { if (dotSeparator != (c == '.')) { // The wrong separator character. return false; } if (sepOrFirst) { // Separator at start or two separators in a row. return false; } sepOrFirst = true; s++; break; } default: { if (!dexIsValidMemberNameUtf8(&s)) { return false; } sepOrFirst = false; break; } } } }