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;