Disallow JNI NewObjectArray of primitive types.

Also, make jni_internal_test execute via the interpreter rather than compile
methods. Add tests for passing negative array sizes to JNI routines new
functions. Re-enable the tests NewStringNullCharsNonzeroLength and
NewDirectBuffer_GetDirectBufferAddress_GetDirectBufferCapacity. Test and
explicitly fail if the initial value argument to NewObjectArray isn't
assignable to that type of array.
Use unchecked ObjectArray::Set with NewObjectArray with an initial value.

Change-Id: If3491cb5f974b42cf70c1b850819265f9963ee48
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index bbe5fda..81cc94b 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -1954,8 +1954,13 @@
   }
 
   static jstring NewString(JNIEnv* env, const jchar* chars, jsize char_count) {
-    if (UNLIKELY(chars == NULL && char_count > 0)) { \
-      JniAbortF("NewString", "char == null && char_count > 0"); \
+    if (UNLIKELY(char_count < 0)) {
+      JniAbortF("NewString", "char_count < 0: %d", char_count);
+      return nullptr;
+    }
+    if (UNLIKELY(chars == nullptr && char_count > 0)) {
+      JniAbortF("NewString", "chars == null && char_count > 0");
+      return nullptr;
     }
     ScopedObjectAccess soa(env);
     String* result = String::AllocFromUtf16(soa.Self(), char_count, chars);
@@ -2129,32 +2134,51 @@
     return NewPrimitiveArray<jlongArray, LongArray>(soa, length);
   }
 
-  static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_jclass, jobject initial_element) {
-    if (length < 0) {
+  static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_jclass,
+                                     jobject initial_element) {
+    if (UNLIKELY(length < 0)) {
       JniAbortF("NewObjectArray", "negative array length: %d", length);
+      return nullptr;
     }
 
     // Compute the array class corresponding to the given element class.
     ScopedObjectAccess soa(env);
-    Class* element_class = soa.Decode<Class*>(element_jclass);
-    std::string descriptor;
-    descriptor += "[";
-    descriptor += ClassHelper(element_class).GetDescriptor();
+    Class* array_class;
+    {
+      Class* element_class = soa.Decode<Class*>(element_jclass);
+      if (UNLIKELY(element_class->IsPrimitive())) {
+        JniAbortF("NewObjectArray", "not an object type: %s",
+                  PrettyDescriptor(element_class).c_str());
+        return nullptr;
+      }
+      std::string descriptor("[");
+      descriptor += ClassHelper(element_class).GetDescriptor();
 
-    // Find the class.
-    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-    SirtRef<mirror::ClassLoader> class_loader(soa.Self(), element_class->GetClassLoader());
-    Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
-    if (array_class == NULL) {
-      return NULL;
+      // Find the class.
+      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+      SirtRef<mirror::ClassLoader> class_loader(soa.Self(), element_class->GetClassLoader());
+      array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
+      if (UNLIKELY(array_class == nullptr)) {
+        return nullptr;
+      }
     }
 
     // Allocate and initialize if necessary.
     ObjectArray<Object>* result = ObjectArray<Object>::Alloc(soa.Self(), array_class, length);
-    if (initial_element != NULL) {
+    if (result != nullptr && initial_element != nullptr) {
       Object* initial_object = soa.Decode<Object*>(initial_element);
-      for (jsize i = 0; i < length; ++i) {
-        result->Set(i, initial_object);
+      if (initial_object != nullptr) {
+        mirror::Class* element_class = result->GetClass()->GetComponentType();
+        if (UNLIKELY(!element_class->IsAssignableFrom(initial_object->GetClass()))) {
+          JniAbortF("NewObjectArray", "cannot assign object of type '%s' to array with element "
+                    "type of '%s'", PrettyDescriptor(initial_object->GetClass()).c_str(),
+                    PrettyDescriptor(element_class).c_str());
+
+        } else {
+          for (jsize i = 0; i < length; ++i) {
+            result->SetWithoutChecks(i, initial_object);
+          }
+        }
       }
     }
     return soa.AddLocalReference<jobjectArray>(result);
@@ -2572,8 +2596,9 @@
   template<typename JniT, typename ArtT>
   static JniT NewPrimitiveArray(const ScopedObjectAccess& soa, jsize length)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    if (length < 0) {
+    if (UNLIKELY(length < 0)) {
       JniAbortF("NewPrimitiveArray", "negative array length: %d", length);
+      return nullptr;
     }
     ArtT* result = ArtT::Alloc(soa.Self(), length);
     return soa.AddLocalReference<JniT>(result);