1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "java_lang_reflect_Executable.h"
18 
19 #include "android-base/stringprintf.h"
20 
21 #include "art_method-inl.h"
22 #include "dex_file_annotations.h"
23 #include "handle.h"
24 #include "jni_internal.h"
25 #include "mirror/class-inl.h"
26 #include "mirror/method.h"
27 #include "mirror/object-inl.h"
28 #include "mirror/object_array-inl.h"
29 #include "reflection.h"
30 #include "scoped_fast_native_object_access-inl.h"
31 #include "well_known_classes.h"
32 
33 namespace art {
34 
35 using android::base::StringPrintf;
36 
Executable_getDeclaredAnnotationsNative(JNIEnv * env,jobject javaMethod)37 static jobjectArray Executable_getDeclaredAnnotationsNative(JNIEnv* env, jobject javaMethod) {
38   ScopedFastNativeObjectAccess soa(env);
39   ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
40   if (method->GetDeclaringClass()->IsProxyClass()) {
41     // Return an empty array instead of a null pointer.
42     ObjPtr<mirror::Class> annotation_array_class =
43         soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
44     ObjPtr<mirror::ObjectArray<mirror::Object>> empty_array =
45         mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
46     return soa.AddLocalReference<jobjectArray>(empty_array);
47   }
48   return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForMethod(method));
49 }
50 
Executable_getAnnotationNative(JNIEnv * env,jobject javaMethod,jclass annotationType)51 static jobject Executable_getAnnotationNative(JNIEnv* env,
52                                               jobject javaMethod,
53                                               jclass annotationType) {
54   ScopedFastNativeObjectAccess soa(env);
55   StackHandleScope<1> hs(soa.Self());
56   ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
57   if (method->IsProxyMethod()) {
58     return nullptr;
59   } else {
60     Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
61     return soa.AddLocalReference<jobject>(annotations::GetAnnotationForMethod(method, klass));
62   }
63 }
64 
Executable_getSignatureAnnotation(JNIEnv * env,jobject javaMethod)65 static jobjectArray Executable_getSignatureAnnotation(JNIEnv* env, jobject javaMethod) {
66   ScopedFastNativeObjectAccess soa(env);
67   ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
68   if (method->GetDeclaringClass()->IsProxyClass()) {
69     return nullptr;
70   }
71   StackHandleScope<1> hs(soa.Self());
72   return soa.AddLocalReference<jobjectArray>(annotations::GetSignatureAnnotationForMethod(method));
73 }
74 
75 
Executable_getParameterAnnotationsNative(JNIEnv * env,jobject javaMethod)76 static jobjectArray Executable_getParameterAnnotationsNative(JNIEnv* env, jobject javaMethod) {
77   ScopedFastNativeObjectAccess soa(env);
78   ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
79   if (method->IsProxyMethod()) {
80     return nullptr;
81   } else {
82     return soa.AddLocalReference<jobjectArray>(annotations::GetParameterAnnotations(method));
83   }
84 }
85 
Executable_getParameters0(JNIEnv * env,jobject javaMethod)86 static jobjectArray Executable_getParameters0(JNIEnv* env, jobject javaMethod) {
87   ScopedFastNativeObjectAccess soa(env);
88   Thread* self = soa.Self();
89   StackHandleScope<8> hs(self);
90 
91   Handle<mirror::Method> executable = hs.NewHandle(soa.Decode<mirror::Method>(javaMethod));
92   ArtMethod* art_method = executable.Get()->GetArtMethod();
93   if (art_method->GetDeclaringClass()->IsProxyClass()) {
94     return nullptr;
95   }
96 
97   // Find the MethodParameters system annotation.
98   MutableHandle<mirror::ObjectArray<mirror::String>> names =
99       hs.NewHandle<mirror::ObjectArray<mirror::String>>(nullptr);
100   MutableHandle<mirror::IntArray> access_flags = hs.NewHandle<mirror::IntArray>(nullptr);
101   if (!annotations::GetParametersMetadataForMethod(art_method, &names, &access_flags)) {
102     return nullptr;
103   }
104 
105   // Validate the MethodParameters system annotation data.
106   if (UNLIKELY(names == nullptr || access_flags == nullptr)) {
107     ThrowIllegalArgumentException(
108         StringPrintf("Missing parameter metadata for names or access flags for %s",
109                      art_method->PrettyMethod().c_str()).c_str());
110     return nullptr;
111   }
112 
113   // Check array sizes match each other
114   int32_t names_count = names.Get()->GetLength();
115   int32_t access_flags_count = access_flags.Get()->GetLength();
116   if (names_count != access_flags_count) {
117     ThrowIllegalArgumentException(
118         StringPrintf(
119             "Inconsistent parameter metadata for %s. names length: %d, access flags length: %d",
120             art_method->PrettyMethod().c_str(),
121             names_count,
122             access_flags_count).c_str());
123     return nullptr;
124   }
125 
126   // Instantiate a Parameter[] to hold the result.
127   Handle<mirror::Class> parameter_array_class =
128       hs.NewHandle(
129           soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Parameter__array));
130   Handle<mirror::ObjectArray<mirror::Object>> parameter_array =
131       hs.NewHandle(
132           mirror::ObjectArray<mirror::Object>::Alloc(self,
133                                                      parameter_array_class.Get(),
134                                                      names_count));
135   if (UNLIKELY(parameter_array == nullptr)) {
136     self->AssertPendingException();
137     return nullptr;
138   }
139 
140   Handle<mirror::Class> parameter_class =
141       hs.NewHandle(soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Parameter));
142   ArtMethod* parameter_init =
143       jni::DecodeArtMethod(WellKnownClasses::java_lang_reflect_Parameter_init);
144 
145   // Mutable handles used in the loop below to ensure cleanup without scaling the number of
146   // handles by the number of parameters.
147   MutableHandle<mirror::String> name = hs.NewHandle<mirror::String>(nullptr);
148   MutableHandle<mirror::Object> parameter = hs.NewHandle<mirror::Object>(nullptr);
149 
150   // Populate the Parameter[] to return.
151   for (int32_t parameter_index = 0; parameter_index < names_count; parameter_index++) {
152     name.Assign(names.Get()->Get(parameter_index));
153     int32_t modifiers = access_flags.Get()->Get(parameter_index);
154 
155     // Allocate / initialize the Parameter to add to parameter_array.
156     parameter.Assign(parameter_class->AllocObject(self));
157     if (UNLIKELY(parameter == nullptr)) {
158       self->AssertPendingOOMException();
159       return nullptr;
160     }
161 
162     uint32_t args[5] = { PointerToLowMemUInt32(parameter.Get()),
163                          PointerToLowMemUInt32(name.Get()),
164                          static_cast<uint32_t>(modifiers),
165                          PointerToLowMemUInt32(executable.Get()),
166                          static_cast<uint32_t>(parameter_index)
167     };
168     JValue result;
169     static const char* method_signature = "VLILI";  // return + parameter types
170     parameter_init->Invoke(self, args, sizeof(args), &result, method_signature);
171     if (UNLIKELY(self->IsExceptionPending())) {
172       return nullptr;
173     }
174 
175     // Store the Parameter in the Parameter[].
176     parameter_array.Get()->Set(parameter_index, parameter.Get());
177     if (UNLIKELY(self->IsExceptionPending())) {
178       return nullptr;
179     }
180   }
181   return soa.AddLocalReference<jobjectArray>(parameter_array.Get());
182 }
183 
Executable_isAnnotationPresentNative(JNIEnv * env,jobject javaMethod,jclass annotationType)184 static jboolean Executable_isAnnotationPresentNative(JNIEnv* env,
185                                                      jobject javaMethod,
186                                                      jclass annotationType) {
187   ScopedFastNativeObjectAccess soa(env);
188   ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
189   if (method->GetDeclaringClass()->IsProxyClass()) {
190     return false;
191   }
192   StackHandleScope<1> hs(soa.Self());
193   Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
194   return annotations::IsMethodAnnotationPresent(method, klass);
195 }
196 
Executable_compareMethodParametersInternal(JNIEnv * env,jobject thisMethod,jobject otherMethod)197 static jint Executable_compareMethodParametersInternal(JNIEnv* env,
198                                                        jobject thisMethod,
199                                                        jobject otherMethod) {
200   ScopedFastNativeObjectAccess soa(env);
201   ArtMethod* this_method = ArtMethod::FromReflectedMethod(soa, thisMethod);
202   ArtMethod* other_method = ArtMethod::FromReflectedMethod(soa, otherMethod);
203 
204   this_method = this_method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
205   other_method = other_method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
206 
207   const DexFile::TypeList* this_list = this_method->GetParameterTypeList();
208   const DexFile::TypeList* other_list = other_method->GetParameterTypeList();
209 
210   if (this_list == other_list) {
211     return 0;
212   }
213 
214   if (this_list == nullptr && other_list != nullptr) {
215     return -1;
216   }
217 
218   if (other_list == nullptr && this_list != nullptr) {
219     return 1;
220   }
221 
222   const int32_t this_size = this_list->Size();
223   const int32_t other_size = other_list->Size();
224 
225   if (this_size != other_size) {
226     return (this_size - other_size);
227   }
228 
229   for (int32_t i = 0; i < this_size; ++i) {
230     const DexFile::TypeId& lhs = this_method->GetDexFile()->GetTypeId(
231         this_list->GetTypeItem(i).type_idx_);
232     const DexFile::TypeId& rhs = other_method->GetDexFile()->GetTypeId(
233         other_list->GetTypeItem(i).type_idx_);
234 
235     uint32_t lhs_len, rhs_len;
236     const char* lhs_data = this_method->GetDexFile()->StringDataAndUtf16LengthByIdx(
237         lhs.descriptor_idx_, &lhs_len);
238     const char* rhs_data = other_method->GetDexFile()->StringDataAndUtf16LengthByIdx(
239         rhs.descriptor_idx_, &rhs_len);
240 
241     int cmp = strcmp(lhs_data, rhs_data);
242     if (cmp != 0) {
243       return (cmp < 0) ? -1 : 1;
244     }
245   }
246 
247   return 0;
248 }
249 
Executable_getMethodNameInternal(JNIEnv * env,jobject javaMethod)250 static jobject Executable_getMethodNameInternal(JNIEnv* env, jobject javaMethod) {
251   ScopedFastNativeObjectAccess soa(env);
252   ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
253   method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
254   return soa.AddLocalReference<jobject>(method->GetNameAsString(soa.Self()));
255 }
256 
Executable_getMethodReturnTypeInternal(JNIEnv * env,jobject javaMethod)257 static jobject Executable_getMethodReturnTypeInternal(JNIEnv* env, jobject javaMethod) {
258   ScopedFastNativeObjectAccess soa(env);
259   ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
260   method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
261   ObjPtr<mirror::Class> return_type(method->GetReturnType(true /* resolve */));
262   if (return_type.IsNull()) {
263     CHECK(soa.Self()->IsExceptionPending());
264     return nullptr;
265   }
266 
267   return soa.AddLocalReference<jobject>(return_type);
268 }
269 
270 // TODO: Move this to mirror::Class ? Other mirror types that commonly appear
271 // as arrays have a GetArrayClass() method. This is duplicated in
272 // java_lang_Class.cc as well.
GetClassArrayClass(Thread * self)273 static ObjPtr<mirror::Class> GetClassArrayClass(Thread* self)
274     REQUIRES_SHARED(Locks::mutator_lock_) {
275   ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
276   return Runtime::Current()->GetClassLinker()->FindArrayClass(self, &class_class);
277 }
278 
Executable_getParameterTypesInternal(JNIEnv * env,jobject javaMethod)279 static jobjectArray Executable_getParameterTypesInternal(JNIEnv* env, jobject javaMethod) {
280   ScopedFastNativeObjectAccess soa(env);
281   ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
282   method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
283 
284   const DexFile::TypeList* params = method->GetParameterTypeList();
285   if (params == nullptr) {
286     return nullptr;
287   }
288 
289   const uint32_t num_params = params->Size();
290 
291   StackHandleScope<3> hs(soa.Self());
292   Handle<mirror::Class> class_array_class = hs.NewHandle(GetClassArrayClass(soa.Self()));
293   Handle<mirror::ObjectArray<mirror::Class>> ptypes = hs.NewHandle(
294       mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class.Get(), num_params));
295   if (ptypes.IsNull()) {
296     DCHECK(soa.Self()->IsExceptionPending());
297     return nullptr;
298   }
299 
300   MutableHandle<mirror::Class> param(hs.NewHandle<mirror::Class>(nullptr));
301   for (uint32_t i = 0; i < num_params; ++i) {
302     const dex::TypeIndex type_idx = params->GetTypeItem(i).type_idx_;
303     param.Assign(Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method));
304     if (param.Get() == nullptr) {
305       DCHECK(soa.Self()->IsExceptionPending());
306       return nullptr;
307     }
308     ptypes->SetWithoutChecks<false>(i, param.Get());
309   }
310 
311   return soa.AddLocalReference<jobjectArray>(ptypes.Get());
312 }
313 
Executable_getParameterCountInternal(JNIEnv * env,jobject javaMethod)314 static jint Executable_getParameterCountInternal(JNIEnv* env, jobject javaMethod) {
315   ScopedFastNativeObjectAccess soa(env);
316   ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
317   method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
318 
319   const DexFile::TypeList* params = method->GetParameterTypeList();
320   return (params == nullptr) ? 0 : params->Size();
321 }
322 
323 
324 static JNINativeMethod gMethods[] = {
325   FAST_NATIVE_METHOD(Executable, compareMethodParametersInternal,
326                      "(Ljava/lang/reflect/Method;)I"),
327   FAST_NATIVE_METHOD(Executable, getAnnotationNative,
328                      "(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;"),
329   FAST_NATIVE_METHOD(Executable, getDeclaredAnnotationsNative,
330                      "()[Ljava/lang/annotation/Annotation;"),
331   FAST_NATIVE_METHOD(Executable, getParameterAnnotationsNative,
332                      "()[[Ljava/lang/annotation/Annotation;"),
333   FAST_NATIVE_METHOD(Executable, getMethodNameInternal, "()Ljava/lang/String;"),
334   FAST_NATIVE_METHOD(Executable, getMethodReturnTypeInternal, "()Ljava/lang/Class;"),
335   FAST_NATIVE_METHOD(Executable, getParameterTypesInternal, "()[Ljava/lang/Class;"),
336   FAST_NATIVE_METHOD(Executable, getParameterCountInternal, "()I"),
337   FAST_NATIVE_METHOD(Executable, getParameters0, "()[Ljava/lang/reflect/Parameter;"),
338   FAST_NATIVE_METHOD(Executable, getSignatureAnnotation, "()[Ljava/lang/String;"),
339   FAST_NATIVE_METHOD(Executable, isAnnotationPresentNative, "(Ljava/lang/Class;)Z"),
340 };
341 
register_java_lang_reflect_Executable(JNIEnv * env)342 void register_java_lang_reflect_Executable(JNIEnv* env) {
343   REGISTER_NATIVE_METHODS("java/lang/reflect/Executable");
344 }
345 
346 }  // namespace art
347