Improve class name checking.
Class.forName() will now do a better job of checking the validity of
the names passed to it.
Also, cleared out the TODO on dvmThrowClassNotFoundException(),
having determined that it would have been a bad idea.
Change-Id: Ia5b8c613ef8f49a313ad825dc4c72cc5ff428e69
diff --git a/vm/Exception.c b/vm/Exception.c
index aaf97a4..bdb3034 100644
--- a/vm/Exception.c
+++ b/vm/Exception.c
@@ -1255,14 +1255,17 @@
}
void dvmThrowClassNotFoundException(const char* name) {
- // TODO: Should the name be converted into human-readable form?
- dvmThrowException(gDvm.exClassNotFoundException, name);
+ dvmThrowChainedClassNotFoundException(name, NULL);
}
void dvmThrowChainedClassNotFoundException(const char* name, Object* cause) {
- // TODO: Should the name be converted into human-readable form?
- dvmThrowChainedException(gDvm.exClassNotFoundException, name,
- cause);
+ /*
+ * Note: This exception is thrown in response to a request coming
+ * from client code for the name as given, so it is preferable to
+ * make the exception message be that string, per se, instead of
+ * trying to prettify it.
+ */
+ dvmThrowChainedException(gDvm.exClassNotFoundException, name, cause);
}
void dvmThrowExceptionInInitializerError(void)
diff --git a/vm/native/InternalNative.c b/vm/native/InternalNative.c
index 49e0c08..603f313 100644
--- a/vm/native/InternalNative.c
+++ b/vm/native/InternalNative.c
@@ -187,27 +187,67 @@
int len = strlen(name);
int i = 0;
+ /*
+ * TODO: This doesn't currently check for all possible name
+ * problems, per the dex spec. Note: dexIsValidTypeDescriptor()
+ * *almost* does the right thing, except it always wants a type
+ * descriptor per se ("L" and ";" around even non-array class
+ * names) and it wants slashes not dots between name components.
+ */
+
/* check for reasonable array types */
if (name[0] == '[') {
while (name[i] == '[')
i++;
+ if (i > 255) {
+ /* Arrays are allowed no more than 255 dimensions. */
+ return false;
+ }
+
if (name[i] == 'L') {
- /* array of objects, make sure it ends well */
- if (name[len-1] != ';')
+ /*
+ * It's an array of objects; make sure it's non-empty and
+ * ends properly.
+ */
+ if ((i >= (len-2)) || (name[len-1] != ';')) {
return false;
+ }
+ } else if (name[i] == 'V') {
+ /* There is no such thing as array of void. */
+ return false;
} else if (strchr(PRIM_TYPE_TO_LETTER, name[i]) != NULL) {
- if (i != len-1)
+ if (i != len-1) {
return false;
+ }
+ /* It is a valid array of primitives. */
+ return true;
} else {
return false;
}
+
+ /*
+ * At this point, we are looking at an array of objects: Skip
+ * the initial "L" (i++) and the final ";" (len--), and fall
+ * through to the illegal character check.
+ */
+
+ i++;
+ len--;
}
- /* quick check for illegal chars */
+ /* Check for (some) illegal characters. */
for ( ; i < len; i++) {
- if (name[i] == '/')
+ char c = name[i];
+ switch (c) {
+ case '.':
+ case '-':
+ case '$':
+ continue;
+ }
+ if (c <= ' ') {
return false;
+ }
}
return true;