check_jni.cc revision 3398c7874e002beaa6c2b2fadf183e7d1ddad23a
1/*
2 * Copyright (C) 2008 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 "check_jni.h"
18
19#include <iomanip>
20#include <sys/mman.h>
21#include <zlib.h>
22
23#include "art_field-inl.h"
24#include "art_method-inl.h"
25#include "base/logging.h"
26#include "base/to_str.h"
27#include "class_linker.h"
28#include "class_linker-inl.h"
29#include "dex_file-inl.h"
30#include "gc/space/space.h"
31#include "java_vm_ext.h"
32#include "jni_internal.h"
33#include "mirror/class-inl.h"
34#include "mirror/object-inl.h"
35#include "mirror/object_array-inl.h"
36#include "mirror/string-inl.h"
37#include "mirror/throwable.h"
38#include "runtime.h"
39#include "scoped_thread_state_change-inl.h"
40#include "thread.h"
41#include "well_known_classes.h"
42
43namespace art {
44
45/*
46 * ===========================================================================
47 *      JNI function helpers
48 * ===========================================================================
49 */
50
51// Flags passed into ScopedCheck.
52#define kFlag_Default       0x0000
53
54#define kFlag_CritBad       0x0000      // Calling while in critical is not allowed.
55#define kFlag_CritOkay      0x0001      // Calling while in critical is allowed.
56#define kFlag_CritGet       0x0002      // This is a critical "get".
57#define kFlag_CritRelease   0x0003      // This is a critical "release".
58#define kFlag_CritMask      0x0003      // Bit mask to get "crit" value.
59
60#define kFlag_ExcepBad      0x0000      // Raised exceptions are not allowed.
61#define kFlag_ExcepOkay     0x0004      // Raised exceptions are allowed.
62
63#define kFlag_Release       0x0010      // Are we in a non-critical release function?
64#define kFlag_NullableUtf   0x0020      // Are our UTF parameters nullable?
65
66#define kFlag_Invocation    0x8000      // Part of the invocation interface (JavaVM*).
67
68#define kFlag_ForceTrace    0x80000000  // Add this to a JNI function's flags if you want to trace every call.
69
70class VarArgs;
71/*
72 * Java primitive types:
73 * B - jbyte
74 * C - jchar
75 * D - jdouble
76 * F - jfloat
77 * I - jint
78 * J - jlong
79 * S - jshort
80 * Z - jboolean (shown as true and false)
81 * V - void
82 *
83 * Java reference types:
84 * L - jobject
85 * a - jarray
86 * c - jclass
87 * s - jstring
88 * t - jthrowable
89 *
90 * JNI types:
91 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
92 * f - jfieldID
93 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
94 * m - jmethodID
95 * p - void*
96 * r - jint (for release mode arguments)
97 * u - const char* (Modified UTF-8)
98 * z - jsize (for lengths; use i if negative values are okay)
99 * v - JavaVM*
100 * w - jobjectRefType
101 * E - JNIEnv*
102 * . - no argument; just print "..." (used for varargs JNI calls)
103 *
104 */
105union JniValueType {
106  jarray a;
107  jboolean b;
108  jclass c;
109  jfieldID f;
110  jint i;
111  jmethodID m;
112  const void* p;  // Pointer.
113  jint r;  // Release mode.
114  jstring s;
115  jthrowable t;
116  const char* u;  // Modified UTF-8.
117  JavaVM* v;
118  jobjectRefType w;
119  jsize z;
120  jbyte B;
121  jchar C;
122  jdouble D;
123  JNIEnv* E;
124  jfloat F;
125  jint I;
126  jlong J;
127  jobject L;
128  jshort S;
129  const void* V;  // void
130  jboolean Z;
131  const VarArgs* va;
132};
133
134/*
135 * A structure containing all the information needed to validate varargs arguments.
136 *
137 * Note that actually getting the arguments from this structure mutates it so should only be done on
138 * owned copies.
139 */
140class VarArgs {
141 public:
142  VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
143    va_copy(vargs_, var);
144  }
145
146  VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
147
148  ~VarArgs() {
149    if (type_ == kTypeVaList) {
150      va_end(vargs_);
151    }
152  }
153
154  VarArgs(VarArgs&& other) {
155    m_ = other.m_;
156    cnt_ = other.cnt_;
157    type_ = other.type_;
158    if (other.type_ == kTypeVaList) {
159      va_copy(vargs_, other.vargs_);
160    } else {
161      ptr_ = other.ptr_;
162    }
163  }
164
165  // This method is const because we need to ensure that one only uses the GetValue method on an
166  // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
167  // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
168  // we want to use one we need to Clone() it.
169  VarArgs Clone() const {
170    if (type_ == kTypeVaList) {
171      // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
172      // messed up if the source argument is not the exact type 'va_list'.
173      return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
174    } else {
175      return VarArgs(m_, cnt_, ptr_);
176    }
177  }
178
179  jmethodID GetMethodID() const {
180    return m_;
181  }
182
183  JniValueType GetValue(char fmt) {
184    JniValueType o;
185    if (type_ == kTypeVaList) {
186      switch (fmt) {
187        case 'Z': o.Z = static_cast<jboolean>(va_arg(vargs_, jint)); break;
188        case 'B': o.B = static_cast<jbyte>(va_arg(vargs_, jint)); break;
189        case 'C': o.C = static_cast<jchar>(va_arg(vargs_, jint)); break;
190        case 'S': o.S = static_cast<jshort>(va_arg(vargs_, jint)); break;
191        case 'I': o.I = va_arg(vargs_, jint); break;
192        case 'J': o.J = va_arg(vargs_, jlong); break;
193        case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
194        case 'D': o.D = va_arg(vargs_, jdouble); break;
195        case 'L': o.L = va_arg(vargs_, jobject); break;
196        default:
197          LOG(FATAL) << "Illegal type format char " << fmt;
198          UNREACHABLE();
199      }
200    } else {
201      CHECK(type_ == kTypePtr);
202      jvalue v = ptr_[cnt_];
203      cnt_++;
204      switch (fmt) {
205        case 'Z': o.Z = v.z; break;
206        case 'B': o.B = v.b; break;
207        case 'C': o.C = v.c; break;
208        case 'S': o.S = v.s; break;
209        case 'I': o.I = v.i; break;
210        case 'J': o.J = v.j; break;
211        case 'F': o.F = v.f; break;
212        case 'D': o.D = v.d; break;
213        case 'L': o.L = v.l; break;
214        default:
215          LOG(FATAL) << "Illegal type format char " << fmt;
216          UNREACHABLE();
217      }
218    }
219    return o;
220  }
221
222 private:
223  VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
224    va_copy(vargs_, var);
225  }
226
227  VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
228
229  enum VarArgsType {
230    kTypeVaList,
231    kTypePtr,
232  };
233
234  jmethodID m_;
235  VarArgsType type_;
236  uint32_t cnt_;
237  union {
238    va_list vargs_;
239    const jvalue* ptr_;
240  };
241};
242
243class ScopedCheck {
244 public:
245  ScopedCheck(int flags, const char* functionName, bool has_method = true)
246      : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
247  }
248
249  ~ScopedCheck() {}
250
251  // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
252  // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
253  // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
254  // circumstances, but this is incorrect.
255  bool CheckClassName(const char* class_name) {
256    if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
257      AbortF("illegal class name '%s'\n"
258             "    (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
259             class_name);
260      return false;
261    }
262    return true;
263  }
264
265  /*
266   * Verify that this instance field ID is valid for this object.
267   *
268   * Assumes "jobj" has already been validated.
269   */
270  bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
271      REQUIRES_SHARED(Locks::mutator_lock_) {
272    ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
273    if (o == nullptr) {
274      AbortF("field operation on NULL object: %p", java_object);
275      return false;
276    }
277    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
278      Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
279      AbortF("field operation on invalid %s: %p",
280             ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
281             java_object);
282      return false;
283    }
284
285    ArtField* f = CheckFieldID(soa, fid);
286    if (f == nullptr) {
287      return false;
288    }
289    mirror::Class* c = o->GetClass();
290    if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
291      AbortF("jfieldID %s not valid for an object of class %s",
292             PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
293      return false;
294    }
295    return true;
296  }
297
298  /*
299   * Verify that the pointer value is non-null.
300   */
301  bool CheckNonNull(const void* ptr) {
302    if (UNLIKELY(ptr == nullptr)) {
303      AbortF("non-nullable argument was NULL");
304      return false;
305    }
306    return true;
307  }
308
309  /*
310   * Verify that the method's return type matches the type of call.
311   * 'expectedType' will be "L" for all objects, including arrays.
312   */
313  bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
314                         jmethodID mid, Primitive::Type type, InvokeType invoke)
315      REQUIRES_SHARED(Locks::mutator_lock_) {
316    ArtMethod* m = CheckMethodID(soa, mid);
317    if (m == nullptr) {
318      return false;
319    }
320    if (type != Primitive::GetType(m->GetShorty()[0])) {
321      AbortF("the return type of %s does not match %s", function_name_, PrettyMethod(m).c_str());
322      return false;
323    }
324    bool is_static = (invoke == kStatic);
325    if (is_static != m->IsStatic()) {
326      if (is_static) {
327        AbortF("calling non-static method %s with %s",
328               PrettyMethod(m).c_str(), function_name_);
329      } else {
330        AbortF("calling static method %s with %s",
331               PrettyMethod(m).c_str(), function_name_);
332      }
333      return false;
334    }
335    if (invoke != kVirtual) {
336      ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
337      if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
338        AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
339            PrettyMethod(m).c_str(), PrettyClass(c).c_str());
340        return false;
341      }
342    }
343    if (invoke != kStatic) {
344      ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
345      if (o == nullptr) {
346        AbortF("can't call %s on null object", PrettyMethod(m).c_str());
347        return false;
348      } else if (!o->InstanceOf(m->GetDeclaringClass())) {
349        AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
350        return false;
351      }
352    }
353    return true;
354  }
355
356  /*
357   * Verify that this static field ID is valid for this class.
358   *
359   * Assumes "java_class" has already been validated.
360   */
361  bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
362      REQUIRES_SHARED(Locks::mutator_lock_) {
363    ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
364    ArtField* f = CheckFieldID(soa, fid);
365    if (f == nullptr) {
366      return false;
367    }
368    if (c != f->GetDeclaringClass()) {
369      AbortF("static jfieldID %p not valid for class %s", fid, PrettyClass(c).c_str());
370      return false;
371    }
372    return true;
373  }
374
375  /*
376   * Verify that "mid" is appropriate for "java_class".
377   *
378   * A mismatch isn't dangerous, because the jmethodID defines the class.  In
379   * fact, java_class is unused in the implementation.  It's best if we don't
380   * allow bad code in the system though.
381   *
382   * Instances of "java_class" must be instances of the method's declaring class.
383   */
384  bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
385      REQUIRES_SHARED(Locks::mutator_lock_) {
386    ArtMethod* m = CheckMethodID(soa, mid);
387    if (m == nullptr) {
388      return false;
389    }
390    ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
391    if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
392      AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str());
393      return false;
394    }
395    return true;
396  }
397
398  /*
399   * Verify that "mid" is appropriate for "jobj".
400   *
401   * Make sure the object is an instance of the method's declaring class.
402   * (Note the mid might point to a declaration in an interface; this
403   * will be handled automatically by the instanceof check.)
404   */
405  bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
406      REQUIRES_SHARED(Locks::mutator_lock_) {
407    ArtMethod* m = CheckMethodID(soa, mid);
408    if (m == nullptr) {
409      return false;
410    }
411    ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
412    if (o == nullptr) {
413      AbortF("can't call %s on null object", PrettyMethod(m).c_str());
414      return false;
415    } else if (!o->InstanceOf(m->GetDeclaringClass())) {
416      AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
417      return false;
418    }
419    return true;
420  }
421
422  /**
423   * The format string is a sequence of the following characters,
424   * and must be followed by arguments of the corresponding types
425   * in the same order.
426   *
427   * Java primitive types:
428   * B - jbyte
429   * C - jchar
430   * D - jdouble
431   * F - jfloat
432   * I - jint
433   * J - jlong
434   * S - jshort
435   * Z - jboolean (shown as true and false)
436   * V - void
437   *
438   * Java reference types:
439   * L - jobject
440   * a - jarray
441   * c - jclass
442   * s - jstring
443   *
444   * JNI types:
445   * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
446   * f - jfieldID
447   * m - jmethodID
448   * p - void*
449   * r - jint (for release mode arguments)
450   * u - const char* (Modified UTF-8)
451   * z - jsize (for lengths; use i if negative values are okay)
452   * v - JavaVM*
453   * E - JNIEnv*
454   * . - VarArgs* for Jni calls with variable length arguments
455   *
456   * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
457   */
458  bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
459      REQUIRES_SHARED(Locks::mutator_lock_) {
460    ArtMethod* traceMethod = nullptr;
461    if (has_method_ && soa.Vm()->IsTracingEnabled()) {
462      // We need to guard some of the invocation interface's calls: a bad caller might
463      // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
464      Thread* self = Thread::Current();
465      if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
466        traceMethod = self->GetCurrentMethod(nullptr);
467      }
468    }
469
470    if (((flags_ & kFlag_ForceTrace) != 0) ||
471        (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
472      std::string msg;
473      for (size_t i = 0; fmt[i] != '\0'; ++i) {
474        TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
475        if (fmt[i + 1] != '\0') {
476          StringAppendF(&msg, ", ");
477        }
478      }
479
480      if ((flags_ & kFlag_ForceTrace) != 0) {
481        LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
482      } else if (entry) {
483        if (has_method_) {
484          std::string methodName(PrettyMethod(traceMethod, false));
485          LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
486          indent_ = methodName.size() + 1;
487        } else {
488          LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
489          indent_ = 0;
490        }
491      } else {
492        LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
493      }
494    }
495
496    // We always do the thorough checks on entry, and never on exit...
497    if (entry) {
498      for (size_t i = 0; fmt[i] != '\0'; ++i) {
499        if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
500          return false;
501        }
502      }
503    }
504    return true;
505  }
506
507  bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
508    bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
509    if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
510      // We need to guard some of the invocation interface's calls: a bad caller might
511      // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
512      Thread* self = Thread::Current();
513      if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
514        ScopedObjectAccess soa(self);
515        ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
516        should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
517      }
518    }
519    if (should_trace) {
520      std::string msg;
521      for (size_t i = 0; fmt[i] != '\0'; ++i) {
522        TraceNonHeapValue(fmt[i], args[i], &msg);
523        if (fmt[i + 1] != '\0') {
524          StringAppendF(&msg, ", ");
525        }
526      }
527
528      if ((flags_ & kFlag_ForceTrace) != 0) {
529        LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
530      } else if (entry) {
531        if (has_method_) {
532          Thread* self = Thread::Current();
533          ScopedObjectAccess soa(self);
534          ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
535          std::string methodName(PrettyMethod(traceMethod, false));
536          LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
537          indent_ = methodName.size() + 1;
538        } else {
539          LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
540          indent_ = 0;
541        }
542      } else {
543        LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
544      }
545    }
546
547    // We always do the thorough checks on entry, and never on exit...
548    if (entry) {
549      for (size_t i = 0; fmt[i] != '\0'; ++i) {
550        if (!CheckNonHeapValue(fmt[i], args[i])) {
551          return false;
552        }
553      }
554    }
555    return true;
556  }
557
558  bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
559      REQUIRES_SHARED(Locks::mutator_lock_) {
560    ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
561    if (method == nullptr) {
562      AbortF("expected non-null method");
563      return false;
564    }
565    mirror::Class* c = method->GetClass();
566    if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c &&
567        soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
568      AbortF("expected java.lang.reflect.Method or "
569          "java.lang.reflect.Constructor but got object of type %s: %p",
570          PrettyTypeOf(method).c_str(), jmethod);
571      return false;
572    }
573    return true;
574  }
575
576  bool CheckConstructor(ScopedObjectAccess& soa, jmethodID mid)
577      REQUIRES_SHARED(Locks::mutator_lock_) {
578    ArtMethod* method = soa.DecodeMethod(mid);
579    if (method == nullptr) {
580      AbortF("expected non-null constructor");
581      return false;
582    }
583    if (!method->IsConstructor() || method->IsStatic()) {
584      AbortF("expected a constructor but %s: %p", PrettyMethod(method).c_str(), mid);
585      return false;
586    }
587    return true;
588  }
589
590  bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
591      REQUIRES_SHARED(Locks::mutator_lock_) {
592    ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
593    if (field == nullptr) {
594      AbortF("expected non-null java.lang.reflect.Field");
595      return false;
596    }
597    mirror::Class* c = field->GetClass();
598    if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) {
599      AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
600             PrettyTypeOf(field).c_str(), jfield);
601      return false;
602    }
603    return true;
604  }
605
606  bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
607      REQUIRES_SHARED(Locks::mutator_lock_) {
608    ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
609    if (!obj->GetClass()->IsThrowableClass()) {
610      AbortF("expected java.lang.Throwable but got object of type "
611             "%s: %p", PrettyTypeOf(obj).c_str(), obj.Decode());
612      return false;
613    }
614    return true;
615  }
616
617  bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
618      REQUIRES_SHARED(Locks::mutator_lock_) {
619    ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
620    if (!c->IsThrowableClass()) {
621      AbortF("expected java.lang.Throwable class but got object of "
622             "type %s: %p", PrettyDescriptor(c).c_str(), c.Decode());
623      return false;
624    }
625    return true;
626  }
627
628  bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
629    IndirectRefKind found_kind;
630    if (expected_kind == kLocal) {
631      found_kind = GetIndirectRefKind(obj);
632      if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
633        found_kind = kLocal;
634      }
635    } else {
636      found_kind = GetIndirectRefKind(obj);
637    }
638    if (obj != nullptr && found_kind != expected_kind) {
639      AbortF("expected reference of kind %s but found %s: %p",
640             ToStr<IndirectRefKind>(expected_kind).c_str(),
641             ToStr<IndirectRefKind>(GetIndirectRefKind(obj)).c_str(),
642             obj);
643      return false;
644    }
645    return true;
646  }
647
648  bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
649      REQUIRES_SHARED(Locks::mutator_lock_) {
650    ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
651    if (!c->IsInstantiableNonArray()) {
652      AbortF("can't make objects of type %s: %p", PrettyDescriptor(c).c_str(), c.Decode());
653      return false;
654    }
655    return true;
656  }
657
658  bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
659      REQUIRES_SHARED(Locks::mutator_lock_) {
660    if (!CheckArray(soa, array)) {
661      return false;
662    }
663    ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
664    if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
665      AbortF("incompatible array type %s expected %s[]: %p",
666             PrettyDescriptor(a->GetClass()).c_str(), PrettyDescriptor(type).c_str(), array);
667      return false;
668    }
669    return true;
670  }
671
672  bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
673                        Primitive::Type type)
674      REQUIRES_SHARED(Locks::mutator_lock_) {
675    if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
676      return false;
677    }
678    if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
679      return false;
680    }
681    ArtField* field = soa.DecodeField(fid);
682    DCHECK(field != nullptr);  // Already checked by Check.
683    if (is_static != field->IsStatic()) {
684      AbortF("attempt to access %s field %s: %p",
685             field->IsStatic() ? "static" : "non-static", PrettyField(field).c_str(), fid);
686      return false;
687    }
688    if (type != field->GetTypeAsPrimitiveType()) {
689      AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
690             PrettyField(field).c_str(), PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
691             PrettyDescriptor(type).c_str(), fid);
692      return false;
693    }
694    if (is_static) {
695      ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
696      if (o == nullptr || !o->IsClass()) {
697        AbortF("attempt to access static field %s with a class argument of type %s: %p",
698               PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
699        return false;
700      }
701      ObjPtr<mirror::Class> c = o->AsClass();
702      if (c != field->GetDeclaringClass()) {
703        AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
704               PrettyField(field).c_str(), PrettyDescriptor(c).c_str(), fid);
705        return false;
706      }
707    } else {
708      ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
709      if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
710        AbortF("attempt to access field %s from an object argument of type %s: %p",
711               PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
712        return false;
713      }
714    }
715    return true;
716  }
717
718 private:
719  enum InstanceKind {
720    kClass,
721    kDirectByteBuffer,
722    kObject,
723    kString,
724    kThrowable,
725  };
726
727  /*
728   * Verify that "jobj" is a valid non-null object reference, and points to
729   * an instance of expectedClass.
730   *
731   * Because we're looking at an object on the GC heap, we have to switch
732   * to "running" mode before doing the checks.
733   */
734  bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
735      REQUIRES_SHARED(Locks::mutator_lock_) {
736    const char* what = nullptr;
737    switch (kind) {
738    case kClass:
739      what = "jclass";
740      break;
741    case kDirectByteBuffer:
742      what = "direct ByteBuffer";
743      break;
744    case kObject:
745      what = "jobject";
746      break;
747    case kString:
748      what = "jstring";
749      break;
750    case kThrowable:
751      what = "jthrowable";
752      break;
753    default:
754      LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
755    }
756
757    if (java_object == nullptr) {
758      if (null_ok) {
759        return true;
760      } else {
761        AbortF("%s received NULL %s", function_name_, what);
762        return false;
763      }
764    }
765
766    ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
767    if (obj == nullptr) {
768      // Either java_object is invalid or is a cleared weak.
769      IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
770      bool okay;
771      if (GetIndirectRefKind(ref) != kWeakGlobal) {
772        okay = false;
773      } else {
774        obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
775        okay = Runtime::Current()->IsClearedJniWeakGlobal(obj.Decode());
776      }
777      if (!okay) {
778        AbortF("%s is an invalid %s: %p (%p)",
779               what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
780               java_object, obj.Decode());
781        return false;
782      }
783    }
784
785    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
786      Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
787      AbortF("%s is an invalid %s: %p (%p)",
788             what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
789             java_object, obj.Decode());
790      return false;
791    }
792
793    bool okay = true;
794    switch (kind) {
795    case kClass:
796      okay = obj->IsClass();
797      break;
798    case kDirectByteBuffer:
799      UNIMPLEMENTED(FATAL);
800      break;
801    case kString:
802      okay = obj->GetClass()->IsStringClass();
803      break;
804    case kThrowable:
805      okay = obj->GetClass()->IsThrowableClass();
806      break;
807    case kObject:
808      break;
809    }
810    if (!okay) {
811      AbortF("%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
812      return false;
813    }
814
815    return true;
816  }
817
818  /*
819   * Verify that the "mode" argument passed to a primitive array Release
820   * function is one of the valid values.
821   */
822  bool CheckReleaseMode(jint mode) {
823    if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
824      AbortF("unknown value for release mode: %d", mode);
825      return false;
826    }
827    return true;
828  }
829
830  bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
831      REQUIRES_SHARED(Locks::mutator_lock_) {
832    switch (fmt) {
833      case 'a':  // jarray
834        return CheckArray(soa, arg.a);
835      case 'c':  // jclass
836        return CheckInstance(soa, kClass, arg.c, false);
837      case 'f':  // jfieldID
838        return CheckFieldID(soa, arg.f) != nullptr;
839      case 'm':  // jmethodID
840        return CheckMethodID(soa, arg.m) != nullptr;
841      case 'r':  // release int
842        return CheckReleaseMode(arg.r);
843      case 's':  // jstring
844        return CheckInstance(soa, kString, arg.s, false);
845      case 't':  // jthrowable
846        return CheckInstance(soa, kThrowable, arg.t, false);
847      case 'E':  // JNIEnv*
848        return CheckThread(arg.E);
849      case 'L':  // jobject
850        return CheckInstance(soa, kObject, arg.L, true);
851      case '.':  // A VarArgs list
852        return CheckVarArgs(soa, arg.va);
853      default:
854        return CheckNonHeapValue(fmt, arg);
855    }
856  }
857
858  bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
859      REQUIRES_SHARED(Locks::mutator_lock_) {
860    CHECK(args_p != nullptr);
861    VarArgs args(args_p->Clone());
862    ArtMethod* m = CheckMethodID(soa, args.GetMethodID());
863    if (m == nullptr) {
864      return false;
865    }
866    uint32_t len = 0;
867    const char* shorty = m->GetShorty(&len);
868    // Skip the return type
869    CHECK_GE(len, 1u);
870    len--;
871    shorty++;
872    for (uint32_t i = 0; i < len; i++) {
873      if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
874        return false;
875      }
876    }
877    return true;
878  }
879
880  bool CheckNonHeapValue(char fmt, JniValueType arg) {
881    switch (fmt) {
882      case 'p':  // TODO: pointer - null or readable?
883      case 'v':  // JavaVM*
884      case 'B':  // jbyte
885      case 'C':  // jchar
886      case 'D':  // jdouble
887      case 'F':  // jfloat
888      case 'I':  // jint
889      case 'J':  // jlong
890      case 'S':  // jshort
891        break;  // Ignored.
892      case 'b':  // jboolean, why two? Fall-through.
893      case 'Z':
894        return CheckBoolean(arg.Z);
895      case 'u':  // utf8
896        if ((flags_ & kFlag_Release) != 0) {
897          return CheckNonNull(arg.u);
898        } else {
899          bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
900          return CheckUtfString(arg.u, nullable);
901        }
902      case 'w':  // jobjectRefType
903        switch (arg.w) {
904          case JNIInvalidRefType:
905          case JNILocalRefType:
906          case JNIGlobalRefType:
907          case JNIWeakGlobalRefType:
908            break;
909          default:
910            AbortF("Unknown reference type");
911            return false;
912        }
913        break;
914      case 'z':  // jsize
915        return CheckLengthPositive(arg.z);
916      default:
917        AbortF("unknown format specifier: '%c'", fmt);
918        return false;
919    }
920    return true;
921  }
922
923  void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
924                              std::string* msg)
925      REQUIRES_SHARED(Locks::mutator_lock_) {
926    switch (fmt) {
927      case 'L':  // jobject fall-through.
928      case 'a':  // jarray fall-through.
929      case 's':  // jstring fall-through.
930      case 't':  // jthrowable fall-through.
931        if (arg.L == nullptr) {
932          *msg += "NULL";
933        } else {
934          StringAppendF(msg, "%p", arg.L);
935        }
936        break;
937      case 'c': {  // jclass
938        jclass jc = arg.c;
939        ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
940        if (c == nullptr) {
941          *msg += "NULL";
942        } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
943          StringAppendF(msg, "INVALID POINTER:%p", jc);
944        } else if (!c->IsClass()) {
945          *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
946        } else {
947          *msg += PrettyClass(c);
948          if (!entry) {
949            StringAppendF(msg, " (%p)", jc);
950          }
951        }
952        break;
953      }
954      case 'f': {  // jfieldID
955        jfieldID fid = arg.f;
956        ArtField* f = soa.DecodeField(fid);
957        *msg += PrettyField(f);
958        if (!entry) {
959          StringAppendF(msg, " (%p)", fid);
960        }
961        break;
962      }
963      case 'm': {  // jmethodID
964        jmethodID mid = arg.m;
965        ArtMethod* m = soa.DecodeMethod(mid);
966        *msg += PrettyMethod(m);
967        if (!entry) {
968          StringAppendF(msg, " (%p)", mid);
969        }
970        break;
971      }
972      case '.': {
973        const VarArgs* va = arg.va;
974        VarArgs args(va->Clone());
975        ArtMethod* m = soa.DecodeMethod(args.GetMethodID());
976        uint32_t len;
977        const char* shorty = m->GetShorty(&len);
978        CHECK_GE(len, 1u);
979        // Skip past return value.
980        len--;
981        shorty++;
982        // Remove the previous ', ' from the message.
983        msg->erase(msg->length() - 2);
984        for (uint32_t i = 0; i < len; i++) {
985          *msg += ", ";
986          TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
987        }
988        break;
989      }
990      default:
991        TraceNonHeapValue(fmt, arg, msg);
992        break;
993    }
994  }
995
996  void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
997    switch (fmt) {
998      case 'B':  // jbyte
999        if (arg.B >= 0 && arg.B < 10) {
1000          StringAppendF(msg, "%d", arg.B);
1001        } else {
1002          StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1003        }
1004        break;
1005      case 'C':  // jchar
1006        if (arg.C < 0x7f && arg.C >= ' ') {
1007          StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1008        } else {
1009          StringAppendF(msg, "U+%x", arg.C);
1010        }
1011        break;
1012      case 'F':  // jfloat
1013        StringAppendF(msg, "%g", arg.F);
1014        break;
1015      case 'D':  // jdouble
1016        StringAppendF(msg, "%g", arg.D);
1017        break;
1018      case 'S':  // jshort
1019        StringAppendF(msg, "%d", arg.S);
1020        break;
1021      case 'i':  // jint - fall-through.
1022      case 'I':  // jint
1023        StringAppendF(msg, "%d", arg.I);
1024        break;
1025      case 'J':  // jlong
1026        StringAppendF(msg, "%" PRId64, arg.J);
1027        break;
1028      case 'Z':  // jboolean
1029      case 'b':  // jboolean (JNI-style)
1030        *msg += arg.b == JNI_TRUE ? "true" : "false";
1031        break;
1032      case 'V':  // void
1033        DCHECK(arg.V == nullptr);
1034        *msg += "void";
1035        break;
1036      case 'v':  // JavaVM*
1037        StringAppendF(msg, "(JavaVM*)%p", arg.v);
1038        break;
1039      case 'E':
1040        StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1041        break;
1042      case 'z':  // non-negative jsize
1043        // You might expect jsize to be size_t, but it's not; it's the same as jint.
1044        // We only treat this specially so we can do the non-negative check.
1045        // TODO: maybe this wasn't worth it?
1046        StringAppendF(msg, "%d", arg.z);
1047        break;
1048      case 'p':  // void* ("pointer")
1049        if (arg.p == nullptr) {
1050          *msg += "NULL";
1051        } else {
1052          StringAppendF(msg, "(void*) %p", arg.p);
1053        }
1054        break;
1055      case 'r': {  // jint (release mode)
1056        jint releaseMode = arg.r;
1057        if (releaseMode == 0) {
1058          *msg += "0";
1059        } else if (releaseMode == JNI_ABORT) {
1060          *msg += "JNI_ABORT";
1061        } else if (releaseMode == JNI_COMMIT) {
1062          *msg += "JNI_COMMIT";
1063        } else {
1064          StringAppendF(msg, "invalid release mode %d", releaseMode);
1065        }
1066        break;
1067      }
1068      case 'u':  // const char* (Modified UTF-8)
1069        if (arg.u == nullptr) {
1070          *msg += "NULL";
1071        } else {
1072          StringAppendF(msg, "\"%s\"", arg.u);
1073        }
1074        break;
1075      case 'w':  // jobjectRefType
1076        switch (arg.w) {
1077          case JNIInvalidRefType:
1078            *msg += "invalid reference type";
1079            break;
1080          case JNILocalRefType:
1081            *msg += "local ref type";
1082            break;
1083          case JNIGlobalRefType:
1084            *msg += "global ref type";
1085            break;
1086          case JNIWeakGlobalRefType:
1087            *msg += "weak global ref type";
1088            break;
1089          default:
1090            *msg += "unknown ref type";
1091            break;
1092        }
1093        break;
1094      default:
1095        LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1096    }
1097  }
1098  /*
1099   * Verify that "array" is non-null and points to an Array object.
1100   *
1101   * Since we're dealing with objects, switch to "running" mode.
1102   */
1103  bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
1104      REQUIRES_SHARED(Locks::mutator_lock_) {
1105    if (UNLIKELY(java_array == nullptr)) {
1106      AbortF("jarray was NULL");
1107      return false;
1108    }
1109
1110    ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
1111    if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) {
1112      Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
1113      AbortF("jarray is an invalid %s: %p (%p)",
1114             ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
1115             java_array, a.Decode());
1116      return false;
1117    } else if (!a->IsArrayInstance()) {
1118      AbortF("jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
1119      return false;
1120    }
1121    return true;
1122  }
1123
1124  bool CheckBoolean(jboolean z) {
1125    if (z != JNI_TRUE && z != JNI_FALSE) {
1126      AbortF("unexpected jboolean value: %d", z);
1127      return false;
1128    }
1129    return true;
1130  }
1131
1132  bool CheckLengthPositive(jsize length) {
1133    if (length < 0) {
1134      AbortF("negative jsize: %d", length);
1135      return false;
1136    }
1137    return true;
1138  }
1139
1140  ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
1141      REQUIRES_SHARED(Locks::mutator_lock_) {
1142    if (fid == nullptr) {
1143      AbortF("jfieldID was NULL");
1144      return nullptr;
1145    }
1146    ArtField* f = soa.DecodeField(fid);
1147    // TODO: Better check here.
1148    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass())) {
1149      Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
1150      AbortF("invalid jfieldID: %p", fid);
1151      return nullptr;
1152    }
1153    return f;
1154  }
1155
1156  ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
1157      REQUIRES_SHARED(Locks::mutator_lock_) {
1158    if (mid == nullptr) {
1159      AbortF("jmethodID was NULL");
1160      return nullptr;
1161    }
1162    ArtMethod* m = soa.DecodeMethod(mid);
1163    // TODO: Better check here.
1164    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
1165      Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
1166      AbortF("invalid jmethodID: %p", mid);
1167      return nullptr;
1168    }
1169    return m;
1170  }
1171
1172  bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
1173    Thread* self = Thread::Current();
1174    if (self == nullptr) {
1175      AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1176      return false;
1177    }
1178
1179    // Get the current thread's JNIEnv by going through our TLS pointer.
1180    JNIEnvExt* threadEnv = self->GetJniEnv();
1181
1182    // Verify that the current thread is (a) attached and (b) associated with
1183    // this particular instance of JNIEnv.
1184    if (env != threadEnv) {
1185      // Get the thread owning the JNIEnv that's being used.
1186      Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self;
1187      AbortF("thread %s using JNIEnv* from thread %s",
1188             ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
1189      return false;
1190    }
1191
1192    // Verify that, if this thread previously made a critical "get" call, we
1193    // do the corresponding "release" call before we try anything else.
1194    switch (flags_ & kFlag_CritMask) {
1195    case kFlag_CritOkay:    // okay to call this method
1196      break;
1197    case kFlag_CritBad:     // not okay to call
1198      if (threadEnv->critical) {
1199        AbortF("thread %s using JNI after critical get",
1200               ToStr<Thread>(*self).c_str());
1201        return false;
1202      }
1203      break;
1204    case kFlag_CritGet:     // this is a "get" call
1205      // Don't check here; we allow nested gets.
1206      threadEnv->critical++;
1207      break;
1208    case kFlag_CritRelease:  // this is a "release" call
1209      threadEnv->critical--;
1210      if (threadEnv->critical < 0) {
1211        AbortF("thread %s called too many critical releases",
1212               ToStr<Thread>(*self).c_str());
1213        return false;
1214      }
1215      break;
1216    default:
1217      LOG(FATAL) << "Bad flags (internal error): " << flags_;
1218    }
1219
1220    // Verify that, if an exception has been raised, the native code doesn't
1221    // make any JNI calls other than the Exception* methods.
1222    if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
1223      mirror::Throwable* exception = self->GetException();
1224      AbortF("JNI %s called with pending exception %s",
1225             function_name_,
1226             exception->Dump().c_str());
1227      return false;
1228    }
1229    return true;
1230  }
1231
1232  // Verifies that "bytes" points to valid Modified UTF-8 data.
1233  bool CheckUtfString(const char* bytes, bool nullable) {
1234    if (bytes == nullptr) {
1235      if (!nullable) {
1236        AbortF("non-nullable const char* was NULL");
1237        return false;
1238      }
1239      return true;
1240    }
1241
1242    const char* errorKind = nullptr;
1243    const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
1244    if (errorKind != nullptr) {
1245      // This is an expensive loop that will resize often, but this isn't supposed to hit in
1246      // practice anyways.
1247      std::ostringstream oss;
1248      oss << std::hex;
1249      const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1250      while (*tmp != 0) {
1251        if (tmp == utf8) {
1252          oss << "<";
1253        }
1254        oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1255        if (tmp == utf8) {
1256          oss << '>';
1257        }
1258        tmp++;
1259        if (*tmp != 0) {
1260          oss << ' ';
1261        }
1262      }
1263
1264      AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
1265          "    string: '%s'\n    input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
1266      return false;
1267    }
1268    return true;
1269  }
1270
1271  // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1272  // sequences in place of encoded surrogate pairs.
1273  static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
1274    while (*bytes != '\0') {
1275      const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1276      // Switch on the high four bits.
1277      switch (*utf8 >> 4) {
1278      case 0x00:
1279      case 0x01:
1280      case 0x02:
1281      case 0x03:
1282      case 0x04:
1283      case 0x05:
1284      case 0x06:
1285      case 0x07:
1286        // Bit pattern 0xxx. No need for any extra bytes.
1287        break;
1288      case 0x08:
1289      case 0x09:
1290      case 0x0a:
1291      case 0x0b:
1292         // Bit patterns 10xx, which are illegal start bytes.
1293        *errorKind = "start";
1294        return utf8;
1295      case 0x0f:
1296        // Bit pattern 1111, which might be the start of a 4 byte sequence.
1297        if ((*utf8 & 0x08) == 0) {
1298          // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1299          // We consume one continuation byte here, and fall through to consume two more.
1300          utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1301          if ((*utf8 & 0xc0) != 0x80) {
1302            *errorKind = "continuation";
1303            return utf8;
1304          }
1305        } else {
1306          *errorKind = "start";
1307          return utf8;
1308        }
1309
1310        // Fall through to the cases below to consume two more continuation bytes.
1311        FALLTHROUGH_INTENDED;
1312      case 0x0e:
1313        // Bit pattern 1110, so there are two additional bytes.
1314        utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1315        if ((*utf8 & 0xc0) != 0x80) {
1316          *errorKind = "continuation";
1317          return utf8;
1318        }
1319
1320        // Fall through to consume one more continuation byte.
1321        FALLTHROUGH_INTENDED;
1322      case 0x0c:
1323      case 0x0d:
1324        // Bit pattern 110x, so there is one additional byte.
1325        utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1326        if ((*utf8 & 0xc0) != 0x80) {
1327          *errorKind = "continuation";
1328          return utf8;
1329        }
1330        break;
1331      }
1332    }
1333    return 0;
1334  }
1335
1336  void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1337    va_list args;
1338    va_start(args, fmt);
1339    Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1340    va_end(args);
1341  }
1342
1343  // The name of the JNI function being checked.
1344  const char* const function_name_;
1345
1346  const int flags_;
1347  int indent_;
1348
1349  const bool has_method_;
1350
1351  DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1352};
1353
1354/*
1355 * ===========================================================================
1356 *      Guarded arrays
1357 * ===========================================================================
1358 */
1359
1360/* this gets tucked in at the start of the buffer; struct size must be even */
1361class GuardedCopy {
1362 public:
1363  /*
1364   * Create an over-sized buffer to hold the contents of "buf".  Copy it in,
1365   * filling in the area around it with guard data.
1366   */
1367  static void* Create(void* original_buf, size_t len, bool mod_okay) {
1368    const size_t new_len = LengthIncludingRedZones(len);
1369    uint8_t* const new_buf = DebugAlloc(new_len);
1370
1371    // If modification is not expected, grab a checksum.
1372    uLong adler = 0;
1373    if (!mod_okay) {
1374      adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
1375    }
1376
1377    GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
1378
1379    // Fill begin region with canary pattern.
1380    const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1381    for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1382      const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1383      if (kCanary[j] == '\0') {
1384        j = 0;
1385      } else {
1386        j++;
1387      }
1388    }
1389
1390    // Copy the data in; note "len" could be zero.
1391    memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1392
1393    // Fill end region with canary pattern.
1394    for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1395      const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1396      if (kCanary[j] == '\0') {
1397        j = 0;
1398      } else {
1399        j++;
1400      }
1401    }
1402
1403    return const_cast<uint8_t*>(copy->BufferWithinRedZones());
1404  }
1405
1406  /*
1407   * Create a guarded copy of a primitive array.  Modifications to the copied
1408   * data are allowed.  Returns a pointer to the copied data.
1409   */
1410  static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1411                                   void* original_ptr) {
1412    ScopedObjectAccess soa(env);
1413
1414    ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
1415    size_t component_size = a->GetClass()->GetComponentSize();
1416    size_t byte_count = a->GetLength() * component_size;
1417    void* result = Create(original_ptr, byte_count, true);
1418    if (is_copy != nullptr) {
1419      *is_copy = JNI_TRUE;
1420    }
1421    return result;
1422  }
1423
1424  /*
1425   * Perform the array "release" operation, which may or may not copy data
1426   * back into the managed heap, and may or may not release the underlying storage.
1427   */
1428  static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1429                                    jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1430                                    int mode) {
1431    ScopedObjectAccess soa(env);
1432    if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1433      return nullptr;
1434    }
1435    GuardedCopy* const copy = FromEmbedded(embedded_buf);
1436    void* original_ptr = copy->original_ptr_;
1437    if (mode != JNI_ABORT) {
1438      memcpy(original_ptr, embedded_buf, copy->original_length_);
1439    }
1440    if (mode != JNI_COMMIT) {
1441      Destroy(embedded_buf);
1442    }
1443    return original_ptr;
1444  }
1445
1446
1447  /*
1448   * Free up the guard buffer, scrub it, and return the original pointer.
1449   */
1450  static void* Destroy(void* embedded_buf) {
1451    GuardedCopy* copy = FromEmbedded(embedded_buf);
1452    void* original_ptr = const_cast<void*>(copy->original_ptr_);
1453    size_t len = LengthIncludingRedZones(copy->original_length_);
1454    DebugFree(copy, len);
1455    return original_ptr;
1456  }
1457
1458  /*
1459   * Verify the guard area and, if "modOkay" is false, that the data itself
1460   * has not been altered.
1461   *
1462   * The caller has already checked that "dataBuf" is non-null.
1463   */
1464  static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1465    const GuardedCopy* copy = FromEmbedded(embedded_buf);
1466    return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
1467  }
1468
1469 private:
1470  GuardedCopy(void* original_buf, size_t len, uLong adler) :
1471    magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1472  }
1473
1474  static uint8_t* DebugAlloc(size_t len) {
1475    void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
1476    if (result == MAP_FAILED) {
1477      PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1478    }
1479    return reinterpret_cast<uint8_t*>(result);
1480  }
1481
1482  static void DebugFree(void* buf, size_t len) {
1483    if (munmap(buf, len) != 0) {
1484      PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
1485    }
1486  }
1487
1488  static size_t LengthIncludingRedZones(size_t len) {
1489    return len + kRedZoneSize;
1490  }
1491
1492  // Get the GuardedCopy from the interior pointer.
1493  static GuardedCopy* FromEmbedded(void* embedded_buf) {
1494    return reinterpret_cast<GuardedCopy*>(
1495        reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
1496  }
1497
1498  static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1499    return reinterpret_cast<const GuardedCopy*>(
1500        reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
1501  }
1502
1503  static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1504    va_list args;
1505    va_start(args, fmt);
1506    Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1507    va_end(args);
1508  }
1509
1510  bool CheckHeader(const char* function_name, bool mod_okay) const {
1511    static const uint32_t kMagicCmp = kGuardMagic;
1512
1513    // Before we do anything with "pExtra", check the magic number.  We
1514    // do the check with memcmp rather than "==" in case the pointer is
1515    // unaligned.  If it points to completely bogus memory we're going
1516    // to crash, but there's no easy way around that.
1517    if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1518      uint8_t buf[4];
1519      memcpy(buf, &magic_, 4);
1520      AbortF(function_name,
1521             "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1522             buf[3], buf[2], buf[1], buf[0], this);  // Assumes little-endian.
1523      return false;
1524    }
1525
1526    // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1527    // told the client that we made a copy, there's no reason they can't alter the buffer.
1528    if (!mod_okay) {
1529      uLong computed_adler =
1530          adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1531      if (computed_adler != adler_) {
1532        AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1533               computed_adler, adler_, this);
1534        return false;
1535      }
1536    }
1537    return true;
1538  }
1539
1540  bool CheckRedZones(const char* function_name) const {
1541    // Check the begin red zone.
1542    const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1543    for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1544      if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1545        AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1546        return false;
1547      }
1548      if (kCanary[j] == '\0') {
1549        j = 0;
1550      } else {
1551        j++;
1552      }
1553    }
1554
1555    // Check end region.
1556    for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1557      if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1558        size_t offset_from_buffer_start =
1559            &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1560        AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1561               offset_from_buffer_start);
1562        return false;
1563      }
1564      if (kCanary[j] == '\0') {
1565        j = 0;
1566      } else {
1567        j++;
1568      }
1569    }
1570    return true;
1571  }
1572
1573  // Location that canary value will be written before the guarded region.
1574  const char* StartRedZone() const {
1575    const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1576    return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1577  }
1578
1579  // Return the interior embedded buffer.
1580  const uint8_t* BufferWithinRedZones() const {
1581    const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1582    return embedded_buf;
1583  }
1584
1585  // Location that canary value will be written after the guarded region.
1586  const char* EndRedZone() const {
1587    const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1588    size_t buf_len = LengthIncludingRedZones(original_length_);
1589    return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1590  }
1591
1592  static constexpr size_t kRedZoneSize = 512;
1593  static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1594
1595  // Value written before and after the guarded array.
1596  static const char* const kCanary;
1597
1598  static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1599
1600  const uint32_t magic_;
1601  const uLong adler_;
1602  void* const original_ptr_;
1603  const size_t original_length_;
1604};
1605const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
1606
1607/*
1608 * ===========================================================================
1609 *      JNI functions
1610 * ===========================================================================
1611 */
1612
1613class CheckJNI {
1614 public:
1615  static jint GetVersion(JNIEnv* env) {
1616    ScopedObjectAccess soa(env);
1617    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1618    JniValueType args[1] = {{.E = env }};
1619    if (sc.Check(soa, true, "E", args)) {
1620      JniValueType result;
1621      result.I = baseEnv(env)->GetVersion(env);
1622      if (sc.Check(soa, false, "I", &result)) {
1623        return result.I;
1624      }
1625    }
1626    return JNI_ERR;
1627  }
1628
1629  static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1630    ScopedObjectAccess soa(env);
1631    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1632    JniValueType args[2] = {{.E = env }, {.p = vm}};
1633    if (sc.Check(soa, true, "Ep", args)) {
1634      JniValueType result;
1635      result.i = baseEnv(env)->GetJavaVM(env, vm);
1636      if (sc.Check(soa, false, "i", &result)) {
1637        return result.i;
1638      }
1639    }
1640    return JNI_ERR;
1641  }
1642
1643  static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1644    ScopedObjectAccess soa(env);
1645    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1646    JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1647    if (sc.Check(soa, true, "EcpI", args)) {
1648      JniValueType result;
1649      result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1650      if (sc.Check(soa, false, "i", &result)) {
1651        return result.i;
1652      }
1653    }
1654    return JNI_ERR;
1655  }
1656
1657  static jint UnregisterNatives(JNIEnv* env, jclass c) {
1658    ScopedObjectAccess soa(env);
1659    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1660    JniValueType args[2] = {{.E = env }, {.c = c}};
1661    if (sc.Check(soa, true, "Ec", args)) {
1662      JniValueType result;
1663      result.i = baseEnv(env)->UnregisterNatives(env, c);
1664      if (sc.Check(soa, false, "i", &result)) {
1665        return result.i;
1666      }
1667    }
1668    return JNI_ERR;
1669  }
1670
1671  static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1672    // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1673    // know the object is invalid. The spec says that passing invalid objects or even ones that
1674    // are deleted isn't supported.
1675    ScopedObjectAccess soa(env);
1676    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1677    JniValueType args[2] = {{.E = env }, {.L = obj}};
1678    if (sc.Check(soa, true, "EL", args)) {
1679      JniValueType result;
1680      result.w = baseEnv(env)->GetObjectRefType(env, obj);
1681      if (sc.Check(soa, false, "w", &result)) {
1682        return result.w;
1683      }
1684    }
1685    return JNIInvalidRefType;
1686  }
1687
1688  static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1689                            jsize bufLen) {
1690    ScopedObjectAccess soa(env);
1691    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1692    JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1693    if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1694      JniValueType result;
1695      result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1696      if (sc.Check(soa, false, "c", &result)) {
1697        return result.c;
1698      }
1699    }
1700    return nullptr;
1701  }
1702
1703  static jclass FindClass(JNIEnv* env, const char* name) {
1704    ScopedObjectAccess soa(env);
1705    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1706    JniValueType args[2] = {{.E = env}, {.u = name}};
1707    if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1708      JniValueType result;
1709      result.c = baseEnv(env)->FindClass(env, name);
1710      if (sc.Check(soa, false, "c", &result)) {
1711        return result.c;
1712      }
1713    }
1714    return nullptr;
1715  }
1716
1717  static jclass GetSuperclass(JNIEnv* env, jclass c) {
1718    ScopedObjectAccess soa(env);
1719    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1720    JniValueType args[2] = {{.E = env}, {.c = c}};
1721    if (sc.Check(soa, true, "Ec", args)) {
1722      JniValueType result;
1723      result.c = baseEnv(env)->GetSuperclass(env, c);
1724      if (sc.Check(soa, false, "c", &result)) {
1725        return result.c;
1726      }
1727    }
1728    return nullptr;
1729  }
1730
1731  static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
1732    ScopedObjectAccess soa(env);
1733    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1734    JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1735    if (sc.Check(soa, true, "Ecc", args)) {
1736      JniValueType result;
1737      result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1738      if (sc.Check(soa, false, "b", &result)) {
1739        return result.b;
1740      }
1741    }
1742    return JNI_FALSE;
1743  }
1744
1745  static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
1746    ScopedObjectAccess soa(env);
1747    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1748    JniValueType args[2] = {{.E = env}, {.L = method}};
1749    if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1750      JniValueType result;
1751      result.m = baseEnv(env)->FromReflectedMethod(env, method);
1752      if (sc.Check(soa, false, "m", &result)) {
1753        return result.m;
1754      }
1755    }
1756    return nullptr;
1757  }
1758
1759  static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
1760    ScopedObjectAccess soa(env);
1761    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1762    JniValueType args[2] = {{.E = env}, {.L = field}};
1763    if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1764      JniValueType result;
1765      result.f = baseEnv(env)->FromReflectedField(env, field);
1766      if (sc.Check(soa, false, "f", &result)) {
1767        return result.f;
1768      }
1769    }
1770    return nullptr;
1771  }
1772
1773  static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
1774    ScopedObjectAccess soa(env);
1775    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1776    JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1777    if (sc.Check(soa, true, "Ecmb", args)) {
1778      JniValueType result;
1779      result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1780      if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1781        DCHECK(sc.CheckReflectedMethod(soa, result.L));
1782        return result.L;
1783      }
1784    }
1785    return nullptr;
1786  }
1787
1788  static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
1789    ScopedObjectAccess soa(env);
1790    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1791    JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1792    if (sc.Check(soa, true, "Ecfb", args)) {
1793      JniValueType result;
1794      result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1795      if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1796        DCHECK(sc.CheckReflectedField(soa, result.L));
1797        return result.L;
1798      }
1799    }
1800    return nullptr;
1801  }
1802
1803  static jint Throw(JNIEnv* env, jthrowable obj) {
1804    ScopedObjectAccess soa(env);
1805    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1806    JniValueType args[2] = {{.E = env}, {.t = obj}};
1807    if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1808      JniValueType result;
1809      result.i = baseEnv(env)->Throw(env, obj);
1810      if (sc.Check(soa, false, "i", &result)) {
1811        return result.i;
1812      }
1813    }
1814    return JNI_ERR;
1815  }
1816
1817  static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
1818    ScopedObjectAccess soa(env);
1819    ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
1820    JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
1821    if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1822      JniValueType result;
1823      result.i = baseEnv(env)->ThrowNew(env, c, message);
1824      if (sc.Check(soa, false, "i", &result)) {
1825        return result.i;
1826      }
1827    }
1828    return JNI_ERR;
1829  }
1830
1831  static jthrowable ExceptionOccurred(JNIEnv* env) {
1832    ScopedObjectAccess soa(env);
1833    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1834    JniValueType args[1] = {{.E = env}};
1835    if (sc.Check(soa, true, "E", args)) {
1836      JniValueType result;
1837      result.t = baseEnv(env)->ExceptionOccurred(env);
1838      if (sc.Check(soa, false, "t", &result)) {
1839        return result.t;
1840      }
1841    }
1842    return nullptr;
1843  }
1844
1845  static void ExceptionDescribe(JNIEnv* env) {
1846    ScopedObjectAccess soa(env);
1847    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1848    JniValueType args[1] = {{.E = env}};
1849    if (sc.Check(soa, true, "E", args)) {
1850      JniValueType result;
1851      baseEnv(env)->ExceptionDescribe(env);
1852      result.V = nullptr;
1853      sc.Check(soa, false, "V", &result);
1854    }
1855  }
1856
1857  static void ExceptionClear(JNIEnv* env) {
1858    ScopedObjectAccess soa(env);
1859    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1860    JniValueType args[1] = {{.E = env}};
1861    if (sc.Check(soa, true, "E", args)) {
1862      JniValueType result;
1863      baseEnv(env)->ExceptionClear(env);
1864      result.V = nullptr;
1865      sc.Check(soa, false, "V", &result);
1866    }
1867  }
1868
1869  static jboolean ExceptionCheck(JNIEnv* env) {
1870    ScopedObjectAccess soa(env);
1871    ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1872    JniValueType args[1] = {{.E = env}};
1873    if (sc.Check(soa, true, "E", args)) {
1874      JniValueType result;
1875      result.b = baseEnv(env)->ExceptionCheck(env);
1876      if (sc.Check(soa, false, "b", &result)) {
1877        return result.b;
1878      }
1879    }
1880    return JNI_FALSE;
1881  }
1882
1883  static void FatalError(JNIEnv* env, const char* msg) {
1884    // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1885    // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1886    // and it's not unimaginable that you don't know that you do. So we allow it.
1887    ScopedObjectAccess soa(env);
1888    ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1889    JniValueType args[2] = {{.E = env}, {.u = msg}};
1890    if (sc.Check(soa, true, "Eu", args)) {
1891      JniValueType result;
1892      baseEnv(env)->FatalError(env, msg);
1893      // Unreachable.
1894      result.V = nullptr;
1895      sc.Check(soa, false, "V", &result);
1896    }
1897  }
1898
1899  static jint PushLocalFrame(JNIEnv* env, jint capacity) {
1900    ScopedObjectAccess soa(env);
1901    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1902    JniValueType args[2] = {{.E = env}, {.I = capacity}};
1903    if (sc.Check(soa, true, "EI", args)) {
1904      JniValueType result;
1905      result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1906      if (sc.Check(soa, false, "i", &result)) {
1907        return result.i;
1908      }
1909    }
1910    return JNI_ERR;
1911  }
1912
1913  static jobject PopLocalFrame(JNIEnv* env, jobject res) {
1914    ScopedObjectAccess soa(env);
1915    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1916    JniValueType args[2] = {{.E = env}, {.L = res}};
1917    if (sc.Check(soa, true, "EL", args)) {
1918      JniValueType result;
1919      result.L = baseEnv(env)->PopLocalFrame(env, res);
1920      sc.Check(soa, false, "L", &result);
1921      return result.L;
1922    }
1923    return nullptr;
1924  }
1925
1926  static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
1927    return NewRef(__FUNCTION__, env, obj, kGlobal);
1928  }
1929
1930  static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1931    return NewRef(__FUNCTION__, env, obj, kLocal);
1932  }
1933
1934  static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
1935    return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
1936  }
1937
1938  static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1939    DeleteRef(__FUNCTION__, env, obj, kGlobal);
1940  }
1941
1942  static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1943    DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1944  }
1945
1946  static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1947    DeleteRef(__FUNCTION__, env, obj, kLocal);
1948  }
1949
1950  static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1951    ScopedObjectAccess soa(env);
1952    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1953    JniValueType args[2] = {{.E = env}, {.I = capacity}};
1954    if (sc.Check(soa, true, "EI", args)) {
1955      JniValueType result;
1956      result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1957      if (sc.Check(soa, false, "i", &result)) {
1958        return result.i;
1959      }
1960    }
1961    return JNI_ERR;
1962  }
1963
1964  static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1965    ScopedObjectAccess soa(env);
1966    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1967    JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1968    if (sc.Check(soa, true, "ELL", args)) {
1969      JniValueType result;
1970      result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1971      if (sc.Check(soa, false, "b", &result)) {
1972        return result.b;
1973      }
1974    }
1975    return JNI_FALSE;
1976  }
1977
1978  static jobject AllocObject(JNIEnv* env, jclass c) {
1979    ScopedObjectAccess soa(env);
1980    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1981    JniValueType args[2] = {{.E = env}, {.c = c}};
1982    if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1983      JniValueType result;
1984      result.L = baseEnv(env)->AllocObject(env, c);
1985      if (sc.Check(soa, false, "L", &result)) {
1986        return result.L;
1987      }
1988    }
1989    return nullptr;
1990  }
1991
1992  static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1993    ScopedObjectAccess soa(env);
1994    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1995    VarArgs rest(mid, vargs);
1996    JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
1997    if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
1998        sc.CheckConstructor(soa, mid)) {
1999      JniValueType result;
2000      result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2001      if (sc.Check(soa, false, "L", &result)) {
2002        return result.L;
2003      }
2004    }
2005    return nullptr;
2006  }
2007
2008  static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2009    va_list args;
2010    va_start(args, mid);
2011    jobject result = NewObjectV(env, c, mid, args);
2012    va_end(args);
2013    return result;
2014  }
2015
2016  static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2017    ScopedObjectAccess soa(env);
2018    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2019    VarArgs rest(mid, vargs);
2020    JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2021    if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
2022        sc.CheckConstructor(soa, mid)) {
2023      JniValueType result;
2024      result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2025      if (sc.Check(soa, false, "L", &result)) {
2026        return result.L;
2027      }
2028    }
2029    return nullptr;
2030  }
2031
2032  static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2033    ScopedObjectAccess soa(env);
2034    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2035    JniValueType args[2] = {{.E = env}, {.L = obj}};
2036    if (sc.Check(soa, true, "EL", args)) {
2037      JniValueType result;
2038      result.c = baseEnv(env)->GetObjectClass(env, obj);
2039      if (sc.Check(soa, false, "c", &result)) {
2040        return result.c;
2041      }
2042    }
2043    return nullptr;
2044  }
2045
2046  static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2047    ScopedObjectAccess soa(env);
2048    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2049    JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2050    if (sc.Check(soa, true, "ELc", args)) {
2051      JniValueType result;
2052      result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2053      if (sc.Check(soa, false, "b", &result)) {
2054        return result.b;
2055      }
2056    }
2057    return JNI_FALSE;
2058  }
2059
2060  static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2061    return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2062  }
2063
2064  static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2065    return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2066  }
2067
2068  static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2069    return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2070  }
2071
2072  static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2073    return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2074  }
2075
2076#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
2077  static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2078    return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2079  } \
2080  \
2081  static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2082    return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2083  } \
2084  \
2085  static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2086    JniValueType value; \
2087    value.shorty = v; \
2088    SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2089  } \
2090  \
2091  static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2092    JniValueType value; \
2093    value.shorty = v; \
2094    SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2095  }
2096
2097  FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
2098  FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2099  FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
2100  FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
2101  FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
2102  FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
2103  FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
2104  FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
2105  FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
2106#undef FIELD_ACCESSORS
2107
2108  static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
2109    CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2110  }
2111
2112  static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2113                                        jvalue* vargs) {
2114    CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2115  }
2116
2117  static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2118    CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2119  }
2120
2121  static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2122    CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2123  }
2124
2125  static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2126                                        va_list vargs) {
2127    CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2128  }
2129
2130  static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2131    CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2132  }
2133
2134  static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2135    va_list vargs;
2136    va_start(vargs, mid);
2137    CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2138    va_end(vargs);
2139  }
2140
2141  static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2142    va_list vargs;
2143    va_start(vargs, mid);
2144    CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2145    va_end(vargs);
2146  }
2147
2148  static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2149    va_list vargs;
2150    va_start(vargs, mid);
2151    CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2152    va_end(vargs);
2153  }
2154
2155#define CALL(rtype, name, ptype, shorty) \
2156  static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
2157    return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2158  } \
2159  \
2160  static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2161                                             jvalue* vargs) { \
2162    return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2163  } \
2164  \
2165  static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2166    return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2167  } \
2168  \
2169  static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2170    return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2171  } \
2172  \
2173  static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2174                                             va_list vargs) { \
2175    return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2176  } \
2177  \
2178  static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2179    return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2180  } \
2181  \
2182  static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2183    va_list vargs; \
2184    va_start(vargs, mid); \
2185    rtype result = \
2186        CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2187    va_end(vargs); \
2188    return result; \
2189  } \
2190  \
2191  static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2192                                            ...) { \
2193    va_list vargs; \
2194    va_start(vargs, mid); \
2195    rtype result = \
2196        CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2197    va_end(vargs); \
2198    return result; \
2199  } \
2200  \
2201  static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2202    va_list vargs; \
2203    va_start(vargs, mid); \
2204    rtype result = \
2205        CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2206    va_end(vargs); \
2207    return result; \
2208  }
2209
2210  CALL(jobject, Object, Primitive::kPrimNot, L)
2211  CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2212  CALL(jbyte, Byte, Primitive::kPrimByte, B)
2213  CALL(jchar, Char, Primitive::kPrimChar, C)
2214  CALL(jshort, Short, Primitive::kPrimShort, S)
2215  CALL(jint, Int, Primitive::kPrimInt, I)
2216  CALL(jlong, Long, Primitive::kPrimLong, J)
2217  CALL(jfloat, Float, Primitive::kPrimFloat, F)
2218  CALL(jdouble, Double, Primitive::kPrimDouble, D)
2219#undef CALL
2220
2221  static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2222    ScopedObjectAccess soa(env);
2223    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2224    JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2225    if (sc.Check(soa, true, "Epz", args)) {
2226      JniValueType result;
2227      result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2228      if (sc.Check(soa, false, "s", &result)) {
2229        return result.s;
2230      }
2231    }
2232    return nullptr;
2233  }
2234
2235  static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2236    ScopedObjectAccess soa(env);
2237    ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2238    JniValueType args[2] = {{.E = env}, {.u = chars}};
2239    if (sc.Check(soa, true, "Eu", args)) {
2240      JniValueType result;
2241      // TODO: stale? show pointer and truncate string.
2242      result.s = baseEnv(env)->NewStringUTF(env, chars);
2243      if (sc.Check(soa, false, "s", &result)) {
2244        return result.s;
2245      }
2246    }
2247    return nullptr;
2248  }
2249
2250  static jsize GetStringLength(JNIEnv* env, jstring string) {
2251    ScopedObjectAccess soa(env);
2252    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2253    JniValueType args[2] = {{.E = env}, {.s = string}};
2254    if (sc.Check(soa, true, "Es", args)) {
2255      JniValueType result;
2256      result.z = baseEnv(env)->GetStringLength(env, string);
2257      if (sc.Check(soa, false, "z", &result)) {
2258        return result.z;
2259      }
2260    }
2261    return JNI_ERR;
2262  }
2263
2264  static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2265    ScopedObjectAccess soa(env);
2266    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2267    JniValueType args[2] = {{.E = env}, {.s = string}};
2268    if (sc.Check(soa, true, "Es", args)) {
2269      JniValueType result;
2270      result.z = baseEnv(env)->GetStringUTFLength(env, string);
2271      if (sc.Check(soa, false, "z", &result)) {
2272        return result.z;
2273      }
2274    }
2275    return JNI_ERR;
2276  }
2277
2278  static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2279    return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2280                                                                 is_copy, false, false));
2281  }
2282
2283  static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2284    return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2285                                                                is_copy, true, false));
2286  }
2287
2288  static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2289    return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2290                                                                 is_copy, false, true));
2291  }
2292
2293  static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2294    ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2295  }
2296
2297  static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2298    ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2299  }
2300
2301  static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2302    ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2303  }
2304
2305  static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2306    ScopedObjectAccess soa(env);
2307    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2308    JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2309    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2310    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2311    if (sc.Check(soa, true, "EsIIp", args)) {
2312      baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2313      JniValueType result;
2314      result.V = nullptr;
2315      sc.Check(soa, false, "V", &result);
2316    }
2317  }
2318
2319  static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2320    ScopedObjectAccess soa(env);
2321    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2322    JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2323    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2324    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2325    if (sc.Check(soa, true, "EsIIp", args)) {
2326      baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2327      JniValueType result;
2328      result.V = nullptr;
2329      sc.Check(soa, false, "V", &result);
2330    }
2331  }
2332
2333  static jsize GetArrayLength(JNIEnv* env, jarray array) {
2334    ScopedObjectAccess soa(env);
2335    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2336    JniValueType args[2] = {{.E = env}, {.a = array}};
2337    if (sc.Check(soa, true, "Ea", args)) {
2338      JniValueType result;
2339      result.z = baseEnv(env)->GetArrayLength(env, array);
2340      if (sc.Check(soa, false, "z", &result)) {
2341        return result.z;
2342      }
2343    }
2344    return JNI_ERR;
2345  }
2346
2347  static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2348                                     jobject initial_element) {
2349    ScopedObjectAccess soa(env);
2350    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2351    JniValueType args[4] =
2352        {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2353    if (sc.Check(soa, true, "EzcL", args)) {
2354      JniValueType result;
2355      // Note: assignability tests of initial_element are done in the base implementation.
2356      result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2357      if (sc.Check(soa, false, "a", &result)) {
2358        return down_cast<jobjectArray>(result.a);
2359      }
2360    }
2361    return nullptr;
2362  }
2363
2364  static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2365    ScopedObjectAccess soa(env);
2366    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2367    JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2368    if (sc.Check(soa, true, "Eaz", args)) {
2369      JniValueType result;
2370      result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2371      if (sc.Check(soa, false, "L", &result)) {
2372        return result.L;
2373      }
2374    }
2375    return nullptr;
2376  }
2377
2378  static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2379    ScopedObjectAccess soa(env);
2380    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2381    JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2382    // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2383    // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2384    // in ArrayStoreExceptions.
2385    if (sc.Check(soa, true, "EaIL", args)) {
2386      baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2387      JniValueType result;
2388      result.V = nullptr;
2389      sc.Check(soa, false, "V", &result);
2390    }
2391  }
2392
2393  static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2394    return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2395                                                      Primitive::kPrimBoolean));
2396  }
2397
2398  static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2399    return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2400                                                   Primitive::kPrimByte));
2401  }
2402
2403  static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2404    return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2405                                                   Primitive::kPrimChar));
2406  }
2407
2408  static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2409    return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2410                                                    Primitive::kPrimShort));
2411  }
2412
2413  static jintArray NewIntArray(JNIEnv* env, jsize length) {
2414    return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2415  }
2416
2417  static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2418    return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2419                                                   Primitive::kPrimLong));
2420  }
2421
2422  static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2423    return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2424                                                    Primitive::kPrimFloat));
2425  }
2426
2427  static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2428    return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2429                                                     Primitive::kPrimDouble));
2430  }
2431
2432// NOLINT added to avoid wrong warning/fix from clang-tidy.
2433#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
2434  static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2435    return reinterpret_cast<ctype*>( /* NOLINT */ \
2436        GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2437  } \
2438  \
2439  static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
2440                                           jint mode) { \
2441    ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2442  } \
2443  \
2444  static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2445                                     ctype* buf) { /* NOLINT */ \
2446    GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2447  } \
2448  \
2449  static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2450                                     const ctype* buf) { \
2451    SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2452  }
2453
2454  PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2455  PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2456  PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2457  PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2458  PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2459  PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2460  PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2461  PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2462#undef PRIMITIVE_ARRAY_FUNCTIONS
2463
2464  static jint MonitorEnter(JNIEnv* env, jobject obj) {
2465    ScopedObjectAccess soa(env);
2466    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2467    JniValueType args[2] = {{.E = env}, {.L = obj}};
2468    if (sc.Check(soa, true, "EL", args)) {
2469      if (obj != nullptr) {
2470        down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2471      }
2472      JniValueType result;
2473      result.i = baseEnv(env)->MonitorEnter(env, obj);
2474      if (sc.Check(soa, false, "i", &result)) {
2475        return result.i;
2476      }
2477    }
2478    return JNI_ERR;
2479  }
2480
2481  static jint MonitorExit(JNIEnv* env, jobject obj) {
2482    ScopedObjectAccess soa(env);
2483    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2484    JniValueType args[2] = {{.E = env}, {.L = obj}};
2485    if (sc.Check(soa, true, "EL", args)) {
2486      if (obj != nullptr) {
2487        down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2488      }
2489      JniValueType result;
2490      result.i = baseEnv(env)->MonitorExit(env, obj);
2491      if (sc.Check(soa, false, "i", &result)) {
2492        return result.i;
2493      }
2494    }
2495    return JNI_ERR;
2496  }
2497
2498  static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2499    ScopedObjectAccess soa(env);
2500    ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2501    JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2502    if (sc.Check(soa, true, "Eap", args)) {
2503      JniValueType result;
2504      void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2505      if (ptr != nullptr && soa.ForceCopy()) {
2506        ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
2507      }
2508      result.p = ptr;
2509      if (sc.Check(soa, false, "p", &result)) {
2510        return const_cast<void*>(result.p);
2511      }
2512    }
2513    return nullptr;
2514  }
2515
2516  static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2517    ScopedObjectAccess soa(env);
2518    ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2519    sc.CheckNonNull(carray);
2520    JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2521    if (sc.Check(soa, true, "Eapr", args)) {
2522      if (soa.ForceCopy()) {
2523        carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
2524      }
2525      baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2526      JniValueType result;
2527      result.V = nullptr;
2528      sc.Check(soa, false, "V", &result);
2529    }
2530  }
2531
2532  static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
2533    ScopedObjectAccess soa(env);
2534    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2535    JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2536    if (sc.Check(soa, true, "EpJ", args)) {
2537      JniValueType result;
2538      // Note: the validity of address and capacity are checked in the base implementation.
2539      result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2540      if (sc.Check(soa, false, "L", &result)) {
2541        return result.L;
2542      }
2543    }
2544    return nullptr;
2545  }
2546
2547  static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
2548    ScopedObjectAccess soa(env);
2549    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2550    JniValueType args[2] = {{.E = env}, {.L = buf}};
2551    if (sc.Check(soa, true, "EL", args)) {
2552      JniValueType result;
2553      // Note: this is implemented in the base environment by a GetLongField which will sanity
2554      // check the type of buf in GetLongField above.
2555      result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2556      if (sc.Check(soa, false, "p", &result)) {
2557        return const_cast<void*>(result.p);
2558      }
2559    }
2560    return nullptr;
2561  }
2562
2563  static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
2564    ScopedObjectAccess soa(env);
2565    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2566    JniValueType args[2] = {{.E = env}, {.L = buf}};
2567    if (sc.Check(soa, true, "EL", args)) {
2568      JniValueType result;
2569      // Note: this is implemented in the base environment by a GetIntField which will sanity
2570      // check the type of buf in GetIntField above.
2571      result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2572      if (sc.Check(soa, false, "J", &result)) {
2573        return result.J;
2574      }
2575    }
2576    return JNI_ERR;
2577  }
2578
2579 private:
2580  static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2581    return reinterpret_cast<JNIEnvExt*>(env)->vm;
2582  }
2583
2584  static const JNINativeInterface* baseEnv(JNIEnv* env) {
2585    return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2586  }
2587
2588  static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2589    ScopedObjectAccess soa(env);
2590    ScopedCheck sc(kFlag_Default, function_name);
2591    JniValueType args[2] = {{.E = env}, {.L = obj}};
2592    if (sc.Check(soa, true, "EL", args)) {
2593      JniValueType result;
2594      switch (kind) {
2595        case kGlobal:
2596          result.L = baseEnv(env)->NewGlobalRef(env, obj);
2597          break;
2598        case kLocal:
2599          result.L = baseEnv(env)->NewLocalRef(env, obj);
2600          break;
2601        case kWeakGlobal:
2602          result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2603          break;
2604        default:
2605          LOG(FATAL) << "Unexpected reference kind: " << kind;
2606      }
2607      if (sc.Check(soa, false, "L", &result)) {
2608        DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
2609        DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
2610        return result.L;
2611      }
2612    }
2613    return nullptr;
2614  }
2615
2616  static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2617    ScopedObjectAccess soa(env);
2618    ScopedCheck sc(kFlag_ExcepOkay, function_name);
2619    JniValueType args[2] = {{.E = env}, {.L = obj}};
2620    sc.Check(soa, true, "EL", args);
2621    if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
2622      JniValueType result;
2623      switch (kind) {
2624        case kGlobal:
2625          baseEnv(env)->DeleteGlobalRef(env, obj);
2626          break;
2627        case kLocal:
2628          baseEnv(env)->DeleteLocalRef(env, obj);
2629          break;
2630        case kWeakGlobal:
2631          baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2632          break;
2633        default:
2634          LOG(FATAL) << "Unexpected reference kind: " << kind;
2635      }
2636      result.V = nullptr;
2637      sc.Check(soa, false, "V", &result);
2638    }
2639  }
2640
2641  static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2642                                       const char* name, const char* sig, bool is_static) {
2643    ScopedObjectAccess soa(env);
2644    ScopedCheck sc(kFlag_Default, function_name);
2645    JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2646    if (sc.Check(soa, true, "Ecuu", args)) {
2647      JniValueType result;
2648      if (is_static) {
2649        result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2650      } else {
2651        result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2652      }
2653      if (sc.Check(soa, false, "m", &result)) {
2654        return result.m;
2655      }
2656    }
2657    return nullptr;
2658  }
2659
2660  static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2661                                     const char* name, const char* sig, bool is_static) {
2662    ScopedObjectAccess soa(env);
2663    ScopedCheck sc(kFlag_Default, function_name);
2664    JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2665    if (sc.Check(soa, true, "Ecuu", args)) {
2666      JniValueType result;
2667      if (is_static) {
2668        result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2669      } else {
2670        result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2671      }
2672      if (sc.Check(soa, false, "f", &result)) {
2673        return result.f;
2674      }
2675    }
2676    return nullptr;
2677  }
2678
2679  static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2680                               bool is_static, Primitive::Type type) {
2681    ScopedObjectAccess soa(env);
2682    ScopedCheck sc(kFlag_Default, function_name);
2683    JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2684    JniValueType result;
2685    if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2686        sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2687      const char* result_check = nullptr;
2688      switch (type) {
2689        case Primitive::kPrimNot:
2690          if (is_static) {
2691            result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2692          } else {
2693            result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2694          }
2695          result_check = "L";
2696          break;
2697        case Primitive::kPrimBoolean:
2698          if (is_static) {
2699            result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2700          } else {
2701            result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2702          }
2703          result_check = "Z";
2704          break;
2705        case Primitive::kPrimByte:
2706          if (is_static) {
2707            result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2708          } else {
2709            result.B = baseEnv(env)->GetByteField(env, obj, fid);
2710          }
2711          result_check = "B";
2712          break;
2713        case Primitive::kPrimChar:
2714          if (is_static) {
2715            result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2716          } else {
2717            result.C = baseEnv(env)->GetCharField(env, obj, fid);
2718          }
2719          result_check = "C";
2720          break;
2721        case Primitive::kPrimShort:
2722          if (is_static) {
2723            result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2724          } else {
2725            result.S = baseEnv(env)->GetShortField(env, obj, fid);
2726          }
2727          result_check = "S";
2728          break;
2729        case Primitive::kPrimInt:
2730          if (is_static) {
2731            result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2732          } else {
2733            result.I = baseEnv(env)->GetIntField(env, obj, fid);
2734          }
2735          result_check = "I";
2736          break;
2737        case Primitive::kPrimLong:
2738          if (is_static) {
2739            result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2740          } else {
2741            result.J = baseEnv(env)->GetLongField(env, obj, fid);
2742          }
2743          result_check = "J";
2744          break;
2745        case Primitive::kPrimFloat:
2746          if (is_static) {
2747            result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2748          } else {
2749            result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2750          }
2751          result_check = "F";
2752          break;
2753        case Primitive::kPrimDouble:
2754          if (is_static) {
2755            result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2756          } else {
2757            result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2758          }
2759          result_check = "D";
2760          break;
2761        case Primitive::kPrimVoid:
2762          LOG(FATAL) << "Unexpected type: " << type;
2763          break;
2764      }
2765      if (sc.Check(soa, false, result_check, &result)) {
2766        return result;
2767      }
2768    }
2769    result.J = 0;
2770    return result;
2771  }
2772
2773  static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2774                       bool is_static, Primitive::Type type, JniValueType value) {
2775    ScopedObjectAccess soa(env);
2776    ScopedCheck sc(kFlag_Default, function_name);
2777    JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2778    char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2779        type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2780    if (sc.Check(soa, true, sig, args) &&
2781        sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2782      switch (type) {
2783        case Primitive::kPrimNot:
2784          if (is_static) {
2785            baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2786          } else {
2787            baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2788          }
2789          break;
2790        case Primitive::kPrimBoolean:
2791          if (is_static) {
2792            baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2793          } else {
2794            baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2795          }
2796          break;
2797        case Primitive::kPrimByte:
2798          if (is_static) {
2799            baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2800          } else {
2801            baseEnv(env)->SetByteField(env, obj, fid, value.B);
2802          }
2803          break;
2804        case Primitive::kPrimChar:
2805          if (is_static) {
2806            baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2807          } else {
2808            baseEnv(env)->SetCharField(env, obj, fid, value.C);
2809          }
2810          break;
2811        case Primitive::kPrimShort:
2812          if (is_static) {
2813            baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2814          } else {
2815            baseEnv(env)->SetShortField(env, obj, fid, value.S);
2816          }
2817          break;
2818        case Primitive::kPrimInt:
2819          if (is_static) {
2820            baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2821          } else {
2822            baseEnv(env)->SetIntField(env, obj, fid, value.I);
2823          }
2824          break;
2825        case Primitive::kPrimLong:
2826          if (is_static) {
2827            baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2828          } else {
2829            baseEnv(env)->SetLongField(env, obj, fid, value.J);
2830          }
2831          break;
2832        case Primitive::kPrimFloat:
2833          if (is_static) {
2834            baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2835          } else {
2836            baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2837          }
2838          break;
2839        case Primitive::kPrimDouble:
2840          if (is_static) {
2841            baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2842          } else {
2843            baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2844          }
2845          break;
2846        case Primitive::kPrimVoid:
2847          LOG(FATAL) << "Unexpected type: " << type;
2848          break;
2849      }
2850      JniValueType result;
2851      result.V = nullptr;
2852      sc.Check(soa, false, "V", &result);
2853    }
2854  }
2855
2856  static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
2857                            jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
2858      REQUIRES_SHARED(Locks::mutator_lock_) {
2859    bool checked;
2860    switch (invoke) {
2861      case kVirtual: {
2862        DCHECK(c == nullptr);
2863        JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
2864        checked = sc.Check(soa, true, "ELm.", args);
2865        break;
2866      }
2867      case kDirect: {
2868        JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
2869        checked = sc.Check(soa, true, "ELcm.", args);
2870        break;
2871      }
2872      case kStatic: {
2873        DCHECK(obj == nullptr);
2874        JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
2875        checked = sc.Check(soa, true, "Ecm.", args);
2876        break;
2877      }
2878      default:
2879        LOG(FATAL) << "Unexpected invoke: " << invoke;
2880        checked = false;
2881        break;
2882    }
2883    return checked;
2884  }
2885
2886  static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2887                                  jmethodID mid, jvalue* vargs, Primitive::Type type,
2888                                  InvokeType invoke) {
2889    ScopedObjectAccess soa(env);
2890    ScopedCheck sc(kFlag_Default, function_name);
2891    JniValueType result;
2892    VarArgs rest(mid, vargs);
2893    if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
2894        sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2895      const char* result_check;
2896      switch (type) {
2897        case Primitive::kPrimNot:
2898          result_check = "L";
2899          switch (invoke) {
2900            case kVirtual:
2901              result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2902              break;
2903            case kDirect:
2904              result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2905              break;
2906            case kStatic:
2907              result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2908              break;
2909            default:
2910              break;
2911          }
2912          break;
2913        case Primitive::kPrimBoolean:
2914          result_check = "Z";
2915          switch (invoke) {
2916            case kVirtual:
2917              result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2918              break;
2919            case kDirect:
2920              result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2921              break;
2922            case kStatic:
2923              result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2924              break;
2925            default:
2926              break;
2927          }
2928          break;
2929        case Primitive::kPrimByte:
2930          result_check = "B";
2931          switch (invoke) {
2932            case kVirtual:
2933              result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2934              break;
2935            case kDirect:
2936              result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2937              break;
2938            case kStatic:
2939              result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2940              break;
2941            default:
2942              break;
2943          }
2944          break;
2945        case Primitive::kPrimChar:
2946          result_check = "C";
2947          switch (invoke) {
2948            case kVirtual:
2949              result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2950              break;
2951            case kDirect:
2952              result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2953              break;
2954            case kStatic:
2955              result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2956              break;
2957            default:
2958              break;
2959          }
2960          break;
2961        case Primitive::kPrimShort:
2962          result_check = "S";
2963          switch (invoke) {
2964            case kVirtual:
2965              result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2966              break;
2967            case kDirect:
2968              result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2969              break;
2970            case kStatic:
2971              result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2972              break;
2973            default:
2974              break;
2975          }
2976          break;
2977        case Primitive::kPrimInt:
2978          result_check = "I";
2979          switch (invoke) {
2980            case kVirtual:
2981              result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2982              break;
2983            case kDirect:
2984              result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2985              break;
2986            case kStatic:
2987              result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
2988              break;
2989            default:
2990              break;
2991          }
2992          break;
2993        case Primitive::kPrimLong:
2994          result_check = "J";
2995          switch (invoke) {
2996            case kVirtual:
2997              result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
2998              break;
2999            case kDirect:
3000              result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3001              break;
3002            case kStatic:
3003              result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3004              break;
3005            default:
3006              break;
3007          }
3008          break;
3009        case Primitive::kPrimFloat:
3010          result_check = "F";
3011          switch (invoke) {
3012            case kVirtual:
3013              result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3014              break;
3015            case kDirect:
3016              result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3017              break;
3018            case kStatic:
3019              result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3020              break;
3021            default:
3022              break;
3023          }
3024          break;
3025        case Primitive::kPrimDouble:
3026          result_check = "D";
3027          switch (invoke) {
3028            case kVirtual:
3029              result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3030              break;
3031            case kDirect:
3032              result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3033              break;
3034            case kStatic:
3035              result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3036              break;
3037            default:
3038              break;
3039          }
3040          break;
3041        case Primitive::kPrimVoid:
3042          result_check = "V";
3043          result.V = nullptr;
3044          switch (invoke) {
3045            case kVirtual:
3046              baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3047              break;
3048            case kDirect:
3049              baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3050              break;
3051            case kStatic:
3052              baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3053              break;
3054            default:
3055              LOG(FATAL) << "Unexpected invoke: " << invoke;
3056          }
3057          break;
3058        default:
3059          LOG(FATAL) << "Unexpected return type: " << type;
3060          result_check = nullptr;
3061      }
3062      if (sc.Check(soa, false, result_check, &result)) {
3063        return result;
3064      }
3065    }
3066    result.J = 0;
3067    return result;
3068  }
3069
3070  static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3071                                  jmethodID mid, va_list vargs, Primitive::Type type,
3072                                  InvokeType invoke) {
3073    ScopedObjectAccess soa(env);
3074    ScopedCheck sc(kFlag_Default, function_name);
3075    JniValueType result;
3076    VarArgs rest(mid, vargs);
3077    if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
3078        sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3079      const char* result_check;
3080      switch (type) {
3081        case Primitive::kPrimNot:
3082          result_check = "L";
3083          switch (invoke) {
3084            case kVirtual:
3085              result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3086              break;
3087            case kDirect:
3088              result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3089              break;
3090            case kStatic:
3091              result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3092              break;
3093            default:
3094              LOG(FATAL) << "Unexpected invoke: " << invoke;
3095          }
3096          break;
3097        case Primitive::kPrimBoolean:
3098          result_check = "Z";
3099          switch (invoke) {
3100            case kVirtual:
3101              result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3102              break;
3103            case kDirect:
3104              result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3105              break;
3106            case kStatic:
3107              result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3108              break;
3109            default:
3110              LOG(FATAL) << "Unexpected invoke: " << invoke;
3111          }
3112          break;
3113        case Primitive::kPrimByte:
3114          result_check = "B";
3115          switch (invoke) {
3116            case kVirtual:
3117              result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3118              break;
3119            case kDirect:
3120              result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3121              break;
3122            case kStatic:
3123              result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3124              break;
3125            default:
3126              LOG(FATAL) << "Unexpected invoke: " << invoke;
3127          }
3128          break;
3129        case Primitive::kPrimChar:
3130          result_check = "C";
3131          switch (invoke) {
3132            case kVirtual:
3133              result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3134              break;
3135            case kDirect:
3136              result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3137              break;
3138            case kStatic:
3139              result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3140              break;
3141            default:
3142              LOG(FATAL) << "Unexpected invoke: " << invoke;
3143          }
3144          break;
3145        case Primitive::kPrimShort:
3146          result_check = "S";
3147          switch (invoke) {
3148            case kVirtual:
3149              result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3150              break;
3151            case kDirect:
3152              result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3153              break;
3154            case kStatic:
3155              result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3156              break;
3157            default:
3158              LOG(FATAL) << "Unexpected invoke: " << invoke;
3159          }
3160          break;
3161        case Primitive::kPrimInt:
3162          result_check = "I";
3163          switch (invoke) {
3164            case kVirtual:
3165              result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3166              break;
3167            case kDirect:
3168              result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3169              break;
3170            case kStatic:
3171              result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3172              break;
3173            default:
3174              LOG(FATAL) << "Unexpected invoke: " << invoke;
3175          }
3176          break;
3177        case Primitive::kPrimLong:
3178          result_check = "J";
3179          switch (invoke) {
3180            case kVirtual:
3181              result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3182              break;
3183            case kDirect:
3184              result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3185              break;
3186            case kStatic:
3187              result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3188              break;
3189            default:
3190              LOG(FATAL) << "Unexpected invoke: " << invoke;
3191          }
3192          break;
3193        case Primitive::kPrimFloat:
3194          result_check = "F";
3195          switch (invoke) {
3196            case kVirtual:
3197              result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3198              break;
3199            case kDirect:
3200              result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3201              break;
3202            case kStatic:
3203              result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3204              break;
3205            default:
3206              LOG(FATAL) << "Unexpected invoke: " << invoke;
3207          }
3208          break;
3209        case Primitive::kPrimDouble:
3210          result_check = "D";
3211          switch (invoke) {
3212            case kVirtual:
3213              result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3214              break;
3215            case kDirect:
3216              result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3217              break;
3218            case kStatic:
3219              result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3220              break;
3221            default:
3222              LOG(FATAL) << "Unexpected invoke: " << invoke;
3223          }
3224          break;
3225        case Primitive::kPrimVoid:
3226          result_check = "V";
3227          result.V = nullptr;
3228          switch (invoke) {
3229            case kVirtual:
3230              baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3231              break;
3232            case kDirect:
3233              baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3234              break;
3235            case kStatic:
3236              baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3237              break;
3238            default:
3239              LOG(FATAL) << "Unexpected invoke: " << invoke;
3240          }
3241          break;
3242        default:
3243          LOG(FATAL) << "Unexpected return type: " << type;
3244          result_check = nullptr;
3245      }
3246      if (sc.Check(soa, false, result_check, &result)) {
3247        return result;
3248      }
3249    }
3250    result.J = 0;
3251    return result;
3252  }
3253
3254  static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3255                                            jboolean* is_copy, bool utf, bool critical) {
3256    ScopedObjectAccess soa(env);
3257    int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3258    ScopedCheck sc(flags, function_name);
3259    JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3260    if (sc.Check(soa, true, "Esp", args)) {
3261      JniValueType result;
3262      void* ptr;
3263      if (utf) {
3264        CHECK(!critical);
3265        ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3266        result.u = reinterpret_cast<char*>(ptr);
3267      } else {
3268        ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3269            baseEnv(env)->GetStringChars(env, string, is_copy));
3270        result.p = ptr;
3271      }
3272      // TODO: could we be smarter about not copying when local_is_copy?
3273      if (ptr != nullptr && soa.ForceCopy()) {
3274        if (utf) {
3275          size_t length_in_bytes = strlen(result.u) + 1;
3276          result.u =
3277              reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
3278        } else {
3279          size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3280          result.p =
3281              reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
3282        }
3283        if (is_copy != nullptr) {
3284          *is_copy = JNI_TRUE;
3285        }
3286      }
3287      if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3288        return utf ? result.u : result.p;
3289      }
3290    }
3291    return nullptr;
3292  }
3293
3294  static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3295                                         const void* chars, bool utf, bool critical) {
3296    ScopedObjectAccess soa(env);
3297    int flags = kFlag_ExcepOkay | kFlag_Release;
3298    if (critical) {
3299      flags |= kFlag_CritRelease;
3300    }
3301    ScopedCheck sc(flags, function_name);
3302    sc.CheckNonNull(chars);
3303    bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3304    if (force_copy_ok && soa.ForceCopy()) {
3305      chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3306    }
3307    if (force_copy_ok) {
3308      JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3309      if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3310        if (utf) {
3311          CHECK(!critical);
3312          baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3313        } else {
3314          if (critical) {
3315            baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3316          } else {
3317            baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3318          }
3319        }
3320        JniValueType result;
3321        sc.Check(soa, false, "V", &result);
3322      }
3323    }
3324  }
3325
3326  static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3327                                  Primitive::Type type) {
3328    ScopedObjectAccess soa(env);
3329    ScopedCheck sc(kFlag_Default, function_name);
3330    JniValueType args[2] = {{.E = env}, {.z = length}};
3331    if (sc.Check(soa, true, "Ez", args)) {
3332      JniValueType result;
3333      switch (type) {
3334        case Primitive::kPrimBoolean:
3335          result.a = baseEnv(env)->NewBooleanArray(env, length);
3336          break;
3337        case Primitive::kPrimByte:
3338          result.a = baseEnv(env)->NewByteArray(env, length);
3339          break;
3340        case Primitive::kPrimChar:
3341          result.a = baseEnv(env)->NewCharArray(env, length);
3342          break;
3343        case Primitive::kPrimShort:
3344          result.a = baseEnv(env)->NewShortArray(env, length);
3345          break;
3346        case Primitive::kPrimInt:
3347          result.a = baseEnv(env)->NewIntArray(env, length);
3348          break;
3349        case Primitive::kPrimLong:
3350          result.a = baseEnv(env)->NewLongArray(env, length);
3351          break;
3352        case Primitive::kPrimFloat:
3353          result.a = baseEnv(env)->NewFloatArray(env, length);
3354          break;
3355        case Primitive::kPrimDouble:
3356          result.a = baseEnv(env)->NewDoubleArray(env, length);
3357          break;
3358        default:
3359          LOG(FATAL) << "Unexpected primitive type: " << type;
3360      }
3361      if (sc.Check(soa, false, "a", &result)) {
3362        return result.a;
3363      }
3364    }
3365    return nullptr;
3366  }
3367
3368  static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3369                                         JNIEnv* env, jarray array, jboolean* is_copy) {
3370    ScopedObjectAccess soa(env);
3371    ScopedCheck sc(kFlag_Default, function_name);
3372    JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3373    if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3374      JniValueType result;
3375      void* ptr = nullptr;
3376      switch (type) {
3377        case Primitive::kPrimBoolean:
3378          ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3379                                                      is_copy);
3380          break;
3381        case Primitive::kPrimByte:
3382          ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
3383          break;
3384        case Primitive::kPrimChar:
3385          ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
3386          break;
3387        case Primitive::kPrimShort:
3388          ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
3389          break;
3390        case Primitive::kPrimInt:
3391          ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
3392          break;
3393        case Primitive::kPrimLong:
3394          ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
3395          break;
3396        case Primitive::kPrimFloat:
3397          ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
3398          break;
3399        case Primitive::kPrimDouble:
3400          ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
3401          break;
3402        default:
3403          LOG(FATAL) << "Unexpected primitive type: " << type;
3404      }
3405      if (ptr != nullptr && soa.ForceCopy()) {
3406        ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
3407        if (is_copy != nullptr) {
3408          *is_copy = JNI_TRUE;
3409        }
3410      }
3411      result.p = ptr;
3412      if (sc.Check(soa, false, "p", &result)) {
3413        return const_cast<void*>(result.p);
3414      }
3415    }
3416    return nullptr;
3417  }
3418
3419  static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3420                                            JNIEnv* env, jarray array, void* elems, jint mode) {
3421    ScopedObjectAccess soa(env);
3422    ScopedCheck sc(kFlag_ExcepOkay, function_name);
3423    if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3424      if (soa.ForceCopy()) {
3425        elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3426      }
3427      if (!soa.ForceCopy() || elems != nullptr) {
3428        JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3429        if (sc.Check(soa, true, "Eapr", args)) {
3430          switch (type) {
3431            case Primitive::kPrimBoolean:
3432              baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3433                                                        reinterpret_cast<jboolean*>(elems), mode);
3434              break;
3435            case Primitive::kPrimByte:
3436              baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3437                                                     reinterpret_cast<jbyte*>(elems), mode);
3438              break;
3439            case Primitive::kPrimChar:
3440              baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3441                                                     reinterpret_cast<jchar*>(elems), mode);
3442              break;
3443            case Primitive::kPrimShort:
3444              baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3445                                                      reinterpret_cast<jshort*>(elems), mode);
3446              break;
3447            case Primitive::kPrimInt:
3448              baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3449                                                    reinterpret_cast<jint*>(elems), mode);
3450              break;
3451            case Primitive::kPrimLong:
3452              baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3453                                                     reinterpret_cast<jlong*>(elems), mode);
3454              break;
3455            case Primitive::kPrimFloat:
3456              baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3457                                                      reinterpret_cast<jfloat*>(elems), mode);
3458              break;
3459            case Primitive::kPrimDouble:
3460              baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3461                                                       reinterpret_cast<jdouble*>(elems), mode);
3462              break;
3463            default:
3464              LOG(FATAL) << "Unexpected primitive type: " << type;
3465          }
3466          JniValueType result;
3467          result.V = nullptr;
3468          sc.Check(soa, false, "V", &result);
3469        }
3470      }
3471    }
3472  }
3473
3474  static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3475                                      jarray array, jsize start, jsize len, void* buf) {
3476    ScopedObjectAccess soa(env);
3477    ScopedCheck sc(kFlag_Default, function_name);
3478    JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3479    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3480    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3481    if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3482      switch (type) {
3483        case Primitive::kPrimBoolean:
3484          baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3485                                              reinterpret_cast<jboolean*>(buf));
3486          break;
3487        case Primitive::kPrimByte:
3488          baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3489                                           reinterpret_cast<jbyte*>(buf));
3490          break;
3491        case Primitive::kPrimChar:
3492          baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3493                                           reinterpret_cast<jchar*>(buf));
3494          break;
3495        case Primitive::kPrimShort:
3496          baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3497                                            reinterpret_cast<jshort*>(buf));
3498          break;
3499        case Primitive::kPrimInt:
3500          baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3501                                          reinterpret_cast<jint*>(buf));
3502          break;
3503        case Primitive::kPrimLong:
3504          baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3505                                           reinterpret_cast<jlong*>(buf));
3506          break;
3507        case Primitive::kPrimFloat:
3508          baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3509                                            reinterpret_cast<jfloat*>(buf));
3510          break;
3511        case Primitive::kPrimDouble:
3512          baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3513                                             reinterpret_cast<jdouble*>(buf));
3514          break;
3515        default:
3516          LOG(FATAL) << "Unexpected primitive type: " << type;
3517      }
3518      JniValueType result;
3519      result.V = nullptr;
3520      sc.Check(soa, false, "V", &result);
3521    }
3522  }
3523
3524  static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3525                                      jarray array, jsize start, jsize len, const void* buf) {
3526    ScopedObjectAccess soa(env);
3527    ScopedCheck sc(kFlag_Default, function_name);
3528    JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3529    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3530    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3531    if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3532      switch (type) {
3533        case Primitive::kPrimBoolean:
3534          baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3535                                              reinterpret_cast<const jboolean*>(buf));
3536          break;
3537        case Primitive::kPrimByte:
3538          baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3539                                           reinterpret_cast<const jbyte*>(buf));
3540          break;
3541        case Primitive::kPrimChar:
3542          baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3543                                           reinterpret_cast<const jchar*>(buf));
3544          break;
3545        case Primitive::kPrimShort:
3546          baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3547                                              reinterpret_cast<const jshort*>(buf));
3548          break;
3549        case Primitive::kPrimInt:
3550          baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3551                                          reinterpret_cast<const jint*>(buf));
3552          break;
3553        case Primitive::kPrimLong:
3554          baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3555                                              reinterpret_cast<const jlong*>(buf));
3556          break;
3557        case Primitive::kPrimFloat:
3558          baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3559                                            reinterpret_cast<const jfloat*>(buf));
3560          break;
3561        case Primitive::kPrimDouble:
3562          baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3563                                             reinterpret_cast<const jdouble*>(buf));
3564          break;
3565        default:
3566          LOG(FATAL) << "Unexpected primitive type: " << type;
3567      }
3568      JniValueType result;
3569      result.V = nullptr;
3570      sc.Check(soa, false, "V", &result);
3571    }
3572  }
3573};
3574
3575const JNINativeInterface gCheckNativeInterface = {
3576  nullptr,  // reserved0.
3577  nullptr,  // reserved1.
3578  nullptr,  // reserved2.
3579  nullptr,  // reserved3.
3580  CheckJNI::GetVersion,
3581  CheckJNI::DefineClass,
3582  CheckJNI::FindClass,
3583  CheckJNI::FromReflectedMethod,
3584  CheckJNI::FromReflectedField,
3585  CheckJNI::ToReflectedMethod,
3586  CheckJNI::GetSuperclass,
3587  CheckJNI::IsAssignableFrom,
3588  CheckJNI::ToReflectedField,
3589  CheckJNI::Throw,
3590  CheckJNI::ThrowNew,
3591  CheckJNI::ExceptionOccurred,
3592  CheckJNI::ExceptionDescribe,
3593  CheckJNI::ExceptionClear,
3594  CheckJNI::FatalError,
3595  CheckJNI::PushLocalFrame,
3596  CheckJNI::PopLocalFrame,
3597  CheckJNI::NewGlobalRef,
3598  CheckJNI::DeleteGlobalRef,
3599  CheckJNI::DeleteLocalRef,
3600  CheckJNI::IsSameObject,
3601  CheckJNI::NewLocalRef,
3602  CheckJNI::EnsureLocalCapacity,
3603  CheckJNI::AllocObject,
3604  CheckJNI::NewObject,
3605  CheckJNI::NewObjectV,
3606  CheckJNI::NewObjectA,
3607  CheckJNI::GetObjectClass,
3608  CheckJNI::IsInstanceOf,
3609  CheckJNI::GetMethodID,
3610  CheckJNI::CallObjectMethod,
3611  CheckJNI::CallObjectMethodV,
3612  CheckJNI::CallObjectMethodA,
3613  CheckJNI::CallBooleanMethod,
3614  CheckJNI::CallBooleanMethodV,
3615  CheckJNI::CallBooleanMethodA,
3616  CheckJNI::CallByteMethod,
3617  CheckJNI::CallByteMethodV,
3618  CheckJNI::CallByteMethodA,
3619  CheckJNI::CallCharMethod,
3620  CheckJNI::CallCharMethodV,
3621  CheckJNI::CallCharMethodA,
3622  CheckJNI::CallShortMethod,
3623  CheckJNI::CallShortMethodV,
3624  CheckJNI::CallShortMethodA,
3625  CheckJNI::CallIntMethod,
3626  CheckJNI::CallIntMethodV,
3627  CheckJNI::CallIntMethodA,
3628  CheckJNI::CallLongMethod,
3629  CheckJNI::CallLongMethodV,
3630  CheckJNI::CallLongMethodA,
3631  CheckJNI::CallFloatMethod,
3632  CheckJNI::CallFloatMethodV,
3633  CheckJNI::CallFloatMethodA,
3634  CheckJNI::CallDoubleMethod,
3635  CheckJNI::CallDoubleMethodV,
3636  CheckJNI::CallDoubleMethodA,
3637  CheckJNI::CallVoidMethod,
3638  CheckJNI::CallVoidMethodV,
3639  CheckJNI::CallVoidMethodA,
3640  CheckJNI::CallNonvirtualObjectMethod,
3641  CheckJNI::CallNonvirtualObjectMethodV,
3642  CheckJNI::CallNonvirtualObjectMethodA,
3643  CheckJNI::CallNonvirtualBooleanMethod,
3644  CheckJNI::CallNonvirtualBooleanMethodV,
3645  CheckJNI::CallNonvirtualBooleanMethodA,
3646  CheckJNI::CallNonvirtualByteMethod,
3647  CheckJNI::CallNonvirtualByteMethodV,
3648  CheckJNI::CallNonvirtualByteMethodA,
3649  CheckJNI::CallNonvirtualCharMethod,
3650  CheckJNI::CallNonvirtualCharMethodV,
3651  CheckJNI::CallNonvirtualCharMethodA,
3652  CheckJNI::CallNonvirtualShortMethod,
3653  CheckJNI::CallNonvirtualShortMethodV,
3654  CheckJNI::CallNonvirtualShortMethodA,
3655  CheckJNI::CallNonvirtualIntMethod,
3656  CheckJNI::CallNonvirtualIntMethodV,
3657  CheckJNI::CallNonvirtualIntMethodA,
3658  CheckJNI::CallNonvirtualLongMethod,
3659  CheckJNI::CallNonvirtualLongMethodV,
3660  CheckJNI::CallNonvirtualLongMethodA,
3661  CheckJNI::CallNonvirtualFloatMethod,
3662  CheckJNI::CallNonvirtualFloatMethodV,
3663  CheckJNI::CallNonvirtualFloatMethodA,
3664  CheckJNI::CallNonvirtualDoubleMethod,
3665  CheckJNI::CallNonvirtualDoubleMethodV,
3666  CheckJNI::CallNonvirtualDoubleMethodA,
3667  CheckJNI::CallNonvirtualVoidMethod,
3668  CheckJNI::CallNonvirtualVoidMethodV,
3669  CheckJNI::CallNonvirtualVoidMethodA,
3670  CheckJNI::GetFieldID,
3671  CheckJNI::GetObjectField,
3672  CheckJNI::GetBooleanField,
3673  CheckJNI::GetByteField,
3674  CheckJNI::GetCharField,
3675  CheckJNI::GetShortField,
3676  CheckJNI::GetIntField,
3677  CheckJNI::GetLongField,
3678  CheckJNI::GetFloatField,
3679  CheckJNI::GetDoubleField,
3680  CheckJNI::SetObjectField,
3681  CheckJNI::SetBooleanField,
3682  CheckJNI::SetByteField,
3683  CheckJNI::SetCharField,
3684  CheckJNI::SetShortField,
3685  CheckJNI::SetIntField,
3686  CheckJNI::SetLongField,
3687  CheckJNI::SetFloatField,
3688  CheckJNI::SetDoubleField,
3689  CheckJNI::GetStaticMethodID,
3690  CheckJNI::CallStaticObjectMethod,
3691  CheckJNI::CallStaticObjectMethodV,
3692  CheckJNI::CallStaticObjectMethodA,
3693  CheckJNI::CallStaticBooleanMethod,
3694  CheckJNI::CallStaticBooleanMethodV,
3695  CheckJNI::CallStaticBooleanMethodA,
3696  CheckJNI::CallStaticByteMethod,
3697  CheckJNI::CallStaticByteMethodV,
3698  CheckJNI::CallStaticByteMethodA,
3699  CheckJNI::CallStaticCharMethod,
3700  CheckJNI::CallStaticCharMethodV,
3701  CheckJNI::CallStaticCharMethodA,
3702  CheckJNI::CallStaticShortMethod,
3703  CheckJNI::CallStaticShortMethodV,
3704  CheckJNI::CallStaticShortMethodA,
3705  CheckJNI::CallStaticIntMethod,
3706  CheckJNI::CallStaticIntMethodV,
3707  CheckJNI::CallStaticIntMethodA,
3708  CheckJNI::CallStaticLongMethod,
3709  CheckJNI::CallStaticLongMethodV,
3710  CheckJNI::CallStaticLongMethodA,
3711  CheckJNI::CallStaticFloatMethod,
3712  CheckJNI::CallStaticFloatMethodV,
3713  CheckJNI::CallStaticFloatMethodA,
3714  CheckJNI::CallStaticDoubleMethod,
3715  CheckJNI::CallStaticDoubleMethodV,
3716  CheckJNI::CallStaticDoubleMethodA,
3717  CheckJNI::CallStaticVoidMethod,
3718  CheckJNI::CallStaticVoidMethodV,
3719  CheckJNI::CallStaticVoidMethodA,
3720  CheckJNI::GetStaticFieldID,
3721  CheckJNI::GetStaticObjectField,
3722  CheckJNI::GetStaticBooleanField,
3723  CheckJNI::GetStaticByteField,
3724  CheckJNI::GetStaticCharField,
3725  CheckJNI::GetStaticShortField,
3726  CheckJNI::GetStaticIntField,
3727  CheckJNI::GetStaticLongField,
3728  CheckJNI::GetStaticFloatField,
3729  CheckJNI::GetStaticDoubleField,
3730  CheckJNI::SetStaticObjectField,
3731  CheckJNI::SetStaticBooleanField,
3732  CheckJNI::SetStaticByteField,
3733  CheckJNI::SetStaticCharField,
3734  CheckJNI::SetStaticShortField,
3735  CheckJNI::SetStaticIntField,
3736  CheckJNI::SetStaticLongField,
3737  CheckJNI::SetStaticFloatField,
3738  CheckJNI::SetStaticDoubleField,
3739  CheckJNI::NewString,
3740  CheckJNI::GetStringLength,
3741  CheckJNI::GetStringChars,
3742  CheckJNI::ReleaseStringChars,
3743  CheckJNI::NewStringUTF,
3744  CheckJNI::GetStringUTFLength,
3745  CheckJNI::GetStringUTFChars,
3746  CheckJNI::ReleaseStringUTFChars,
3747  CheckJNI::GetArrayLength,
3748  CheckJNI::NewObjectArray,
3749  CheckJNI::GetObjectArrayElement,
3750  CheckJNI::SetObjectArrayElement,
3751  CheckJNI::NewBooleanArray,
3752  CheckJNI::NewByteArray,
3753  CheckJNI::NewCharArray,
3754  CheckJNI::NewShortArray,
3755  CheckJNI::NewIntArray,
3756  CheckJNI::NewLongArray,
3757  CheckJNI::NewFloatArray,
3758  CheckJNI::NewDoubleArray,
3759  CheckJNI::GetBooleanArrayElements,
3760  CheckJNI::GetByteArrayElements,
3761  CheckJNI::GetCharArrayElements,
3762  CheckJNI::GetShortArrayElements,
3763  CheckJNI::GetIntArrayElements,
3764  CheckJNI::GetLongArrayElements,
3765  CheckJNI::GetFloatArrayElements,
3766  CheckJNI::GetDoubleArrayElements,
3767  CheckJNI::ReleaseBooleanArrayElements,
3768  CheckJNI::ReleaseByteArrayElements,
3769  CheckJNI::ReleaseCharArrayElements,
3770  CheckJNI::ReleaseShortArrayElements,
3771  CheckJNI::ReleaseIntArrayElements,
3772  CheckJNI::ReleaseLongArrayElements,
3773  CheckJNI::ReleaseFloatArrayElements,
3774  CheckJNI::ReleaseDoubleArrayElements,
3775  CheckJNI::GetBooleanArrayRegion,
3776  CheckJNI::GetByteArrayRegion,
3777  CheckJNI::GetCharArrayRegion,
3778  CheckJNI::GetShortArrayRegion,
3779  CheckJNI::GetIntArrayRegion,
3780  CheckJNI::GetLongArrayRegion,
3781  CheckJNI::GetFloatArrayRegion,
3782  CheckJNI::GetDoubleArrayRegion,
3783  CheckJNI::SetBooleanArrayRegion,
3784  CheckJNI::SetByteArrayRegion,
3785  CheckJNI::SetCharArrayRegion,
3786  CheckJNI::SetShortArrayRegion,
3787  CheckJNI::SetIntArrayRegion,
3788  CheckJNI::SetLongArrayRegion,
3789  CheckJNI::SetFloatArrayRegion,
3790  CheckJNI::SetDoubleArrayRegion,
3791  CheckJNI::RegisterNatives,
3792  CheckJNI::UnregisterNatives,
3793  CheckJNI::MonitorEnter,
3794  CheckJNI::MonitorExit,
3795  CheckJNI::GetJavaVM,
3796  CheckJNI::GetStringRegion,
3797  CheckJNI::GetStringUTFRegion,
3798  CheckJNI::GetPrimitiveArrayCritical,
3799  CheckJNI::ReleasePrimitiveArrayCritical,
3800  CheckJNI::GetStringCritical,
3801  CheckJNI::ReleaseStringCritical,
3802  CheckJNI::NewWeakGlobalRef,
3803  CheckJNI::DeleteWeakGlobalRef,
3804  CheckJNI::ExceptionCheck,
3805  CheckJNI::NewDirectByteBuffer,
3806  CheckJNI::GetDirectBufferAddress,
3807  CheckJNI::GetDirectBufferCapacity,
3808  CheckJNI::GetObjectRefType,
3809};
3810
3811const JNINativeInterface* GetCheckJniNativeInterface() {
3812  return &gCheckNativeInterface;
3813}
3814
3815class CheckJII {
3816 public:
3817  static jint DestroyJavaVM(JavaVM* vm) {
3818    ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3819    JniValueType args[1] = {{.v = vm}};
3820    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3821    JniValueType result;
3822    result.i = BaseVm(vm)->DestroyJavaVM(vm);
3823    // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3824    // which will delete the JavaVMExt.
3825    sc.CheckNonHeap(nullptr, false, "i", &result);
3826    return result.i;
3827  }
3828
3829  static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
3830    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3831    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3832    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3833    JniValueType result;
3834    result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3835    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3836    return result.i;
3837  }
3838
3839  static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
3840    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3841    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3842    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3843    JniValueType result;
3844    result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3845    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3846    return result.i;
3847  }
3848
3849  static jint DetachCurrentThread(JavaVM* vm) {
3850    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3851    JniValueType args[1] = {{.v = vm}};
3852    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3853    JniValueType result;
3854    result.i = BaseVm(vm)->DetachCurrentThread(vm);
3855    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3856    return result.i;
3857  }
3858
3859  static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3860    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3861    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3862    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3863    JniValueType result;
3864    result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3865    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3866    return result.i;
3867  }
3868
3869 private:
3870  static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3871    return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
3872  }
3873};
3874
3875const JNIInvokeInterface gCheckInvokeInterface = {
3876  nullptr,  // reserved0
3877  nullptr,  // reserved1
3878  nullptr,  // reserved2
3879  CheckJII::DestroyJavaVM,
3880  CheckJII::AttachCurrentThread,
3881  CheckJII::DetachCurrentThread,
3882  CheckJII::GetEnv,
3883  CheckJII::AttachCurrentThreadAsDaemon
3884};
3885
3886const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3887  return &gCheckInvokeInterface;
3888}
3889
3890}  // namespace art
3891