diff options
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 4bc8e8efba..1d0684202c 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2592,9 +2592,25 @@ mirror::Class* ClassLinker::FindClass(Thread* self, return nullptr; } + // Inlined DescriptorToDot(descriptor) with extra validation. + // + // Throw NoClassDefFoundError early rather than potentially load a class only to fail + // the DescriptorEquals() check below and give a confusing error message. For example, + // when native code erroneously calls JNI GetFieldId() with signature "java/lang/String" + // instead of "Ljava/lang/String;", the message below using the "dot" names would be + // "class loader [...] returned class java.lang.String instead of java.lang.String". + size_t descriptor_length = strlen(descriptor); + if (UNLIKELY(descriptor[0] != 'L') || + UNLIKELY(descriptor[descriptor_length - 1] != ';') || + UNLIKELY(memchr(descriptor + 1, '.', descriptor_length - 2) != nullptr)) { + ThrowNoClassDefFoundError("Invalid descriptor: %s.", descriptor); + return nullptr; + } + std::string class_name_string(descriptor + 1, descriptor_length - 2); + std::replace(class_name_string.begin(), class_name_string.end(), '/', '.'); + ScopedLocalRef<jobject> class_loader_object( soa.Env(), soa.AddLocalReference<jobject>(class_loader.Get())); - std::string class_name_string(DescriptorToDot(descriptor)); ScopedLocalRef<jobject> result(soa.Env(), nullptr); { ScopedThreadStateChange tsc(self, kNative); |