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