Ensure GetSourceDebugExtension works with Proxy classes.

We were unconditionally trying to read a class-def pointer from
classes passed to GetSourceDebugExtension but this pointer will be
null for proxy classes. This could cause segfaults.

Bug: 67836742
Bug: 68157595

Test: ./test.py --host -j50
Change-Id: I3d9ee4647b65bf5092de486903c7fb1e88c718a5
diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc
index fe33bde..6075230 100644
--- a/runtime/dex_file_annotations.cc
+++ b/runtime/dex_file_annotations.cc
@@ -134,8 +134,12 @@
     REQUIRES_SHARED(Locks::mutator_lock_) {
   const DexFile* dex_file = field->GetDexFile();
   ObjPtr<mirror::Class> klass = field->GetDeclaringClass();
+  const DexFile::ClassDef* class_def = klass->GetClassDef();
+  if (class_def == nullptr) {
+    return nullptr;
+  }
   const DexFile::AnnotationsDirectoryItem* annotations_dir =
-      dex_file->GetAnnotationsDirectory(*klass->GetClassDef());
+      dex_file->GetAnnotationsDirectory(*class_def);
   if (annotations_dir == nullptr) {
     return nullptr;
   }
@@ -258,6 +262,9 @@
 
 const DexFile::AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method)
     REQUIRES_SHARED(Locks::mutator_lock_) {
+  if (method->IsProxyMethod()) {
+    return nullptr;
+  }
   const DexFile* dex_file = method->GetDexFile();
   const DexFile::AnnotationsDirectoryItem* annotations_dir =
       dex_file->GetAnnotationsDirectory(method->GetClassDef());
@@ -305,8 +312,12 @@
 const DexFile::AnnotationSetItem* FindAnnotationSetForClass(const ClassData& klass)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   const DexFile& dex_file = klass.GetDexFile();
+  const DexFile::ClassDef* class_def = klass.GetClassDef();
+  if (class_def == nullptr) {
+    return nullptr;
+  }
   const DexFile::AnnotationsDirectoryItem* annotations_dir =
-      dex_file.GetAnnotationsDirectory(*klass.GetClassDef());
+      dex_file.GetAnnotationsDirectory(*class_def);
   if (annotations_dir == nullptr) {
     return nullptr;
   }
diff --git a/test/992-source-data/expected.txt b/test/992-source-data/expected.txt
index 4db8df0..7f59682 100644
--- a/test/992-source-data/expected.txt
+++ b/test/992-source-data/expected.txt
@@ -1,10 +1,22 @@
 class art.Test992 is defined in file "Test992.java"
+class art.Test992 does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
 class art.Test992$Target1 is defined in file "Test992.java"
+class art.Test992$Target1 does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
 class art.Target2 is defined in file "Target2.java"
+class art.Target2 does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
 int does not have a known source file because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
+int does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
 class java.lang.Integer is defined in file "Integer.java"
+class java.lang.Integer does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
 class java.lang.Object is defined in file "Object.java"
+class java.lang.Object does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
 interface java.lang.Runnable is defined in file "Runnable.java"
+interface java.lang.Runnable does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
 class [Ljava.lang.Object; does not have a known source file because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
+class [Ljava.lang.Object; does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
 class [I does not have a known source file because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
+class [I does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
 null does not have a known source file because java.lang.RuntimeException: JVMTI_ERROR_INVALID_CLASS
+null does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_INVALID_CLASS
+Proxy of [interface java.lang.Runnable] does not have a known source file because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
+Proxy of [interface java.lang.Runnable] does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
diff --git a/test/992-source-data/source_file.cc b/test/992-source-data/source_file.cc
index 46d197d..78687ff 100644
--- a/test/992-source-data/source_file.cc
+++ b/test/992-source-data/source_file.cc
@@ -49,6 +49,19 @@
   return ret;
 }
 
+extern "C" JNIEXPORT
+jstring JNICALL Java_art_Test992_getSourceDebugExtension(JNIEnv* env,
+                                                         jclass klass ATTRIBUTE_UNUSED,
+                                                         jclass target) {
+  char* ext = nullptr;
+  if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetSourceDebugExtension(target, &ext))) {
+    return nullptr;
+  }
+  jstring ret = env->NewStringUTF(ext);
+  jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(ext));
+  return ret;
+}
+
 }  // namespace Test992SourceFile
 }  // namespace art
 
diff --git a/test/992-source-data/src/art/Test992.java b/test/992-source-data/src/art/Test992.java
index d9ab112..cc4f0c7 100644
--- a/test/992-source-data/src/art/Test992.java
+++ b/test/992-source-data/src/art/Test992.java
@@ -16,6 +16,8 @@
 
 package art;
 
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
 import java.util.Base64;
 
 public class Test992 {
@@ -33,15 +35,30 @@
     doTest(new Object[0].getClass());
     doTest(new int[0].getClass());
     doTest(null);
+    doTest(Proxy.getProxyClass(Test992.class.getClassLoader(), Runnable.class));
   }
 
+  public static String printClass(Class<?> k) {
+    if (k != null && Proxy.class.isAssignableFrom(k)) {
+      return String.format("Proxy of %s", Arrays.toString(k.getInterfaces()));
+    } else {
+      return String.format("%s", k);
+    }
+  }
   public static void doTest(Class<?> k) {
+    String pk = printClass(k);
     try {
-      System.out.println(k + " is defined in file \"" + getSourceFileName(k) + "\"");
+      System.out.println(pk + " is defined in file \"" + getSourceFileName(k) + "\"");
     } catch (Exception e) {
-      System.out.println(k + " does not have a known source file because " + e);
+      System.out.println(pk + " does not have a known source file because " + e);
+    }
+    try {
+      System.out.println(pk + " has extension \"" + getSourceDebugExtension(k) + "\"");
+    } catch (Exception e) {
+      System.out.println(pk + " does not have a known source file extension because " + e);
     }
   }
 
   public static native String getSourceFileName(Class<?> k) throws Exception;
+  public static native String getSourceDebugExtension(Class<?> k) throws Exception;
 }