1 /*
2 * Copyright (C) 2011 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 "reflection-inl.h"
18
19 #include "art_field-inl.h"
20 #include "art_method-inl.h"
21 #include "base/enums.h"
22 #include "class_linker.h"
23 #include "common_throws.h"
24 #include "dex/dex_file-inl.h"
25 #include "indirect_reference_table-inl.h"
26 #include "java_vm_ext.h"
27 #include "jni_internal.h"
28 #include "mirror/class-inl.h"
29 #include "mirror/executable.h"
30 #include "mirror/object_array-inl.h"
31 #include "nativehelper/scoped_local_ref.h"
32 #include "nth_caller_visitor.h"
33 #include "scoped_thread_state_change-inl.h"
34 #include "stack_reference.h"
35 #include "well_known_classes.h"
36
37 namespace art {
38 namespace {
39
40 using android::base::StringPrintf;
41
42 class ArgArray {
43 public:
ArgArray(const char * shorty,uint32_t shorty_len)44 ArgArray(const char* shorty, uint32_t shorty_len)
45 : shorty_(shorty), shorty_len_(shorty_len), num_bytes_(0) {
46 size_t num_slots = shorty_len + 1; // +1 in case of receiver.
47 if (LIKELY((num_slots * 2) < kSmallArgArraySize)) {
48 // We can trivially use the small arg array.
49 arg_array_ = small_arg_array_;
50 } else {
51 // Analyze shorty to see if we need the large arg array.
52 for (size_t i = 1; i < shorty_len; ++i) {
53 char c = shorty[i];
54 if (c == 'J' || c == 'D') {
55 num_slots++;
56 }
57 }
58 if (num_slots <= kSmallArgArraySize) {
59 arg_array_ = small_arg_array_;
60 } else {
61 large_arg_array_.reset(new uint32_t[num_slots]);
62 arg_array_ = large_arg_array_.get();
63 }
64 }
65 }
66
GetArray()67 uint32_t* GetArray() {
68 return arg_array_;
69 }
70
GetNumBytes()71 uint32_t GetNumBytes() {
72 return num_bytes_;
73 }
74
Append(uint32_t value)75 void Append(uint32_t value) {
76 arg_array_[num_bytes_ / 4] = value;
77 num_bytes_ += 4;
78 }
79
Append(ObjPtr<mirror::Object> obj)80 void Append(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) {
81 Append(StackReference<mirror::Object>::FromMirrorPtr(obj.Ptr()).AsVRegValue());
82 }
83
AppendWide(uint64_t value)84 void AppendWide(uint64_t value) {
85 arg_array_[num_bytes_ / 4] = value;
86 arg_array_[(num_bytes_ / 4) + 1] = value >> 32;
87 num_bytes_ += 8;
88 }
89
AppendFloat(float value)90 void AppendFloat(float value) {
91 jvalue jv;
92 jv.f = value;
93 Append(jv.i);
94 }
95
AppendDouble(double value)96 void AppendDouble(double value) {
97 jvalue jv;
98 jv.d = value;
99 AppendWide(jv.j);
100 }
101
BuildArgArrayFromVarArgs(const ScopedObjectAccessAlreadyRunnable & soa,ObjPtr<mirror::Object> receiver,va_list ap)102 void BuildArgArrayFromVarArgs(const ScopedObjectAccessAlreadyRunnable& soa,
103 ObjPtr<mirror::Object> receiver,
104 va_list ap)
105 REQUIRES_SHARED(Locks::mutator_lock_) {
106 // Set receiver if non-null (method is not static)
107 if (receiver != nullptr) {
108 Append(receiver);
109 }
110 for (size_t i = 1; i < shorty_len_; ++i) {
111 switch (shorty_[i]) {
112 case 'Z':
113 case 'B':
114 case 'C':
115 case 'S':
116 case 'I':
117 Append(va_arg(ap, jint));
118 break;
119 case 'F':
120 AppendFloat(va_arg(ap, jdouble));
121 break;
122 case 'L':
123 Append(soa.Decode<mirror::Object>(va_arg(ap, jobject)));
124 break;
125 case 'D':
126 AppendDouble(va_arg(ap, jdouble));
127 break;
128 case 'J':
129 AppendWide(va_arg(ap, jlong));
130 break;
131 #ifndef NDEBUG
132 default:
133 LOG(FATAL) << "Unexpected shorty character: " << shorty_[i];
134 #endif
135 }
136 }
137 }
138
BuildArgArrayFromJValues(const ScopedObjectAccessAlreadyRunnable & soa,ObjPtr<mirror::Object> receiver,jvalue * args)139 void BuildArgArrayFromJValues(const ScopedObjectAccessAlreadyRunnable& soa,
140 ObjPtr<mirror::Object> receiver, jvalue* args)
141 REQUIRES_SHARED(Locks::mutator_lock_) {
142 // Set receiver if non-null (method is not static)
143 if (receiver != nullptr) {
144 Append(receiver);
145 }
146 for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) {
147 switch (shorty_[i]) {
148 case 'Z':
149 Append(args[args_offset].z);
150 break;
151 case 'B':
152 Append(args[args_offset].b);
153 break;
154 case 'C':
155 Append(args[args_offset].c);
156 break;
157 case 'S':
158 Append(args[args_offset].s);
159 break;
160 case 'I':
161 FALLTHROUGH_INTENDED;
162 case 'F':
163 Append(args[args_offset].i);
164 break;
165 case 'L':
166 Append(soa.Decode<mirror::Object>(args[args_offset].l));
167 break;
168 case 'D':
169 FALLTHROUGH_INTENDED;
170 case 'J':
171 AppendWide(args[args_offset].j);
172 break;
173 #ifndef NDEBUG
174 default:
175 LOG(FATAL) << "Unexpected shorty character: " << shorty_[i];
176 #endif
177 }
178 }
179 }
180
BuildArgArrayFromFrame(ShadowFrame * shadow_frame,uint32_t arg_offset)181 void BuildArgArrayFromFrame(ShadowFrame* shadow_frame, uint32_t arg_offset)
182 REQUIRES_SHARED(Locks::mutator_lock_) {
183 // Set receiver if non-null (method is not static)
184 size_t cur_arg = arg_offset;
185 if (!shadow_frame->GetMethod()->IsStatic()) {
186 Append(shadow_frame->GetVReg(cur_arg));
187 cur_arg++;
188 }
189 for (size_t i = 1; i < shorty_len_; ++i) {
190 switch (shorty_[i]) {
191 case 'Z':
192 case 'B':
193 case 'C':
194 case 'S':
195 case 'I':
196 case 'F':
197 case 'L':
198 Append(shadow_frame->GetVReg(cur_arg));
199 cur_arg++;
200 break;
201 case 'D':
202 case 'J':
203 AppendWide(shadow_frame->GetVRegLong(cur_arg));
204 cur_arg++;
205 cur_arg++;
206 break;
207 #ifndef NDEBUG
208 default:
209 LOG(FATAL) << "Unexpected shorty character: " << shorty_[i];
210 #endif
211 }
212 }
213 }
214
ThrowIllegalPrimitiveArgumentException(const char * expected,const char * found_descriptor)215 static void ThrowIllegalPrimitiveArgumentException(const char* expected,
216 const char* found_descriptor)
217 REQUIRES_SHARED(Locks::mutator_lock_) {
218 ThrowIllegalArgumentException(
219 StringPrintf("Invalid primitive conversion from %s to %s", expected,
220 PrettyDescriptor(found_descriptor).c_str()).c_str());
221 }
222
BuildArgArrayFromObjectArray(ObjPtr<mirror::Object> receiver,ObjPtr<mirror::ObjectArray<mirror::Object>> raw_args,ArtMethod * m,Thread * self)223 bool BuildArgArrayFromObjectArray(ObjPtr<mirror::Object> receiver,
224 ObjPtr<mirror::ObjectArray<mirror::Object>> raw_args,
225 ArtMethod* m,
226 Thread* self)
227 REQUIRES_SHARED(Locks::mutator_lock_) {
228 const DexFile::TypeList* classes = m->GetParameterTypeList();
229 // Set receiver if non-null (method is not static)
230 if (receiver != nullptr) {
231 Append(receiver);
232 }
233 StackHandleScope<2> hs(self);
234 MutableHandle<mirror::Object> arg(hs.NewHandle<mirror::Object>(nullptr));
235 Handle<mirror::ObjectArray<mirror::Object>> args(
236 hs.NewHandle<mirror::ObjectArray<mirror::Object>>(raw_args));
237 for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) {
238 arg.Assign(args->Get(args_offset));
239 if (((shorty_[i] == 'L') && (arg != nullptr)) ||
240 ((arg == nullptr && shorty_[i] != 'L'))) {
241 // TODO: The method's parameter's type must have been previously resolved, yet
242 // we've seen cases where it's not b/34440020.
243 ObjPtr<mirror::Class> dst_class(
244 m->ResolveClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_));
245 if (dst_class.Ptr() == nullptr) {
246 CHECK(self->IsExceptionPending());
247 return false;
248 }
249 if (UNLIKELY(arg == nullptr || !arg->InstanceOf(dst_class))) {
250 ThrowIllegalArgumentException(
251 StringPrintf("method %s argument %zd has type %s, got %s",
252 m->PrettyMethod(false).c_str(),
253 args_offset + 1, // Humans don't count from 0.
254 mirror::Class::PrettyDescriptor(dst_class).c_str(),
255 mirror::Object::PrettyTypeOf(arg.Get()).c_str()).c_str());
256 return false;
257 }
258 }
259
260 #define DO_FIRST_ARG(match_descriptor, get_fn, append) { \
261 if (LIKELY(arg != nullptr && \
262 arg->GetClass()->DescriptorEquals(match_descriptor))) { \
263 ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \
264 append(primitive_field-> get_fn(arg.Get()));
265
266 #define DO_ARG(match_descriptor, get_fn, append) \
267 } else if (LIKELY(arg != nullptr && \
268 arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
269 ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \
270 append(primitive_field-> get_fn(arg.Get()));
271
272 #define DO_FAIL(expected) \
273 } else { \
274 if (arg->GetClass<>()->IsPrimitive()) { \
275 std::string temp; \
276 ThrowIllegalPrimitiveArgumentException(expected, \
277 arg->GetClass<>()->GetDescriptor(&temp)); \
278 } else { \
279 ThrowIllegalArgumentException(\
280 StringPrintf("method %s argument %zd has type %s, got %s", \
281 ArtMethod::PrettyMethod(m, false).c_str(), \
282 args_offset + 1, \
283 expected, \
284 mirror::Object::PrettyTypeOf(arg.Get()).c_str()).c_str()); \
285 } \
286 return false; \
287 } }
288
289 switch (shorty_[i]) {
290 case 'L':
291 Append(arg.Get());
292 break;
293 case 'Z':
294 DO_FIRST_ARG("Ljava/lang/Boolean;", GetBoolean, Append)
295 DO_FAIL("boolean")
296 break;
297 case 'B':
298 DO_FIRST_ARG("Ljava/lang/Byte;", GetByte, Append)
299 DO_FAIL("byte")
300 break;
301 case 'C':
302 DO_FIRST_ARG("Ljava/lang/Character;", GetChar, Append)
303 DO_FAIL("char")
304 break;
305 case 'S':
306 DO_FIRST_ARG("Ljava/lang/Short;", GetShort, Append)
307 DO_ARG("Ljava/lang/Byte;", GetByte, Append)
308 DO_FAIL("short")
309 break;
310 case 'I':
311 DO_FIRST_ARG("Ljava/lang/Integer;", GetInt, Append)
312 DO_ARG("Ljava/lang/Character;", GetChar, Append)
313 DO_ARG("Ljava/lang/Short;", GetShort, Append)
314 DO_ARG("Ljava/lang/Byte;", GetByte, Append)
315 DO_FAIL("int")
316 break;
317 case 'J':
318 DO_FIRST_ARG("Ljava/lang/Long;", GetLong, AppendWide)
319 DO_ARG("Ljava/lang/Integer;", GetInt, AppendWide)
320 DO_ARG("Ljava/lang/Character;", GetChar, AppendWide)
321 DO_ARG("Ljava/lang/Short;", GetShort, AppendWide)
322 DO_ARG("Ljava/lang/Byte;", GetByte, AppendWide)
323 DO_FAIL("long")
324 break;
325 case 'F':
326 DO_FIRST_ARG("Ljava/lang/Float;", GetFloat, AppendFloat)
327 DO_ARG("Ljava/lang/Long;", GetLong, AppendFloat)
328 DO_ARG("Ljava/lang/Integer;", GetInt, AppendFloat)
329 DO_ARG("Ljava/lang/Character;", GetChar, AppendFloat)
330 DO_ARG("Ljava/lang/Short;", GetShort, AppendFloat)
331 DO_ARG("Ljava/lang/Byte;", GetByte, AppendFloat)
332 DO_FAIL("float")
333 break;
334 case 'D':
335 DO_FIRST_ARG("Ljava/lang/Double;", GetDouble, AppendDouble)
336 DO_ARG("Ljava/lang/Float;", GetFloat, AppendDouble)
337 DO_ARG("Ljava/lang/Long;", GetLong, AppendDouble)
338 DO_ARG("Ljava/lang/Integer;", GetInt, AppendDouble)
339 DO_ARG("Ljava/lang/Character;", GetChar, AppendDouble)
340 DO_ARG("Ljava/lang/Short;", GetShort, AppendDouble)
341 DO_ARG("Ljava/lang/Byte;", GetByte, AppendDouble)
342 DO_FAIL("double")
343 break;
344 #ifndef NDEBUG
345 default:
346 LOG(FATAL) << "Unexpected shorty character: " << shorty_[i];
347 UNREACHABLE();
348 #endif
349 }
350 #undef DO_FIRST_ARG
351 #undef DO_ARG
352 #undef DO_FAIL
353 }
354 return true;
355 }
356
357 private:
358 enum { kSmallArgArraySize = 16 };
359 const char* const shorty_;
360 const uint32_t shorty_len_;
361 uint32_t num_bytes_;
362 uint32_t* arg_array_;
363 uint32_t small_arg_array_[kSmallArgArraySize];
364 std::unique_ptr<uint32_t[]> large_arg_array_;
365 };
366
CheckMethodArguments(JavaVMExt * vm,ArtMethod * m,uint32_t * args)367 void CheckMethodArguments(JavaVMExt* vm, ArtMethod* m, uint32_t* args)
368 REQUIRES_SHARED(Locks::mutator_lock_) {
369 const DexFile::TypeList* params = m->GetParameterTypeList();
370 if (params == nullptr) {
371 return; // No arguments so nothing to check.
372 }
373 uint32_t offset = 0;
374 uint32_t num_params = params->Size();
375 size_t error_count = 0;
376 if (!m->IsStatic()) {
377 offset = 1;
378 }
379 // TODO: If args contain object references, it may cause problems.
380 Thread* const self = Thread::Current();
381 for (uint32_t i = 0; i < num_params; i++) {
382 dex::TypeIndex type_idx = params->GetTypeItem(i).type_idx_;
383 ObjPtr<mirror::Class> param_type(m->ResolveClassFromTypeIndex(type_idx));
384 if (param_type == nullptr) {
385 CHECK(self->IsExceptionPending());
386 LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: "
387 << m->GetTypeDescriptorFromTypeIdx(type_idx) << "\n"
388 << self->GetException()->Dump();
389 self->ClearException();
390 ++error_count;
391 } else if (!param_type->IsPrimitive()) {
392 // TODO: There is a compaction bug here since GetClassFromTypeIdx can cause thread suspension,
393 // this is a hard to fix problem since the args can contain Object*, we need to save and
394 // restore them by using a visitor similar to the ones used in the trampoline entrypoints.
395 ObjPtr<mirror::Object> argument =
396 (reinterpret_cast<StackReference<mirror::Object>*>(&args[i + offset]))->AsMirrorPtr();
397 if (argument != nullptr && !argument->InstanceOf(param_type)) {
398 LOG(ERROR) << "JNI ERROR (app bug): attempt to pass an instance of "
399 << argument->PrettyTypeOf() << " as argument " << (i + 1)
400 << " to " << m->PrettyMethod();
401 ++error_count;
402 }
403 } else if (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble()) {
404 offset++;
405 } else {
406 int32_t arg = static_cast<int32_t>(args[i + offset]);
407 if (param_type->IsPrimitiveBoolean()) {
408 if (arg != JNI_TRUE && arg != JNI_FALSE) {
409 LOG(ERROR) << "JNI ERROR (app bug): expected jboolean (0/1) but got value of "
410 << arg << " as argument " << (i + 1) << " to " << m->PrettyMethod();
411 ++error_count;
412 }
413 } else if (param_type->IsPrimitiveByte()) {
414 if (arg < -128 || arg > 127) {
415 LOG(ERROR) << "JNI ERROR (app bug): expected jbyte but got value of "
416 << arg << " as argument " << (i + 1) << " to " << m->PrettyMethod();
417 ++error_count;
418 }
419 } else if (param_type->IsPrimitiveChar()) {
420 if (args[i + offset] > 0xFFFF) {
421 LOG(ERROR) << "JNI ERROR (app bug): expected jchar but got value of "
422 << arg << " as argument " << (i + 1) << " to " << m->PrettyMethod();
423 ++error_count;
424 }
425 } else if (param_type->IsPrimitiveShort()) {
426 if (arg < -32768 || arg > 0x7FFF) {
427 LOG(ERROR) << "JNI ERROR (app bug): expected jshort but got value of "
428 << arg << " as argument " << (i + 1) << " to " << m->PrettyMethod();
429 ++error_count;
430 }
431 }
432 }
433 }
434 if (UNLIKELY(error_count > 0)) {
435 // TODO: pass the JNI function name (such as "CallVoidMethodV") through so we can call JniAbort
436 // with an argument.
437 vm->JniAbortF(nullptr, "bad arguments passed to %s (see above for details)",
438 m->PrettyMethod().c_str());
439 }
440 }
441
FindVirtualMethod(ObjPtr<mirror::Object> receiver,ArtMethod * method)442 ArtMethod* FindVirtualMethod(ObjPtr<mirror::Object> receiver, ArtMethod* method)
443 REQUIRES_SHARED(Locks::mutator_lock_) {
444 return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method, kRuntimePointerSize);
445 }
446
447
InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable & soa,ArtMethod * method,ArgArray * arg_array,JValue * result,const char * shorty)448 void InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable& soa,
449 ArtMethod* method, ArgArray* arg_array, JValue* result,
450 const char* shorty)
451 REQUIRES_SHARED(Locks::mutator_lock_) {
452 uint32_t* args = arg_array->GetArray();
453 if (UNLIKELY(soa.Env()->IsCheckJniEnabled())) {
454 CheckMethodArguments(soa.Vm(), method->GetInterfaceMethodIfProxy(kRuntimePointerSize), args);
455 }
456 method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, shorty);
457 }
458
459 } // anonymous namespace
460
InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable & soa,jobject obj,jmethodID mid,va_list args)461 JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid,
462 va_list args)
463 REQUIRES_SHARED(Locks::mutator_lock_) {
464 // We want to make sure that the stack is not within a small distance from the
465 // protected region in case we are calling into a leaf function whose stack
466 // check has been elided.
467 if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) {
468 ThrowStackOverflowError(soa.Self());
469 return JValue();
470 }
471
472 ArtMethod* method = jni::DecodeArtMethod(mid);
473 bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
474 if (is_string_init) {
475 // Replace calls to String.<init> with equivalent StringFactory call.
476 method = WellKnownClasses::StringInitToStringFactory(method);
477 }
478 ObjPtr<mirror::Object> receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object>(obj);
479 uint32_t shorty_len = 0;
480 const char* shorty =
481 method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
482 JValue result;
483 ArgArray arg_array(shorty, shorty_len);
484 arg_array.BuildArgArrayFromVarArgs(soa, receiver, args);
485 InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
486 if (is_string_init) {
487 // For string init, remap original receiver to StringFactory result.
488 UpdateReference(soa.Self(), obj, result.GetL());
489 }
490 return result;
491 }
492
InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable & soa,jobject obj,jmethodID mid,jvalue * args)493 JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid,
494 jvalue* args) {
495 // We want to make sure that the stack is not within a small distance from the
496 // protected region in case we are calling into a leaf function whose stack
497 // check has been elided.
498 if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) {
499 ThrowStackOverflowError(soa.Self());
500 return JValue();
501 }
502
503 ArtMethod* method = jni::DecodeArtMethod(mid);
504 bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
505 if (is_string_init) {
506 // Replace calls to String.<init> with equivalent StringFactory call.
507 method = WellKnownClasses::StringInitToStringFactory(method);
508 }
509 ObjPtr<mirror::Object> receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object>(obj);
510 uint32_t shorty_len = 0;
511 const char* shorty =
512 method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
513 JValue result;
514 ArgArray arg_array(shorty, shorty_len);
515 arg_array.BuildArgArrayFromJValues(soa, receiver, args);
516 InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
517 if (is_string_init) {
518 // For string init, remap original receiver to StringFactory result.
519 UpdateReference(soa.Self(), obj, result.GetL());
520 }
521 return result;
522 }
523
InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable & soa,jobject obj,jmethodID mid,jvalue * args)524 JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable& soa,
525 jobject obj, jmethodID mid, jvalue* args) {
526 // We want to make sure that the stack is not within a small distance from the
527 // protected region in case we are calling into a leaf function whose stack
528 // check has been elided.
529 if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) {
530 ThrowStackOverflowError(soa.Self());
531 return JValue();
532 }
533
534 ObjPtr<mirror::Object> receiver = soa.Decode<mirror::Object>(obj);
535 ArtMethod* method = FindVirtualMethod(receiver, jni::DecodeArtMethod(mid));
536 bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
537 if (is_string_init) {
538 // Replace calls to String.<init> with equivalent StringFactory call.
539 method = WellKnownClasses::StringInitToStringFactory(method);
540 receiver = nullptr;
541 }
542 uint32_t shorty_len = 0;
543 const char* shorty =
544 method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
545 JValue result;
546 ArgArray arg_array(shorty, shorty_len);
547 arg_array.BuildArgArrayFromJValues(soa, receiver, args);
548 InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
549 if (is_string_init) {
550 // For string init, remap original receiver to StringFactory result.
551 UpdateReference(soa.Self(), obj, result.GetL());
552 }
553 return result;
554 }
555
InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnable & soa,jobject obj,jmethodID mid,va_list args)556 JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa,
557 jobject obj, jmethodID mid, va_list args) {
558 // We want to make sure that the stack is not within a small distance from the
559 // protected region in case we are calling into a leaf function whose stack
560 // check has been elided.
561 if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) {
562 ThrowStackOverflowError(soa.Self());
563 return JValue();
564 }
565
566 ObjPtr<mirror::Object> receiver = soa.Decode<mirror::Object>(obj);
567 ArtMethod* method = FindVirtualMethod(receiver, jni::DecodeArtMethod(mid));
568 bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
569 if (is_string_init) {
570 // Replace calls to String.<init> with equivalent StringFactory call.
571 method = WellKnownClasses::StringInitToStringFactory(method);
572 receiver = nullptr;
573 }
574 uint32_t shorty_len = 0;
575 const char* shorty =
576 method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
577 JValue result;
578 ArgArray arg_array(shorty, shorty_len);
579 arg_array.BuildArgArrayFromVarArgs(soa, receiver, args);
580 InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
581 if (is_string_init) {
582 // For string init, remap original receiver to StringFactory result.
583 UpdateReference(soa.Self(), obj, result.GetL());
584 }
585 return result;
586 }
587
InvokeMethod(const ScopedObjectAccessAlreadyRunnable & soa,jobject javaMethod,jobject javaReceiver,jobject javaArgs,size_t num_frames)588 jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaMethod,
589 jobject javaReceiver, jobject javaArgs, size_t num_frames) {
590 // We want to make sure that the stack is not within a small distance from the
591 // protected region in case we are calling into a leaf function whose stack
592 // check has been elided.
593 if (UNLIKELY(__builtin_frame_address(0) <
594 soa.Self()->GetStackEndForInterpreter(true))) {
595 ThrowStackOverflowError(soa.Self());
596 return nullptr;
597 }
598
599 ObjPtr<mirror::Executable> executable = soa.Decode<mirror::Executable>(javaMethod);
600 const bool accessible = executable->IsAccessible();
601 ArtMethod* m = executable->GetArtMethod();
602
603 ObjPtr<mirror::Class> declaring_class = m->GetDeclaringClass();
604 if (UNLIKELY(!declaring_class->IsInitialized())) {
605 StackHandleScope<1> hs(soa.Self());
606 HandleWrapperObjPtr<mirror::Class> h_class(hs.NewHandleWrapper(&declaring_class));
607 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(soa.Self(), h_class, true, true)) {
608 return nullptr;
609 }
610 }
611
612 ObjPtr<mirror::Object> receiver;
613 if (!m->IsStatic()) {
614 // Replace calls to String.<init> with equivalent StringFactory call.
615 if (declaring_class->IsStringClass() && m->IsConstructor()) {
616 m = WellKnownClasses::StringInitToStringFactory(m);
617 CHECK(javaReceiver == nullptr);
618 } else {
619 // Check that the receiver is non-null and an instance of the field's declaring class.
620 receiver = soa.Decode<mirror::Object>(javaReceiver);
621 if (!VerifyObjectIsClass(receiver, declaring_class)) {
622 return nullptr;
623 }
624
625 // Find the actual implementation of the virtual method.
626 m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m, kRuntimePointerSize);
627 }
628 }
629
630 // Get our arrays of arguments and their types, and check they're the same size.
631 ObjPtr<mirror::ObjectArray<mirror::Object>> objects =
632 soa.Decode<mirror::ObjectArray<mirror::Object>>(javaArgs);
633 auto* np_method = m->GetInterfaceMethodIfProxy(kRuntimePointerSize);
634 const DexFile::TypeList* classes = np_method->GetParameterTypeList();
635 uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size();
636 uint32_t arg_count = (objects != nullptr) ? objects->GetLength() : 0;
637 if (arg_count != classes_size) {
638 ThrowIllegalArgumentException(StringPrintf("Wrong number of arguments; expected %d, got %d",
639 classes_size, arg_count).c_str());
640 return nullptr;
641 }
642
643 // If method is not set to be accessible, verify it can be accessed by the caller.
644 ObjPtr<mirror::Class> calling_class;
645 if (!accessible && !VerifyAccess(soa.Self(),
646 receiver,
647 declaring_class,
648 m->GetAccessFlags(),
649 &calling_class,
650 num_frames)) {
651 ThrowIllegalAccessException(
652 StringPrintf("Class %s cannot access %s method %s of class %s",
653 calling_class == nullptr ? "null" : calling_class->PrettyClass().c_str(),
654 PrettyJavaAccessFlags(m->GetAccessFlags()).c_str(),
655 m->PrettyMethod().c_str(),
656 m->GetDeclaringClass() == nullptr ? "null" :
657 m->GetDeclaringClass()->PrettyClass().c_str()).c_str());
658 return nullptr;
659 }
660
661 // Invoke the method.
662 JValue result;
663 uint32_t shorty_len = 0;
664 const char* shorty = np_method->GetShorty(&shorty_len);
665 ArgArray arg_array(shorty, shorty_len);
666 if (!arg_array.BuildArgArrayFromObjectArray(receiver, objects, np_method, soa.Self())) {
667 CHECK(soa.Self()->IsExceptionPending());
668 return nullptr;
669 }
670
671 InvokeWithArgArray(soa, m, &arg_array, &result, shorty);
672
673 // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early.
674 if (soa.Self()->IsExceptionPending()) {
675 // If we get another exception when we are trying to wrap, then just use that instead.
676 ScopedLocalRef<jthrowable> th(soa.Env(), soa.Env()->ExceptionOccurred());
677 soa.Self()->ClearException();
678 jclass exception_class = soa.Env()->FindClass("java/lang/reflect/InvocationTargetException");
679 if (exception_class == nullptr) {
680 soa.Self()->AssertPendingException();
681 return nullptr;
682 }
683 jmethodID mid = soa.Env()->GetMethodID(exception_class, "<init>", "(Ljava/lang/Throwable;)V");
684 CHECK(mid != nullptr);
685 jobject exception_instance = soa.Env()->NewObject(exception_class, mid, th.get());
686 if (exception_instance == nullptr) {
687 soa.Self()->AssertPendingException();
688 return nullptr;
689 }
690 soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance));
691 return nullptr;
692 }
693
694 // Box if necessary and return.
695 return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result));
696 }
697
BoxPrimitive(Primitive::Type src_class,const JValue & value)698 ObjPtr<mirror::Object> BoxPrimitive(Primitive::Type src_class, const JValue& value) {
699 if (src_class == Primitive::kPrimNot) {
700 return MakeObjPtr(value.GetL());
701 }
702 if (src_class == Primitive::kPrimVoid) {
703 // There's no such thing as a void field, and void methods invoked via reflection return null.
704 return nullptr;
705 }
706
707 jmethodID m = nullptr;
708 const char* shorty;
709 switch (src_class) {
710 case Primitive::kPrimBoolean:
711 m = WellKnownClasses::java_lang_Boolean_valueOf;
712 shorty = "LZ";
713 break;
714 case Primitive::kPrimByte:
715 m = WellKnownClasses::java_lang_Byte_valueOf;
716 shorty = "LB";
717 break;
718 case Primitive::kPrimChar:
719 m = WellKnownClasses::java_lang_Character_valueOf;
720 shorty = "LC";
721 break;
722 case Primitive::kPrimDouble:
723 m = WellKnownClasses::java_lang_Double_valueOf;
724 shorty = "LD";
725 break;
726 case Primitive::kPrimFloat:
727 m = WellKnownClasses::java_lang_Float_valueOf;
728 shorty = "LF";
729 break;
730 case Primitive::kPrimInt:
731 m = WellKnownClasses::java_lang_Integer_valueOf;
732 shorty = "LI";
733 break;
734 case Primitive::kPrimLong:
735 m = WellKnownClasses::java_lang_Long_valueOf;
736 shorty = "LJ";
737 break;
738 case Primitive::kPrimShort:
739 m = WellKnownClasses::java_lang_Short_valueOf;
740 shorty = "LS";
741 break;
742 default:
743 LOG(FATAL) << static_cast<int>(src_class);
744 shorty = nullptr;
745 }
746
747 ScopedObjectAccessUnchecked soa(Thread::Current());
748 DCHECK_EQ(soa.Self()->GetState(), kRunnable);
749
750 ArgArray arg_array(shorty, 2);
751 JValue result;
752 if (src_class == Primitive::kPrimDouble || src_class == Primitive::kPrimLong) {
753 arg_array.AppendWide(value.GetJ());
754 } else {
755 arg_array.Append(value.GetI());
756 }
757
758 jni::DecodeArtMethod(m)->Invoke(soa.Self(),
759 arg_array.GetArray(),
760 arg_array.GetNumBytes(),
761 &result,
762 shorty);
763 return result.GetL();
764 }
765
UnboxingFailureKind(ArtField * f)766 static std::string UnboxingFailureKind(ArtField* f)
767 REQUIRES_SHARED(Locks::mutator_lock_) {
768 if (f != nullptr) {
769 return "field " + f->PrettyField(false);
770 }
771 return "result";
772 }
773
UnboxPrimitive(ObjPtr<mirror::Object> o,ObjPtr<mirror::Class> dst_class,ArtField * f,JValue * unboxed_value)774 static bool UnboxPrimitive(ObjPtr<mirror::Object> o,
775 ObjPtr<mirror::Class> dst_class,
776 ArtField* f,
777 JValue* unboxed_value)
778 REQUIRES_SHARED(Locks::mutator_lock_) {
779 bool unbox_for_result = (f == nullptr);
780 if (!dst_class->IsPrimitive()) {
781 if (UNLIKELY(o != nullptr && !o->InstanceOf(dst_class))) {
782 if (!unbox_for_result) {
783 ThrowIllegalArgumentException(
784 StringPrintf("%s has type %s, got %s",
785 UnboxingFailureKind(f).c_str(),
786 dst_class->PrettyDescriptor().c_str(),
787 o->PrettyTypeOf().c_str()).c_str());
788 } else {
789 ThrowClassCastException(
790 StringPrintf("Couldn't convert result of type %s to %s",
791 o->PrettyTypeOf().c_str(),
792 dst_class->PrettyDescriptor().c_str()).c_str());
793 }
794 return false;
795 }
796 unboxed_value->SetL(o);
797 return true;
798 }
799 if (UNLIKELY(dst_class->GetPrimitiveType() == Primitive::kPrimVoid)) {
800 ThrowIllegalArgumentException(StringPrintf("Can't unbox %s to void",
801 UnboxingFailureKind(f).c_str()).c_str());
802 return false;
803 }
804 if (UNLIKELY(o == nullptr)) {
805 if (!unbox_for_result) {
806 ThrowIllegalArgumentException(
807 StringPrintf("%s has type %s, got null",
808 UnboxingFailureKind(f).c_str(),
809 dst_class->PrettyDescriptor().c_str()).c_str());
810 } else {
811 ThrowNullPointerException(
812 StringPrintf("Expected to unbox a '%s' primitive type but was returned null",
813 dst_class->PrettyDescriptor().c_str()).c_str());
814 }
815 return false;
816 }
817
818 JValue boxed_value;
819 ObjPtr<mirror::Class> klass = o->GetClass();
820 ObjPtr<mirror::Class> src_class = nullptr;
821 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
822 ArtField* primitive_field = &klass->GetIFieldsPtr()->At(0);
823 if (klass->DescriptorEquals("Ljava/lang/Boolean;")) {
824 src_class = class_linker->FindPrimitiveClass('Z');
825 boxed_value.SetZ(primitive_field->GetBoolean(o));
826 } else if (klass->DescriptorEquals("Ljava/lang/Byte;")) {
827 src_class = class_linker->FindPrimitiveClass('B');
828 boxed_value.SetB(primitive_field->GetByte(o));
829 } else if (klass->DescriptorEquals("Ljava/lang/Character;")) {
830 src_class = class_linker->FindPrimitiveClass('C');
831 boxed_value.SetC(primitive_field->GetChar(o));
832 } else if (klass->DescriptorEquals("Ljava/lang/Float;")) {
833 src_class = class_linker->FindPrimitiveClass('F');
834 boxed_value.SetF(primitive_field->GetFloat(o));
835 } else if (klass->DescriptorEquals("Ljava/lang/Double;")) {
836 src_class = class_linker->FindPrimitiveClass('D');
837 boxed_value.SetD(primitive_field->GetDouble(o));
838 } else if (klass->DescriptorEquals("Ljava/lang/Integer;")) {
839 src_class = class_linker->FindPrimitiveClass('I');
840 boxed_value.SetI(primitive_field->GetInt(o));
841 } else if (klass->DescriptorEquals("Ljava/lang/Long;")) {
842 src_class = class_linker->FindPrimitiveClass('J');
843 boxed_value.SetJ(primitive_field->GetLong(o));
844 } else if (klass->DescriptorEquals("Ljava/lang/Short;")) {
845 src_class = class_linker->FindPrimitiveClass('S');
846 boxed_value.SetS(primitive_field->GetShort(o));
847 } else {
848 std::string temp;
849 ThrowIllegalArgumentException(
850 StringPrintf("%s has type %s, got %s", UnboxingFailureKind(f).c_str(),
851 dst_class->PrettyDescriptor().c_str(),
852 PrettyDescriptor(o->GetClass()->GetDescriptor(&temp)).c_str()).c_str());
853 return false;
854 }
855
856 return ConvertPrimitiveValue(unbox_for_result,
857 src_class->GetPrimitiveType(), dst_class->GetPrimitiveType(),
858 boxed_value, unboxed_value);
859 }
860
UnboxPrimitiveForField(ObjPtr<mirror::Object> o,ObjPtr<mirror::Class> dst_class,ArtField * f,JValue * unboxed_value)861 bool UnboxPrimitiveForField(ObjPtr<mirror::Object> o,
862 ObjPtr<mirror::Class> dst_class,
863 ArtField* f,
864 JValue* unboxed_value) {
865 DCHECK(f != nullptr);
866 return UnboxPrimitive(o, dst_class, f, unboxed_value);
867 }
868
UnboxPrimitiveForResult(ObjPtr<mirror::Object> o,ObjPtr<mirror::Class> dst_class,JValue * unboxed_value)869 bool UnboxPrimitiveForResult(ObjPtr<mirror::Object> o,
870 ObjPtr<mirror::Class> dst_class,
871 JValue* unboxed_value) {
872 return UnboxPrimitive(o, dst_class, nullptr, unboxed_value);
873 }
874
GetCallingClass(Thread * self,size_t num_frames)875 ObjPtr<mirror::Class> GetCallingClass(Thread* self, size_t num_frames) {
876 NthCallerVisitor visitor(self, num_frames);
877 visitor.WalkStack();
878 return visitor.caller != nullptr ? visitor.caller->GetDeclaringClass() : nullptr;
879 }
880
VerifyAccess(Thread * self,ObjPtr<mirror::Object> obj,ObjPtr<mirror::Class> declaring_class,uint32_t access_flags,ObjPtr<mirror::Class> * calling_class,size_t num_frames)881 bool VerifyAccess(Thread* self,
882 ObjPtr<mirror::Object> obj,
883 ObjPtr<mirror::Class> declaring_class,
884 uint32_t access_flags,
885 ObjPtr<mirror::Class>* calling_class,
886 size_t num_frames) {
887 if ((access_flags & kAccPublic) != 0) {
888 return true;
889 }
890 ObjPtr<mirror::Class> klass = GetCallingClass(self, num_frames);
891 if (UNLIKELY(klass == nullptr)) {
892 // The caller is an attached native thread.
893 return false;
894 }
895 *calling_class = klass;
896 return VerifyAccess(obj, declaring_class, access_flags, klass);
897 }
898
VerifyAccess(ObjPtr<mirror::Object> obj,ObjPtr<mirror::Class> declaring_class,uint32_t access_flags,ObjPtr<mirror::Class> calling_class)899 bool VerifyAccess(ObjPtr<mirror::Object> obj,
900 ObjPtr<mirror::Class> declaring_class,
901 uint32_t access_flags,
902 ObjPtr<mirror::Class> calling_class) {
903 if (calling_class == declaring_class) {
904 return true;
905 }
906 ScopedAssertNoThreadSuspension sants("verify-access");
907 if ((access_flags & kAccPrivate) != 0) {
908 return false;
909 }
910 if ((access_flags & kAccProtected) != 0) {
911 if (obj != nullptr && !obj->InstanceOf(calling_class) &&
912 !declaring_class->IsInSamePackage(calling_class)) {
913 return false;
914 } else if (declaring_class->IsAssignableFrom(calling_class)) {
915 return true;
916 }
917 }
918 return declaring_class->IsInSamePackage(calling_class);
919 }
920
InvalidReceiverError(ObjPtr<mirror::Object> o,ObjPtr<mirror::Class> c)921 void InvalidReceiverError(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c) {
922 std::string expected_class_name(mirror::Class::PrettyDescriptor(c));
923 std::string actual_class_name(mirror::Object::PrettyTypeOf(o));
924 ThrowIllegalArgumentException(StringPrintf("Expected receiver of type %s, but got %s",
925 expected_class_name.c_str(),
926 actual_class_name.c_str()).c_str());
927 }
928
929 // This only works if there's one reference which points to the object in obj.
930 // Will need to be fixed if there's cases where it's not.
UpdateReference(Thread * self,jobject obj,ObjPtr<mirror::Object> result)931 void UpdateReference(Thread* self, jobject obj, ObjPtr<mirror::Object> result) {
932 IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
933 IndirectRefKind kind = IndirectReferenceTable::GetIndirectRefKind(ref);
934 if (kind == kLocal) {
935 self->GetJniEnv()->UpdateLocal(obj, result);
936 } else if (kind == kHandleScopeOrInvalid) {
937 LOG(FATAL) << "Unsupported UpdateReference for kind kHandleScopeOrInvalid";
938 } else if (kind == kGlobal) {
939 self->GetJniEnv()->GetVm()->UpdateGlobal(self, ref, result);
940 } else {
941 DCHECK_EQ(kind, kWeakGlobal);
942 self->GetJniEnv()->GetVm()->UpdateWeakGlobal(self, ref, result);
943 }
944 }
945
946 } // namespace art
947