check_jni.cc revision 5f4a09a54eed55de89e194780214a2acfd2cb431
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.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      SHARED_REQUIRES(Locks::mutator_lock_) {
272    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(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      SHARED_REQUIRES(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      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      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      SHARED_REQUIRES(Locks::mutator_lock_) {
363    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 (f->GetDeclaringClass() != c) {
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      SHARED_REQUIRES(Locks::mutator_lock_) {
386    ArtMethod* m = CheckMethodID(soa, mid);
387    if (m == nullptr) {
388      return false;
389    }
390    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      SHARED_REQUIRES(Locks::mutator_lock_) {
407    ArtMethod* m = CheckMethodID(soa, mid);
408    if (m == nullptr) {
409      return false;
410    }
411    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      SHARED_REQUIRES(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      SHARED_REQUIRES(Locks::mutator_lock_) {
560    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      SHARED_REQUIRES(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      SHARED_REQUIRES(Locks::mutator_lock_) {
592    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      SHARED_REQUIRES(Locks::mutator_lock_) {
608    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);
612      return false;
613    }
614    return true;
615  }
616
617  bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
618      SHARED_REQUIRES(Locks::mutator_lock_) {
619    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);
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      SHARED_REQUIRES(Locks::mutator_lock_) {
650    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);
653      return false;
654    }
655    return true;
656  }
657
658  bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
659      SHARED_REQUIRES(Locks::mutator_lock_) {
660    if (!CheckArray(soa, array)) {
661      return false;
662    }
663    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      SHARED_REQUIRES(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      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      mirror::Class* c = o->AsClass();
702      if (field->GetDeclaringClass() != c) {
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      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      SHARED_REQUIRES(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    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);
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);
781        return false;
782      }
783    }
784
785    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
786      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
787      AbortF("%s is an invalid %s: %p (%p)",
788             what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
789             java_object, obj);
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      SHARED_REQUIRES(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      SHARED_REQUIRES(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      SHARED_REQUIRES(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        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      SHARED_REQUIRES(Locks::mutator_lock_) {
1105    if (UNLIKELY(java_array == nullptr)) {
1106      AbortF("jarray was NULL");
1107      return false;
1108    }
1109
1110    mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1111    if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) {
1112      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
1113      AbortF("jarray is an invalid %s: %p (%p)",
1114             ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
1115             java_array, a);
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      SHARED_REQUIRES(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(ERROR));
1150      AbortF("invalid jfieldID: %p", fid);
1151      return nullptr;
1152    }
1153    return f;
1154  }
1155
1156  ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
1157      SHARED_REQUIRES(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(ERROR));
1166      AbortF("invalid jmethodID: %p", mid);
1167      return nullptr;
1168    }
1169    return m;
1170  }
1171
1172  bool CheckThread(JNIEnv* env) SHARED_REQUIRES(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 *correct* 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      AbortF("thread %s using JNIEnv* from thread %s",
1186             ToStr<Thread>(*self).c_str(), ToStr<Thread>(*self).c_str());
1187      return false;
1188    }
1189
1190    // Verify that, if this thread previously made a critical "get" call, we
1191    // do the corresponding "release" call before we try anything else.
1192    switch (flags_ & kFlag_CritMask) {
1193    case kFlag_CritOkay:    // okay to call this method
1194      break;
1195    case kFlag_CritBad:     // not okay to call
1196      if (threadEnv->critical) {
1197        AbortF("thread %s using JNI after critical get",
1198               ToStr<Thread>(*self).c_str());
1199        return false;
1200      }
1201      break;
1202    case kFlag_CritGet:     // this is a "get" call
1203      // Don't check here; we allow nested gets.
1204      threadEnv->critical++;
1205      break;
1206    case kFlag_CritRelease:  // this is a "release" call
1207      threadEnv->critical--;
1208      if (threadEnv->critical < 0) {
1209        AbortF("thread %s called too many critical releases",
1210               ToStr<Thread>(*self).c_str());
1211        return false;
1212      }
1213      break;
1214    default:
1215      LOG(FATAL) << "Bad flags (internal error): " << flags_;
1216    }
1217
1218    // Verify that, if an exception has been raised, the native code doesn't
1219    // make any JNI calls other than the Exception* methods.
1220    if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
1221      mirror::Throwable* exception = self->GetException();
1222      AbortF("JNI %s called with pending exception %s",
1223             function_name_,
1224             exception->Dump().c_str());
1225      return false;
1226    }
1227    return true;
1228  }
1229
1230  // Verifies that "bytes" points to valid Modified UTF-8 data.
1231  bool CheckUtfString(const char* bytes, bool nullable) {
1232    if (bytes == nullptr) {
1233      if (!nullable) {
1234        AbortF("non-nullable const char* was NULL");
1235        return false;
1236      }
1237      return true;
1238    }
1239
1240    const char* errorKind = nullptr;
1241    const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
1242    if (errorKind != nullptr) {
1243      // This is an expensive loop that will resize often, but this isn't supposed to hit in
1244      // practice anyways.
1245      std::ostringstream oss;
1246      oss << std::hex;
1247      const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1248      while (*tmp != 0) {
1249        if (tmp == utf8) {
1250          oss << "<";
1251        }
1252        oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1253        if (tmp == utf8) {
1254          oss << '>';
1255        }
1256        tmp++;
1257        if (*tmp != 0) {
1258          oss << ' ';
1259        }
1260      }
1261
1262      AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
1263          "    string: '%s'\n    input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
1264      return false;
1265    }
1266    return true;
1267  }
1268
1269  // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1270  // sequences in place of encoded surrogate pairs.
1271  static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
1272    while (*bytes != '\0') {
1273      const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1274      // Switch on the high four bits.
1275      switch (*utf8 >> 4) {
1276      case 0x00:
1277      case 0x01:
1278      case 0x02:
1279      case 0x03:
1280      case 0x04:
1281      case 0x05:
1282      case 0x06:
1283      case 0x07:
1284        // Bit pattern 0xxx. No need for any extra bytes.
1285        break;
1286      case 0x08:
1287      case 0x09:
1288      case 0x0a:
1289      case 0x0b:
1290         // Bit patterns 10xx, which are illegal start bytes.
1291        *errorKind = "start";
1292        return utf8;
1293      case 0x0f:
1294        // Bit pattern 1111, which might be the start of a 4 byte sequence.
1295        if ((*utf8 & 0x08) == 0) {
1296          // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1297          // We consume one continuation byte here, and fall through to consume two more.
1298          utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1299          if ((*utf8 & 0xc0) != 0x80) {
1300            *errorKind = "continuation";
1301            return utf8;
1302          }
1303        } else {
1304          *errorKind = "start";
1305          return utf8;
1306        }
1307
1308        // Fall through to the cases below to consume two more continuation bytes.
1309        FALLTHROUGH_INTENDED;
1310      case 0x0e:
1311        // Bit pattern 1110, so there are two additional bytes.
1312        utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1313        if ((*utf8 & 0xc0) != 0x80) {
1314          *errorKind = "continuation";
1315          return utf8;
1316        }
1317
1318        // Fall through to consume one more continuation byte.
1319        FALLTHROUGH_INTENDED;
1320      case 0x0c:
1321      case 0x0d:
1322        // Bit pattern 110x, so there is one additional byte.
1323        utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1324        if ((*utf8 & 0xc0) != 0x80) {
1325          *errorKind = "continuation";
1326          return utf8;
1327        }
1328        break;
1329      }
1330    }
1331    return 0;
1332  }
1333
1334  void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1335    va_list args;
1336    va_start(args, fmt);
1337    Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1338    va_end(args);
1339  }
1340
1341  // The name of the JNI function being checked.
1342  const char* const function_name_;
1343
1344  const int flags_;
1345  int indent_;
1346
1347  const bool has_method_;
1348
1349  DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1350};
1351
1352/*
1353 * ===========================================================================
1354 *      Guarded arrays
1355 * ===========================================================================
1356 */
1357
1358/* this gets tucked in at the start of the buffer; struct size must be even */
1359class GuardedCopy {
1360 public:
1361  /*
1362   * Create an over-sized buffer to hold the contents of "buf".  Copy it in,
1363   * filling in the area around it with guard data.
1364   */
1365  static void* Create(void* original_buf, size_t len, bool mod_okay) {
1366    const size_t new_len = LengthIncludingRedZones(len);
1367    uint8_t* const new_buf = DebugAlloc(new_len);
1368
1369    // If modification is not expected, grab a checksum.
1370    uLong adler = 0;
1371    if (!mod_okay) {
1372      adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
1373    }
1374
1375    GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
1376
1377    // Fill begin region with canary pattern.
1378    const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1379    for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1380      const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1381      if (kCanary[j] == '\0') {
1382        j = 0;
1383      } else {
1384        j++;
1385      }
1386    }
1387
1388    // Copy the data in; note "len" could be zero.
1389    memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1390
1391    // Fill end region with canary pattern.
1392    for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1393      const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1394      if (kCanary[j] == '\0') {
1395        j = 0;
1396      } else {
1397        j++;
1398      }
1399    }
1400
1401    return const_cast<uint8_t*>(copy->BufferWithinRedZones());
1402  }
1403
1404  /*
1405   * Create a guarded copy of a primitive array.  Modifications to the copied
1406   * data are allowed.  Returns a pointer to the copied data.
1407   */
1408  static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1409                                   void* original_ptr) {
1410    ScopedObjectAccess soa(env);
1411
1412    mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1413    size_t component_size = a->GetClass()->GetComponentSize();
1414    size_t byte_count = a->GetLength() * component_size;
1415    void* result = Create(original_ptr, byte_count, true);
1416    if (is_copy != nullptr) {
1417      *is_copy = JNI_TRUE;
1418    }
1419    return result;
1420  }
1421
1422  /*
1423   * Perform the array "release" operation, which may or may not copy data
1424   * back into the managed heap, and may or may not release the underlying storage.
1425   */
1426  static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1427                                    jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1428                                    int mode) {
1429    ScopedObjectAccess soa(env);
1430    if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1431      return nullptr;
1432    }
1433    GuardedCopy* const copy = FromEmbedded(embedded_buf);
1434    void* original_ptr = copy->original_ptr_;
1435    if (mode != JNI_ABORT) {
1436      memcpy(original_ptr, embedded_buf, copy->original_length_);
1437    }
1438    if (mode != JNI_COMMIT) {
1439      Destroy(embedded_buf);
1440    }
1441    return original_ptr;
1442  }
1443
1444
1445  /*
1446   * Free up the guard buffer, scrub it, and return the original pointer.
1447   */
1448  static void* Destroy(void* embedded_buf) {
1449    GuardedCopy* copy = FromEmbedded(embedded_buf);
1450    void* original_ptr = const_cast<void*>(copy->original_ptr_);
1451    size_t len = LengthIncludingRedZones(copy->original_length_);
1452    DebugFree(copy, len);
1453    return original_ptr;
1454  }
1455
1456  /*
1457   * Verify the guard area and, if "modOkay" is false, that the data itself
1458   * has not been altered.
1459   *
1460   * The caller has already checked that "dataBuf" is non-null.
1461   */
1462  static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1463    const GuardedCopy* copy = FromEmbedded(embedded_buf);
1464    return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
1465  }
1466
1467 private:
1468  GuardedCopy(void* original_buf, size_t len, uLong adler) :
1469    magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1470  }
1471
1472  static uint8_t* DebugAlloc(size_t len) {
1473    void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
1474    if (result == MAP_FAILED) {
1475      PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1476    }
1477    return reinterpret_cast<uint8_t*>(result);
1478  }
1479
1480  static void DebugFree(void* buf, size_t len) {
1481    if (munmap(buf, len) != 0) {
1482      PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
1483    }
1484  }
1485
1486  static size_t LengthIncludingRedZones(size_t len) {
1487    return len + kRedZoneSize;
1488  }
1489
1490  // Get the GuardedCopy from the interior pointer.
1491  static GuardedCopy* FromEmbedded(void* embedded_buf) {
1492    return reinterpret_cast<GuardedCopy*>(
1493        reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
1494  }
1495
1496  static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1497    return reinterpret_cast<const GuardedCopy*>(
1498        reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
1499  }
1500
1501  static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1502    va_list args;
1503    va_start(args, fmt);
1504    Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1505    va_end(args);
1506  }
1507
1508  bool CheckHeader(const char* function_name, bool mod_okay) const {
1509    static const uint32_t kMagicCmp = kGuardMagic;
1510
1511    // Before we do anything with "pExtra", check the magic number.  We
1512    // do the check with memcmp rather than "==" in case the pointer is
1513    // unaligned.  If it points to completely bogus memory we're going
1514    // to crash, but there's no easy way around that.
1515    if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1516      uint8_t buf[4];
1517      memcpy(buf, &magic_, 4);
1518      AbortF(function_name,
1519             "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1520             buf[3], buf[2], buf[1], buf[0], this);  // Assumes little-endian.
1521      return false;
1522    }
1523
1524    // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1525    // told the client that we made a copy, there's no reason they can't alter the buffer.
1526    if (!mod_okay) {
1527      uLong computed_adler =
1528          adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1529      if (computed_adler != adler_) {
1530        AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1531               computed_adler, adler_, this);
1532        return false;
1533      }
1534    }
1535    return true;
1536  }
1537
1538  bool CheckRedZones(const char* function_name) const {
1539    // Check the begin red zone.
1540    const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1541    for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1542      if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1543        AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1544        return false;
1545      }
1546      if (kCanary[j] == '\0') {
1547        j = 0;
1548      } else {
1549        j++;
1550      }
1551    }
1552
1553    // Check end region.
1554    for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1555      if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1556        size_t offset_from_buffer_start =
1557            &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1558        AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1559               offset_from_buffer_start);
1560        return false;
1561      }
1562      if (kCanary[j] == '\0') {
1563        j = 0;
1564      } else {
1565        j++;
1566      }
1567    }
1568    return true;
1569  }
1570
1571  // Location that canary value will be written before the guarded region.
1572  const char* StartRedZone() const {
1573    const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1574    return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1575  }
1576
1577  // Return the interior embedded buffer.
1578  const uint8_t* BufferWithinRedZones() const {
1579    const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1580    return embedded_buf;
1581  }
1582
1583  // Location that canary value will be written after the guarded region.
1584  const char* EndRedZone() const {
1585    const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1586    size_t buf_len = LengthIncludingRedZones(original_length_);
1587    return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1588  }
1589
1590  static constexpr size_t kRedZoneSize = 512;
1591  static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1592
1593  // Value written before and after the guarded array.
1594  static const char* const kCanary;
1595
1596  static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1597
1598  const uint32_t magic_;
1599  const uLong adler_;
1600  void* const original_ptr_;
1601  const size_t original_length_;
1602};
1603const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
1604
1605/*
1606 * ===========================================================================
1607 *      JNI functions
1608 * ===========================================================================
1609 */
1610
1611class CheckJNI {
1612 public:
1613  static jint GetVersion(JNIEnv* env) {
1614    ScopedObjectAccess soa(env);
1615    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1616    JniValueType args[1] = {{.E = env }};
1617    if (sc.Check(soa, true, "E", args)) {
1618      JniValueType result;
1619      result.I = baseEnv(env)->GetVersion(env);
1620      if (sc.Check(soa, false, "I", &result)) {
1621        return result.I;
1622      }
1623    }
1624    return JNI_ERR;
1625  }
1626
1627  static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1628    ScopedObjectAccess soa(env);
1629    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1630    JniValueType args[2] = {{.E = env }, {.p = vm}};
1631    if (sc.Check(soa, true, "Ep", args)) {
1632      JniValueType result;
1633      result.i = baseEnv(env)->GetJavaVM(env, vm);
1634      if (sc.Check(soa, false, "i", &result)) {
1635        return result.i;
1636      }
1637    }
1638    return JNI_ERR;
1639  }
1640
1641  static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1642    ScopedObjectAccess soa(env);
1643    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1644    JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1645    if (sc.Check(soa, true, "EcpI", args)) {
1646      JniValueType result;
1647      result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1648      if (sc.Check(soa, false, "i", &result)) {
1649        return result.i;
1650      }
1651    }
1652    return JNI_ERR;
1653  }
1654
1655  static jint UnregisterNatives(JNIEnv* env, jclass c) {
1656    ScopedObjectAccess soa(env);
1657    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1658    JniValueType args[2] = {{.E = env }, {.c = c}};
1659    if (sc.Check(soa, true, "Ec", args)) {
1660      JniValueType result;
1661      result.i = baseEnv(env)->UnregisterNatives(env, c);
1662      if (sc.Check(soa, false, "i", &result)) {
1663        return result.i;
1664      }
1665    }
1666    return JNI_ERR;
1667  }
1668
1669  static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1670    // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1671    // know the object is invalid. The spec says that passing invalid objects or even ones that
1672    // are deleted isn't supported.
1673    ScopedObjectAccess soa(env);
1674    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1675    JniValueType args[2] = {{.E = env }, {.L = obj}};
1676    if (sc.Check(soa, true, "EL", args)) {
1677      JniValueType result;
1678      result.w = baseEnv(env)->GetObjectRefType(env, obj);
1679      if (sc.Check(soa, false, "w", &result)) {
1680        return result.w;
1681      }
1682    }
1683    return JNIInvalidRefType;
1684  }
1685
1686  static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1687                            jsize bufLen) {
1688    ScopedObjectAccess soa(env);
1689    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1690    JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1691    if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1692      JniValueType result;
1693      result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1694      if (sc.Check(soa, false, "c", &result)) {
1695        return result.c;
1696      }
1697    }
1698    return nullptr;
1699  }
1700
1701  static jclass FindClass(JNIEnv* env, const char* name) {
1702    ScopedObjectAccess soa(env);
1703    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1704    JniValueType args[2] = {{.E = env}, {.u = name}};
1705    if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1706      JniValueType result;
1707      result.c = baseEnv(env)->FindClass(env, name);
1708      if (sc.Check(soa, false, "c", &result)) {
1709        return result.c;
1710      }
1711    }
1712    return nullptr;
1713  }
1714
1715  static jclass GetSuperclass(JNIEnv* env, jclass c) {
1716    ScopedObjectAccess soa(env);
1717    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1718    JniValueType args[2] = {{.E = env}, {.c = c}};
1719    if (sc.Check(soa, true, "Ec", args)) {
1720      JniValueType result;
1721      result.c = baseEnv(env)->GetSuperclass(env, c);
1722      if (sc.Check(soa, false, "c", &result)) {
1723        return result.c;
1724      }
1725    }
1726    return nullptr;
1727  }
1728
1729  static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
1730    ScopedObjectAccess soa(env);
1731    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1732    JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1733    if (sc.Check(soa, true, "Ecc", args)) {
1734      JniValueType result;
1735      result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1736      if (sc.Check(soa, false, "b", &result)) {
1737        return result.b;
1738      }
1739    }
1740    return JNI_FALSE;
1741  }
1742
1743  static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
1744    ScopedObjectAccess soa(env);
1745    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1746    JniValueType args[2] = {{.E = env}, {.L = method}};
1747    if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1748      JniValueType result;
1749      result.m = baseEnv(env)->FromReflectedMethod(env, method);
1750      if (sc.Check(soa, false, "m", &result)) {
1751        return result.m;
1752      }
1753    }
1754    return nullptr;
1755  }
1756
1757  static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
1758    ScopedObjectAccess soa(env);
1759    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1760    JniValueType args[2] = {{.E = env}, {.L = field}};
1761    if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1762      JniValueType result;
1763      result.f = baseEnv(env)->FromReflectedField(env, field);
1764      if (sc.Check(soa, false, "f", &result)) {
1765        return result.f;
1766      }
1767    }
1768    return nullptr;
1769  }
1770
1771  static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
1772    ScopedObjectAccess soa(env);
1773    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1774    JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1775    if (sc.Check(soa, true, "Ecmb", args)) {
1776      JniValueType result;
1777      result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1778      if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1779        DCHECK(sc.CheckReflectedMethod(soa, result.L));
1780        return result.L;
1781      }
1782    }
1783    return nullptr;
1784  }
1785
1786  static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
1787    ScopedObjectAccess soa(env);
1788    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1789    JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1790    if (sc.Check(soa, true, "Ecfb", args)) {
1791      JniValueType result;
1792      result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1793      if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1794        DCHECK(sc.CheckReflectedField(soa, result.L));
1795        return result.L;
1796      }
1797    }
1798    return nullptr;
1799  }
1800
1801  static jint Throw(JNIEnv* env, jthrowable obj) {
1802    ScopedObjectAccess soa(env);
1803    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1804    JniValueType args[2] = {{.E = env}, {.t = obj}};
1805    if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1806      JniValueType result;
1807      result.i = baseEnv(env)->Throw(env, obj);
1808      if (sc.Check(soa, false, "i", &result)) {
1809        return result.i;
1810      }
1811    }
1812    return JNI_ERR;
1813  }
1814
1815  static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
1816    ScopedObjectAccess soa(env);
1817    ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
1818    JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
1819    if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1820      JniValueType result;
1821      result.i = baseEnv(env)->ThrowNew(env, c, message);
1822      if (sc.Check(soa, false, "i", &result)) {
1823        return result.i;
1824      }
1825    }
1826    return JNI_ERR;
1827  }
1828
1829  static jthrowable ExceptionOccurred(JNIEnv* env) {
1830    ScopedObjectAccess soa(env);
1831    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1832    JniValueType args[1] = {{.E = env}};
1833    if (sc.Check(soa, true, "E", args)) {
1834      JniValueType result;
1835      result.t = baseEnv(env)->ExceptionOccurred(env);
1836      if (sc.Check(soa, false, "t", &result)) {
1837        return result.t;
1838      }
1839    }
1840    return nullptr;
1841  }
1842
1843  static void ExceptionDescribe(JNIEnv* env) {
1844    ScopedObjectAccess soa(env);
1845    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1846    JniValueType args[1] = {{.E = env}};
1847    if (sc.Check(soa, true, "E", args)) {
1848      JniValueType result;
1849      baseEnv(env)->ExceptionDescribe(env);
1850      result.V = nullptr;
1851      sc.Check(soa, false, "V", &result);
1852    }
1853  }
1854
1855  static void ExceptionClear(JNIEnv* env) {
1856    ScopedObjectAccess soa(env);
1857    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1858    JniValueType args[1] = {{.E = env}};
1859    if (sc.Check(soa, true, "E", args)) {
1860      JniValueType result;
1861      baseEnv(env)->ExceptionClear(env);
1862      result.V = nullptr;
1863      sc.Check(soa, false, "V", &result);
1864    }
1865  }
1866
1867  static jboolean ExceptionCheck(JNIEnv* env) {
1868    ScopedObjectAccess soa(env);
1869    ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1870    JniValueType args[1] = {{.E = env}};
1871    if (sc.Check(soa, true, "E", args)) {
1872      JniValueType result;
1873      result.b = baseEnv(env)->ExceptionCheck(env);
1874      if (sc.Check(soa, false, "b", &result)) {
1875        return result.b;
1876      }
1877    }
1878    return JNI_FALSE;
1879  }
1880
1881  static void FatalError(JNIEnv* env, const char* msg) {
1882    // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1883    // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1884    // and it's not unimaginable that you don't know that you do. So we allow it.
1885    ScopedObjectAccess soa(env);
1886    ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1887    JniValueType args[2] = {{.E = env}, {.u = msg}};
1888    if (sc.Check(soa, true, "Eu", args)) {
1889      JniValueType result;
1890      baseEnv(env)->FatalError(env, msg);
1891      // Unreachable.
1892      result.V = nullptr;
1893      sc.Check(soa, false, "V", &result);
1894    }
1895  }
1896
1897  static jint PushLocalFrame(JNIEnv* env, jint capacity) {
1898    ScopedObjectAccess soa(env);
1899    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1900    JniValueType args[2] = {{.E = env}, {.I = capacity}};
1901    if (sc.Check(soa, true, "EI", args)) {
1902      JniValueType result;
1903      result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1904      if (sc.Check(soa, false, "i", &result)) {
1905        return result.i;
1906      }
1907    }
1908    return JNI_ERR;
1909  }
1910
1911  static jobject PopLocalFrame(JNIEnv* env, jobject res) {
1912    ScopedObjectAccess soa(env);
1913    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1914    JniValueType args[2] = {{.E = env}, {.L = res}};
1915    if (sc.Check(soa, true, "EL", args)) {
1916      JniValueType result;
1917      result.L = baseEnv(env)->PopLocalFrame(env, res);
1918      sc.Check(soa, false, "L", &result);
1919      return result.L;
1920    }
1921    return nullptr;
1922  }
1923
1924  static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
1925    return NewRef(__FUNCTION__, env, obj, kGlobal);
1926  }
1927
1928  static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1929    return NewRef(__FUNCTION__, env, obj, kLocal);
1930  }
1931
1932  static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
1933    return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
1934  }
1935
1936  static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1937    DeleteRef(__FUNCTION__, env, obj, kGlobal);
1938  }
1939
1940  static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1941    DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1942  }
1943
1944  static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1945    DeleteRef(__FUNCTION__, env, obj, kLocal);
1946  }
1947
1948  static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1949    ScopedObjectAccess soa(env);
1950    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1951    JniValueType args[2] = {{.E = env}, {.I = capacity}};
1952    if (sc.Check(soa, true, "EI", args)) {
1953      JniValueType result;
1954      result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1955      if (sc.Check(soa, false, "i", &result)) {
1956        return result.i;
1957      }
1958    }
1959    return JNI_ERR;
1960  }
1961
1962  static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1963    ScopedObjectAccess soa(env);
1964    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1965    JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1966    if (sc.Check(soa, true, "ELL", args)) {
1967      JniValueType result;
1968      result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1969      if (sc.Check(soa, false, "b", &result)) {
1970        return result.b;
1971      }
1972    }
1973    return JNI_FALSE;
1974  }
1975
1976  static jobject AllocObject(JNIEnv* env, jclass c) {
1977    ScopedObjectAccess soa(env);
1978    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1979    JniValueType args[2] = {{.E = env}, {.c = c}};
1980    if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1981      JniValueType result;
1982      result.L = baseEnv(env)->AllocObject(env, c);
1983      if (sc.Check(soa, false, "L", &result)) {
1984        return result.L;
1985      }
1986    }
1987    return nullptr;
1988  }
1989
1990  static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1991    ScopedObjectAccess soa(env);
1992    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1993    VarArgs rest(mid, vargs);
1994    JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
1995    if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
1996        sc.CheckConstructor(soa, mid)) {
1997      JniValueType result;
1998      result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
1999      if (sc.Check(soa, false, "L", &result)) {
2000        return result.L;
2001      }
2002    }
2003    return nullptr;
2004  }
2005
2006  static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2007    va_list args;
2008    va_start(args, mid);
2009    jobject result = NewObjectV(env, c, mid, args);
2010    va_end(args);
2011    return result;
2012  }
2013
2014  static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2015    ScopedObjectAccess soa(env);
2016    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2017    VarArgs rest(mid, vargs);
2018    JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2019    if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
2020        sc.CheckConstructor(soa, mid)) {
2021      JniValueType result;
2022      result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2023      if (sc.Check(soa, false, "L", &result)) {
2024        return result.L;
2025      }
2026    }
2027    return nullptr;
2028  }
2029
2030  static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2031    ScopedObjectAccess soa(env);
2032    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2033    JniValueType args[2] = {{.E = env}, {.L = obj}};
2034    if (sc.Check(soa, true, "EL", args)) {
2035      JniValueType result;
2036      result.c = baseEnv(env)->GetObjectClass(env, obj);
2037      if (sc.Check(soa, false, "c", &result)) {
2038        return result.c;
2039      }
2040    }
2041    return nullptr;
2042  }
2043
2044  static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2045    ScopedObjectAccess soa(env);
2046    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2047    JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2048    if (sc.Check(soa, true, "ELc", args)) {
2049      JniValueType result;
2050      result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2051      if (sc.Check(soa, false, "b", &result)) {
2052        return result.b;
2053      }
2054    }
2055    return JNI_FALSE;
2056  }
2057
2058  static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2059    return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2060  }
2061
2062  static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2063    return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2064  }
2065
2066  static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2067    return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2068  }
2069
2070  static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2071    return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2072  }
2073
2074#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
2075  static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2076    return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2077  } \
2078  \
2079  static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2080    return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2081  } \
2082  \
2083  static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2084    JniValueType value; \
2085    value.shorty = v; \
2086    SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2087  } \
2088  \
2089  static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2090    JniValueType value; \
2091    value.shorty = v; \
2092    SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2093  }
2094
2095  FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
2096  FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2097  FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
2098  FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
2099  FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
2100  FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
2101  FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
2102  FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
2103  FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
2104#undef FIELD_ACCESSORS
2105
2106  static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
2107    CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2108  }
2109
2110  static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2111                                        jvalue* vargs) {
2112    CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2113  }
2114
2115  static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2116    CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2117  }
2118
2119  static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2120    CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2121  }
2122
2123  static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2124                                        va_list vargs) {
2125    CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2126  }
2127
2128  static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2129    CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2130  }
2131
2132  static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2133    va_list vargs;
2134    va_start(vargs, mid);
2135    CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2136    va_end(vargs);
2137  }
2138
2139  static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2140    va_list vargs;
2141    va_start(vargs, mid);
2142    CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2143    va_end(vargs);
2144  }
2145
2146  static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2147    va_list vargs;
2148    va_start(vargs, mid);
2149    CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2150    va_end(vargs);
2151  }
2152
2153#define CALL(rtype, name, ptype, shorty) \
2154  static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
2155    return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2156  } \
2157  \
2158  static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2159                                             jvalue* vargs) { \
2160    return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2161  } \
2162  \
2163  static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2164    return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2165  } \
2166  \
2167  static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2168    return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2169  } \
2170  \
2171  static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2172                                             va_list vargs) { \
2173    return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2174  } \
2175  \
2176  static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2177    return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2178  } \
2179  \
2180  static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2181    va_list vargs; \
2182    va_start(vargs, mid); \
2183    rtype result = \
2184        CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2185    va_end(vargs); \
2186    return result; \
2187  } \
2188  \
2189  static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2190                                            ...) { \
2191    va_list vargs; \
2192    va_start(vargs, mid); \
2193    rtype result = \
2194        CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2195    va_end(vargs); \
2196    return result; \
2197  } \
2198  \
2199  static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2200    va_list vargs; \
2201    va_start(vargs, mid); \
2202    rtype result = \
2203        CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2204    va_end(vargs); \
2205    return result; \
2206  }
2207
2208  CALL(jobject, Object, Primitive::kPrimNot, L)
2209  CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2210  CALL(jbyte, Byte, Primitive::kPrimByte, B)
2211  CALL(jchar, Char, Primitive::kPrimChar, C)
2212  CALL(jshort, Short, Primitive::kPrimShort, S)
2213  CALL(jint, Int, Primitive::kPrimInt, I)
2214  CALL(jlong, Long, Primitive::kPrimLong, J)
2215  CALL(jfloat, Float, Primitive::kPrimFloat, F)
2216  CALL(jdouble, Double, Primitive::kPrimDouble, D)
2217#undef CALL
2218
2219  static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2220    ScopedObjectAccess soa(env);
2221    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2222    JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2223    if (sc.Check(soa, true, "Epz", args)) {
2224      JniValueType result;
2225      result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2226      if (sc.Check(soa, false, "s", &result)) {
2227        return result.s;
2228      }
2229    }
2230    return nullptr;
2231  }
2232
2233  static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2234    ScopedObjectAccess soa(env);
2235    ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2236    JniValueType args[2] = {{.E = env}, {.u = chars}};
2237    if (sc.Check(soa, true, "Eu", args)) {
2238      JniValueType result;
2239      // TODO: stale? show pointer and truncate string.
2240      result.s = baseEnv(env)->NewStringUTF(env, chars);
2241      if (sc.Check(soa, false, "s", &result)) {
2242        return result.s;
2243      }
2244    }
2245    return nullptr;
2246  }
2247
2248  static jsize GetStringLength(JNIEnv* env, jstring string) {
2249    ScopedObjectAccess soa(env);
2250    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2251    JniValueType args[2] = {{.E = env}, {.s = string}};
2252    if (sc.Check(soa, true, "Es", args)) {
2253      JniValueType result;
2254      result.z = baseEnv(env)->GetStringLength(env, string);
2255      if (sc.Check(soa, false, "z", &result)) {
2256        return result.z;
2257      }
2258    }
2259    return JNI_ERR;
2260  }
2261
2262  static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2263    ScopedObjectAccess soa(env);
2264    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2265    JniValueType args[2] = {{.E = env}, {.s = string}};
2266    if (sc.Check(soa, true, "Es", args)) {
2267      JniValueType result;
2268      result.z = baseEnv(env)->GetStringUTFLength(env, string);
2269      if (sc.Check(soa, false, "z", &result)) {
2270        return result.z;
2271      }
2272    }
2273    return JNI_ERR;
2274  }
2275
2276  static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2277    return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2278                                                                 is_copy, false, false));
2279  }
2280
2281  static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2282    return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2283                                                                is_copy, true, false));
2284  }
2285
2286  static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2287    return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2288                                                                 is_copy, false, true));
2289  }
2290
2291  static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2292    ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2293  }
2294
2295  static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2296    ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2297  }
2298
2299  static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2300    ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2301  }
2302
2303  static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2304    ScopedObjectAccess soa(env);
2305    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2306    JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2307    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2308    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2309    if (sc.Check(soa, true, "EsIIp", args)) {
2310      baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2311      JniValueType result;
2312      result.V = nullptr;
2313      sc.Check(soa, false, "V", &result);
2314    }
2315  }
2316
2317  static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2318    ScopedObjectAccess soa(env);
2319    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2320    JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2321    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2322    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2323    if (sc.Check(soa, true, "EsIIp", args)) {
2324      baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2325      JniValueType result;
2326      result.V = nullptr;
2327      sc.Check(soa, false, "V", &result);
2328    }
2329  }
2330
2331  static jsize GetArrayLength(JNIEnv* env, jarray array) {
2332    ScopedObjectAccess soa(env);
2333    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2334    JniValueType args[2] = {{.E = env}, {.a = array}};
2335    if (sc.Check(soa, true, "Ea", args)) {
2336      JniValueType result;
2337      result.z = baseEnv(env)->GetArrayLength(env, array);
2338      if (sc.Check(soa, false, "z", &result)) {
2339        return result.z;
2340      }
2341    }
2342    return JNI_ERR;
2343  }
2344
2345  static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2346                                     jobject initial_element) {
2347    ScopedObjectAccess soa(env);
2348    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2349    JniValueType args[4] =
2350        {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2351    if (sc.Check(soa, true, "EzcL", args)) {
2352      JniValueType result;
2353      // Note: assignability tests of initial_element are done in the base implementation.
2354      result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2355      if (sc.Check(soa, false, "a", &result)) {
2356        return down_cast<jobjectArray>(result.a);
2357      }
2358    }
2359    return nullptr;
2360  }
2361
2362  static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2363    ScopedObjectAccess soa(env);
2364    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2365    JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2366    if (sc.Check(soa, true, "Eaz", args)) {
2367      JniValueType result;
2368      result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2369      if (sc.Check(soa, false, "L", &result)) {
2370        return result.L;
2371      }
2372    }
2373    return nullptr;
2374  }
2375
2376  static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2377    ScopedObjectAccess soa(env);
2378    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2379    JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2380    // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2381    // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2382    // in ArrayStoreExceptions.
2383    if (sc.Check(soa, true, "EaIL", args)) {
2384      baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2385      JniValueType result;
2386      result.V = nullptr;
2387      sc.Check(soa, false, "V", &result);
2388    }
2389  }
2390
2391  static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2392    return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2393                                                      Primitive::kPrimBoolean));
2394  }
2395
2396  static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2397    return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2398                                                   Primitive::kPrimByte));
2399  }
2400
2401  static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2402    return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2403                                                   Primitive::kPrimChar));
2404  }
2405
2406  static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2407    return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2408                                                    Primitive::kPrimShort));
2409  }
2410
2411  static jintArray NewIntArray(JNIEnv* env, jsize length) {
2412    return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2413  }
2414
2415  static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2416    return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2417                                                   Primitive::kPrimLong));
2418  }
2419
2420  static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2421    return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2422                                                    Primitive::kPrimFloat));
2423  }
2424
2425  static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2426    return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2427                                                     Primitive::kPrimDouble));
2428  }
2429
2430#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
2431  static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { \
2432    return reinterpret_cast<ctype*>( \
2433        GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2434  } \
2435  \
2436  static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, \
2437                                           jint mode) { \
2438    ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2439  } \
2440  \
2441  static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2442                                     ctype* buf) { \
2443    GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2444  } \
2445  \
2446  static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2447                                     const ctype* buf) { \
2448    SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2449  }
2450
2451  PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2452  PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2453  PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2454  PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2455  PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2456  PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2457  PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2458  PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2459#undef PRIMITIVE_ARRAY_FUNCTIONS
2460
2461  static jint MonitorEnter(JNIEnv* env, jobject obj) {
2462    ScopedObjectAccess soa(env);
2463    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2464    JniValueType args[2] = {{.E = env}, {.L = obj}};
2465    if (sc.Check(soa, true, "EL", args)) {
2466      if (obj != nullptr) {
2467        down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2468      }
2469      JniValueType result;
2470      result.i = baseEnv(env)->MonitorEnter(env, obj);
2471      if (sc.Check(soa, false, "i", &result)) {
2472        return result.i;
2473      }
2474    }
2475    return JNI_ERR;
2476  }
2477
2478  static jint MonitorExit(JNIEnv* env, jobject obj) {
2479    ScopedObjectAccess soa(env);
2480    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2481    JniValueType args[2] = {{.E = env}, {.L = obj}};
2482    if (sc.Check(soa, true, "EL", args)) {
2483      if (obj != nullptr) {
2484        down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2485      }
2486      JniValueType result;
2487      result.i = baseEnv(env)->MonitorExit(env, obj);
2488      if (sc.Check(soa, false, "i", &result)) {
2489        return result.i;
2490      }
2491    }
2492    return JNI_ERR;
2493  }
2494
2495  static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2496    ScopedObjectAccess soa(env);
2497    ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2498    JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2499    if (sc.Check(soa, true, "Eap", args)) {
2500      JniValueType result;
2501      void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2502      if (ptr != nullptr && soa.ForceCopy()) {
2503        ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
2504      }
2505      result.p = ptr;
2506      if (sc.Check(soa, false, "p", &result)) {
2507        return const_cast<void*>(result.p);
2508      }
2509    }
2510    return nullptr;
2511  }
2512
2513  static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2514    ScopedObjectAccess soa(env);
2515    ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2516    sc.CheckNonNull(carray);
2517    JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2518    if (sc.Check(soa, true, "Eapr", args)) {
2519      if (soa.ForceCopy()) {
2520        carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
2521      }
2522      baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2523      JniValueType result;
2524      result.V = nullptr;
2525      sc.Check(soa, false, "V", &result);
2526    }
2527  }
2528
2529  static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
2530    ScopedObjectAccess soa(env);
2531    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2532    JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2533    if (sc.Check(soa, true, "EpJ", args)) {
2534      JniValueType result;
2535      // Note: the validity of address and capacity are checked in the base implementation.
2536      result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2537      if (sc.Check(soa, false, "L", &result)) {
2538        return result.L;
2539      }
2540    }
2541    return nullptr;
2542  }
2543
2544  static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
2545    ScopedObjectAccess soa(env);
2546    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2547    JniValueType args[2] = {{.E = env}, {.L = buf}};
2548    if (sc.Check(soa, true, "EL", args)) {
2549      JniValueType result;
2550      // Note: this is implemented in the base environment by a GetLongField which will sanity
2551      // check the type of buf in GetLongField above.
2552      result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2553      if (sc.Check(soa, false, "p", &result)) {
2554        return const_cast<void*>(result.p);
2555      }
2556    }
2557    return nullptr;
2558  }
2559
2560  static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
2561    ScopedObjectAccess soa(env);
2562    ScopedCheck sc(kFlag_Default, __FUNCTION__);
2563    JniValueType args[2] = {{.E = env}, {.L = buf}};
2564    if (sc.Check(soa, true, "EL", args)) {
2565      JniValueType result;
2566      // Note: this is implemented in the base environment by a GetIntField which will sanity
2567      // check the type of buf in GetIntField above.
2568      result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2569      if (sc.Check(soa, false, "J", &result)) {
2570        return result.J;
2571      }
2572    }
2573    return JNI_ERR;
2574  }
2575
2576 private:
2577  static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2578    return reinterpret_cast<JNIEnvExt*>(env)->vm;
2579  }
2580
2581  static const JNINativeInterface* baseEnv(JNIEnv* env) {
2582    return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2583  }
2584
2585  static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2586    ScopedObjectAccess soa(env);
2587    ScopedCheck sc(kFlag_Default, function_name);
2588    JniValueType args[2] = {{.E = env}, {.L = obj}};
2589    if (sc.Check(soa, true, "EL", args)) {
2590      JniValueType result;
2591      switch (kind) {
2592        case kGlobal:
2593          result.L = baseEnv(env)->NewGlobalRef(env, obj);
2594          break;
2595        case kLocal:
2596          result.L = baseEnv(env)->NewLocalRef(env, obj);
2597          break;
2598        case kWeakGlobal:
2599          result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2600          break;
2601        default:
2602          LOG(FATAL) << "Unexpected reference kind: " << kind;
2603      }
2604      if (sc.Check(soa, false, "L", &result)) {
2605        DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
2606        DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
2607        return result.L;
2608      }
2609    }
2610    return nullptr;
2611  }
2612
2613  static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2614    ScopedObjectAccess soa(env);
2615    ScopedCheck sc(kFlag_ExcepOkay, function_name);
2616    JniValueType args[2] = {{.E = env}, {.L = obj}};
2617    sc.Check(soa, true, "EL", args);
2618    if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
2619      JniValueType result;
2620      switch (kind) {
2621        case kGlobal:
2622          baseEnv(env)->DeleteGlobalRef(env, obj);
2623          break;
2624        case kLocal:
2625          baseEnv(env)->DeleteLocalRef(env, obj);
2626          break;
2627        case kWeakGlobal:
2628          baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2629          break;
2630        default:
2631          LOG(FATAL) << "Unexpected reference kind: " << kind;
2632      }
2633      result.V = nullptr;
2634      sc.Check(soa, false, "V", &result);
2635    }
2636  }
2637
2638  static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2639                                       const char* name, const char* sig, bool is_static) {
2640    ScopedObjectAccess soa(env);
2641    ScopedCheck sc(kFlag_Default, function_name);
2642    JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2643    if (sc.Check(soa, true, "Ecuu", args)) {
2644      JniValueType result;
2645      if (is_static) {
2646        result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2647      } else {
2648        result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2649      }
2650      if (sc.Check(soa, false, "m", &result)) {
2651        return result.m;
2652      }
2653    }
2654    return nullptr;
2655  }
2656
2657  static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2658                                     const char* name, const char* sig, bool is_static) {
2659    ScopedObjectAccess soa(env);
2660    ScopedCheck sc(kFlag_Default, function_name);
2661    JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2662    if (sc.Check(soa, true, "Ecuu", args)) {
2663      JniValueType result;
2664      if (is_static) {
2665        result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2666      } else {
2667        result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2668      }
2669      if (sc.Check(soa, false, "f", &result)) {
2670        return result.f;
2671      }
2672    }
2673    return nullptr;
2674  }
2675
2676  static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2677                               bool is_static, Primitive::Type type) {
2678    ScopedObjectAccess soa(env);
2679    ScopedCheck sc(kFlag_Default, function_name);
2680    JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2681    JniValueType result;
2682    if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2683        sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2684      const char* result_check = nullptr;
2685      switch (type) {
2686        case Primitive::kPrimNot:
2687          if (is_static) {
2688            result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2689          } else {
2690            result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2691          }
2692          result_check = "L";
2693          break;
2694        case Primitive::kPrimBoolean:
2695          if (is_static) {
2696            result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2697          } else {
2698            result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2699          }
2700          result_check = "Z";
2701          break;
2702        case Primitive::kPrimByte:
2703          if (is_static) {
2704            result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2705          } else {
2706            result.B = baseEnv(env)->GetByteField(env, obj, fid);
2707          }
2708          result_check = "B";
2709          break;
2710        case Primitive::kPrimChar:
2711          if (is_static) {
2712            result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2713          } else {
2714            result.C = baseEnv(env)->GetCharField(env, obj, fid);
2715          }
2716          result_check = "C";
2717          break;
2718        case Primitive::kPrimShort:
2719          if (is_static) {
2720            result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2721          } else {
2722            result.S = baseEnv(env)->GetShortField(env, obj, fid);
2723          }
2724          result_check = "S";
2725          break;
2726        case Primitive::kPrimInt:
2727          if (is_static) {
2728            result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2729          } else {
2730            result.I = baseEnv(env)->GetIntField(env, obj, fid);
2731          }
2732          result_check = "I";
2733          break;
2734        case Primitive::kPrimLong:
2735          if (is_static) {
2736            result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2737          } else {
2738            result.J = baseEnv(env)->GetLongField(env, obj, fid);
2739          }
2740          result_check = "J";
2741          break;
2742        case Primitive::kPrimFloat:
2743          if (is_static) {
2744            result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2745          } else {
2746            result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2747          }
2748          result_check = "F";
2749          break;
2750        case Primitive::kPrimDouble:
2751          if (is_static) {
2752            result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2753          } else {
2754            result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2755          }
2756          result_check = "D";
2757          break;
2758        case Primitive::kPrimVoid:
2759          LOG(FATAL) << "Unexpected type: " << type;
2760          break;
2761      }
2762      if (sc.Check(soa, false, result_check, &result)) {
2763        return result;
2764      }
2765    }
2766    result.J = 0;
2767    return result;
2768  }
2769
2770  static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2771                       bool is_static, Primitive::Type type, JniValueType value) {
2772    ScopedObjectAccess soa(env);
2773    ScopedCheck sc(kFlag_Default, function_name);
2774    JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2775    char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2776        type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2777    if (sc.Check(soa, true, sig, args) &&
2778        sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2779      switch (type) {
2780        case Primitive::kPrimNot:
2781          if (is_static) {
2782            baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2783          } else {
2784            baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2785          }
2786          break;
2787        case Primitive::kPrimBoolean:
2788          if (is_static) {
2789            baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2790          } else {
2791            baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2792          }
2793          break;
2794        case Primitive::kPrimByte:
2795          if (is_static) {
2796            baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2797          } else {
2798            baseEnv(env)->SetByteField(env, obj, fid, value.B);
2799          }
2800          break;
2801        case Primitive::kPrimChar:
2802          if (is_static) {
2803            baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2804          } else {
2805            baseEnv(env)->SetCharField(env, obj, fid, value.C);
2806          }
2807          break;
2808        case Primitive::kPrimShort:
2809          if (is_static) {
2810            baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2811          } else {
2812            baseEnv(env)->SetShortField(env, obj, fid, value.S);
2813          }
2814          break;
2815        case Primitive::kPrimInt:
2816          if (is_static) {
2817            baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2818          } else {
2819            baseEnv(env)->SetIntField(env, obj, fid, value.I);
2820          }
2821          break;
2822        case Primitive::kPrimLong:
2823          if (is_static) {
2824            baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2825          } else {
2826            baseEnv(env)->SetLongField(env, obj, fid, value.J);
2827          }
2828          break;
2829        case Primitive::kPrimFloat:
2830          if (is_static) {
2831            baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2832          } else {
2833            baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2834          }
2835          break;
2836        case Primitive::kPrimDouble:
2837          if (is_static) {
2838            baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2839          } else {
2840            baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2841          }
2842          break;
2843        case Primitive::kPrimVoid:
2844          LOG(FATAL) << "Unexpected type: " << type;
2845          break;
2846      }
2847      JniValueType result;
2848      result.V = nullptr;
2849      sc.Check(soa, false, "V", &result);
2850    }
2851  }
2852
2853  static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
2854                            jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
2855      SHARED_REQUIRES(Locks::mutator_lock_) {
2856    bool checked;
2857    switch (invoke) {
2858      case kVirtual: {
2859        DCHECK(c == nullptr);
2860        JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
2861        checked = sc.Check(soa, true, "ELm.", args);
2862        break;
2863      }
2864      case kDirect: {
2865        JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
2866        checked = sc.Check(soa, true, "ELcm.", args);
2867        break;
2868      }
2869      case kStatic: {
2870        DCHECK(obj == nullptr);
2871        JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
2872        checked = sc.Check(soa, true, "Ecm.", args);
2873        break;
2874      }
2875      default:
2876        LOG(FATAL) << "Unexpected invoke: " << invoke;
2877        checked = false;
2878        break;
2879    }
2880    return checked;
2881  }
2882
2883  static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2884                                  jmethodID mid, jvalue* vargs, Primitive::Type type,
2885                                  InvokeType invoke) {
2886    ScopedObjectAccess soa(env);
2887    ScopedCheck sc(kFlag_Default, function_name);
2888    JniValueType result;
2889    VarArgs rest(mid, vargs);
2890    if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
2891        sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2892      const char* result_check;
2893      switch (type) {
2894        case Primitive::kPrimNot:
2895          result_check = "L";
2896          switch (invoke) {
2897            case kVirtual:
2898              result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2899              break;
2900            case kDirect:
2901              result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2902              break;
2903            case kStatic:
2904              result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2905              break;
2906            default:
2907              break;
2908          }
2909          break;
2910        case Primitive::kPrimBoolean:
2911          result_check = "Z";
2912          switch (invoke) {
2913            case kVirtual:
2914              result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2915              break;
2916            case kDirect:
2917              result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2918              break;
2919            case kStatic:
2920              result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2921              break;
2922            default:
2923              break;
2924          }
2925          break;
2926        case Primitive::kPrimByte:
2927          result_check = "B";
2928          switch (invoke) {
2929            case kVirtual:
2930              result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2931              break;
2932            case kDirect:
2933              result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2934              break;
2935            case kStatic:
2936              result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2937              break;
2938            default:
2939              break;
2940          }
2941          break;
2942        case Primitive::kPrimChar:
2943          result_check = "C";
2944          switch (invoke) {
2945            case kVirtual:
2946              result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2947              break;
2948            case kDirect:
2949              result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2950              break;
2951            case kStatic:
2952              result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2953              break;
2954            default:
2955              break;
2956          }
2957          break;
2958        case Primitive::kPrimShort:
2959          result_check = "S";
2960          switch (invoke) {
2961            case kVirtual:
2962              result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2963              break;
2964            case kDirect:
2965              result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2966              break;
2967            case kStatic:
2968              result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2969              break;
2970            default:
2971              break;
2972          }
2973          break;
2974        case Primitive::kPrimInt:
2975          result_check = "I";
2976          switch (invoke) {
2977            case kVirtual:
2978              result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2979              break;
2980            case kDirect:
2981              result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2982              break;
2983            case kStatic:
2984              result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
2985              break;
2986            default:
2987              break;
2988          }
2989          break;
2990        case Primitive::kPrimLong:
2991          result_check = "J";
2992          switch (invoke) {
2993            case kVirtual:
2994              result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
2995              break;
2996            case kDirect:
2997              result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
2998              break;
2999            case kStatic:
3000              result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3001              break;
3002            default:
3003              break;
3004          }
3005          break;
3006        case Primitive::kPrimFloat:
3007          result_check = "F";
3008          switch (invoke) {
3009            case kVirtual:
3010              result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3011              break;
3012            case kDirect:
3013              result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3014              break;
3015            case kStatic:
3016              result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3017              break;
3018            default:
3019              break;
3020          }
3021          break;
3022        case Primitive::kPrimDouble:
3023          result_check = "D";
3024          switch (invoke) {
3025            case kVirtual:
3026              result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3027              break;
3028            case kDirect:
3029              result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3030              break;
3031            case kStatic:
3032              result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3033              break;
3034            default:
3035              break;
3036          }
3037          break;
3038        case Primitive::kPrimVoid:
3039          result_check = "V";
3040          result.V = nullptr;
3041          switch (invoke) {
3042            case kVirtual:
3043              baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3044              break;
3045            case kDirect:
3046              baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3047              break;
3048            case kStatic:
3049              baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3050              break;
3051            default:
3052              LOG(FATAL) << "Unexpected invoke: " << invoke;
3053          }
3054          break;
3055        default:
3056          LOG(FATAL) << "Unexpected return type: " << type;
3057          result_check = nullptr;
3058      }
3059      if (sc.Check(soa, false, result_check, &result)) {
3060        return result;
3061      }
3062    }
3063    result.J = 0;
3064    return result;
3065  }
3066
3067  static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3068                                  jmethodID mid, va_list vargs, Primitive::Type type,
3069                                  InvokeType invoke) {
3070    ScopedObjectAccess soa(env);
3071    ScopedCheck sc(kFlag_Default, function_name);
3072    JniValueType result;
3073    VarArgs rest(mid, vargs);
3074    if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
3075        sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3076      const char* result_check;
3077      switch (type) {
3078        case Primitive::kPrimNot:
3079          result_check = "L";
3080          switch (invoke) {
3081            case kVirtual:
3082              result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3083              break;
3084            case kDirect:
3085              result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3086              break;
3087            case kStatic:
3088              result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3089              break;
3090            default:
3091              LOG(FATAL) << "Unexpected invoke: " << invoke;
3092          }
3093          break;
3094        case Primitive::kPrimBoolean:
3095          result_check = "Z";
3096          switch (invoke) {
3097            case kVirtual:
3098              result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3099              break;
3100            case kDirect:
3101              result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3102              break;
3103            case kStatic:
3104              result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3105              break;
3106            default:
3107              LOG(FATAL) << "Unexpected invoke: " << invoke;
3108          }
3109          break;
3110        case Primitive::kPrimByte:
3111          result_check = "B";
3112          switch (invoke) {
3113            case kVirtual:
3114              result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3115              break;
3116            case kDirect:
3117              result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3118              break;
3119            case kStatic:
3120              result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3121              break;
3122            default:
3123              LOG(FATAL) << "Unexpected invoke: " << invoke;
3124          }
3125          break;
3126        case Primitive::kPrimChar:
3127          result_check = "C";
3128          switch (invoke) {
3129            case kVirtual:
3130              result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3131              break;
3132            case kDirect:
3133              result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3134              break;
3135            case kStatic:
3136              result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3137              break;
3138            default:
3139              LOG(FATAL) << "Unexpected invoke: " << invoke;
3140          }
3141          break;
3142        case Primitive::kPrimShort:
3143          result_check = "S";
3144          switch (invoke) {
3145            case kVirtual:
3146              result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3147              break;
3148            case kDirect:
3149              result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3150              break;
3151            case kStatic:
3152              result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3153              break;
3154            default:
3155              LOG(FATAL) << "Unexpected invoke: " << invoke;
3156          }
3157          break;
3158        case Primitive::kPrimInt:
3159          result_check = "I";
3160          switch (invoke) {
3161            case kVirtual:
3162              result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3163              break;
3164            case kDirect:
3165              result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3166              break;
3167            case kStatic:
3168              result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3169              break;
3170            default:
3171              LOG(FATAL) << "Unexpected invoke: " << invoke;
3172          }
3173          break;
3174        case Primitive::kPrimLong:
3175          result_check = "J";
3176          switch (invoke) {
3177            case kVirtual:
3178              result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3179              break;
3180            case kDirect:
3181              result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3182              break;
3183            case kStatic:
3184              result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3185              break;
3186            default:
3187              LOG(FATAL) << "Unexpected invoke: " << invoke;
3188          }
3189          break;
3190        case Primitive::kPrimFloat:
3191          result_check = "F";
3192          switch (invoke) {
3193            case kVirtual:
3194              result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3195              break;
3196            case kDirect:
3197              result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3198              break;
3199            case kStatic:
3200              result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3201              break;
3202            default:
3203              LOG(FATAL) << "Unexpected invoke: " << invoke;
3204          }
3205          break;
3206        case Primitive::kPrimDouble:
3207          result_check = "D";
3208          switch (invoke) {
3209            case kVirtual:
3210              result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3211              break;
3212            case kDirect:
3213              result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3214              break;
3215            case kStatic:
3216              result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3217              break;
3218            default:
3219              LOG(FATAL) << "Unexpected invoke: " << invoke;
3220          }
3221          break;
3222        case Primitive::kPrimVoid:
3223          result_check = "V";
3224          result.V = nullptr;
3225          switch (invoke) {
3226            case kVirtual:
3227              baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3228              break;
3229            case kDirect:
3230              baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3231              break;
3232            case kStatic:
3233              baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3234              break;
3235            default:
3236              LOG(FATAL) << "Unexpected invoke: " << invoke;
3237          }
3238          break;
3239        default:
3240          LOG(FATAL) << "Unexpected return type: " << type;
3241          result_check = nullptr;
3242      }
3243      if (sc.Check(soa, false, result_check, &result)) {
3244        return result;
3245      }
3246    }
3247    result.J = 0;
3248    return result;
3249  }
3250
3251  static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3252                                            jboolean* is_copy, bool utf, bool critical) {
3253    ScopedObjectAccess soa(env);
3254    int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3255    ScopedCheck sc(flags, function_name);
3256    JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3257    if (sc.Check(soa, true, "Esp", args)) {
3258      JniValueType result;
3259      void* ptr;
3260      if (utf) {
3261        CHECK(!critical);
3262        ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3263        result.u = reinterpret_cast<char*>(ptr);
3264      } else {
3265        ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3266            baseEnv(env)->GetStringChars(env, string, is_copy));
3267        result.p = ptr;
3268      }
3269      // TODO: could we be smarter about not copying when local_is_copy?
3270      if (ptr != nullptr && soa.ForceCopy()) {
3271        if (utf) {
3272          size_t length_in_bytes = strlen(result.u) + 1;
3273          result.u =
3274              reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
3275        } else {
3276          size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3277          result.p =
3278              reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
3279        }
3280        if (is_copy != nullptr) {
3281          *is_copy = JNI_TRUE;
3282        }
3283      }
3284      if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3285        return utf ? result.u : result.p;
3286      }
3287    }
3288    return nullptr;
3289  }
3290
3291  static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3292                                         const void* chars, bool utf, bool critical) {
3293    ScopedObjectAccess soa(env);
3294    int flags = kFlag_ExcepOkay | kFlag_Release;
3295    if (critical) {
3296      flags |= kFlag_CritRelease;
3297    }
3298    ScopedCheck sc(flags, function_name);
3299    sc.CheckNonNull(chars);
3300    bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3301    if (force_copy_ok && soa.ForceCopy()) {
3302      chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3303    }
3304    if (force_copy_ok) {
3305      JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3306      if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3307        if (utf) {
3308          CHECK(!critical);
3309          baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3310        } else {
3311          if (critical) {
3312            baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3313          } else {
3314            baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3315          }
3316        }
3317        JniValueType result;
3318        sc.Check(soa, false, "V", &result);
3319      }
3320    }
3321  }
3322
3323  static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3324                                  Primitive::Type type) {
3325    ScopedObjectAccess soa(env);
3326    ScopedCheck sc(kFlag_Default, function_name);
3327    JniValueType args[2] = {{.E = env}, {.z = length}};
3328    if (sc.Check(soa, true, "Ez", args)) {
3329      JniValueType result;
3330      switch (type) {
3331        case Primitive::kPrimBoolean:
3332          result.a = baseEnv(env)->NewBooleanArray(env, length);
3333          break;
3334        case Primitive::kPrimByte:
3335          result.a = baseEnv(env)->NewByteArray(env, length);
3336          break;
3337        case Primitive::kPrimChar:
3338          result.a = baseEnv(env)->NewCharArray(env, length);
3339          break;
3340        case Primitive::kPrimShort:
3341          result.a = baseEnv(env)->NewShortArray(env, length);
3342          break;
3343        case Primitive::kPrimInt:
3344          result.a = baseEnv(env)->NewIntArray(env, length);
3345          break;
3346        case Primitive::kPrimLong:
3347          result.a = baseEnv(env)->NewLongArray(env, length);
3348          break;
3349        case Primitive::kPrimFloat:
3350          result.a = baseEnv(env)->NewFloatArray(env, length);
3351          break;
3352        case Primitive::kPrimDouble:
3353          result.a = baseEnv(env)->NewDoubleArray(env, length);
3354          break;
3355        default:
3356          LOG(FATAL) << "Unexpected primitive type: " << type;
3357      }
3358      if (sc.Check(soa, false, "a", &result)) {
3359        return result.a;
3360      }
3361    }
3362    return nullptr;
3363  }
3364
3365  static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3366                                         JNIEnv* env, jarray array, jboolean* is_copy) {
3367    ScopedObjectAccess soa(env);
3368    ScopedCheck sc(kFlag_Default, function_name);
3369    JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3370    if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3371      JniValueType result;
3372      void* ptr = nullptr;
3373      switch (type) {
3374        case Primitive::kPrimBoolean:
3375          ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3376                                                      is_copy);
3377          break;
3378        case Primitive::kPrimByte:
3379          ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
3380          break;
3381        case Primitive::kPrimChar:
3382          ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
3383          break;
3384        case Primitive::kPrimShort:
3385          ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
3386          break;
3387        case Primitive::kPrimInt:
3388          ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
3389          break;
3390        case Primitive::kPrimLong:
3391          ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
3392          break;
3393        case Primitive::kPrimFloat:
3394          ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
3395          break;
3396        case Primitive::kPrimDouble:
3397          ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
3398          break;
3399        default:
3400          LOG(FATAL) << "Unexpected primitive type: " << type;
3401      }
3402      if (ptr != nullptr && soa.ForceCopy()) {
3403        ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
3404        if (is_copy != nullptr) {
3405          *is_copy = JNI_TRUE;
3406        }
3407      }
3408      result.p = ptr;
3409      if (sc.Check(soa, false, "p", &result)) {
3410        return const_cast<void*>(result.p);
3411      }
3412    }
3413    return nullptr;
3414  }
3415
3416  static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3417                                            JNIEnv* env, jarray array, void* elems, jint mode) {
3418    ScopedObjectAccess soa(env);
3419    ScopedCheck sc(kFlag_ExcepOkay, function_name);
3420    if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3421      if (soa.ForceCopy()) {
3422        elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3423      }
3424      if (!soa.ForceCopy() || elems != nullptr) {
3425        JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3426        if (sc.Check(soa, true, "Eapr", args)) {
3427          switch (type) {
3428            case Primitive::kPrimBoolean:
3429              baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3430                                                        reinterpret_cast<jboolean*>(elems), mode);
3431              break;
3432            case Primitive::kPrimByte:
3433              baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3434                                                     reinterpret_cast<jbyte*>(elems), mode);
3435              break;
3436            case Primitive::kPrimChar:
3437              baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3438                                                     reinterpret_cast<jchar*>(elems), mode);
3439              break;
3440            case Primitive::kPrimShort:
3441              baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3442                                                      reinterpret_cast<jshort*>(elems), mode);
3443              break;
3444            case Primitive::kPrimInt:
3445              baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3446                                                    reinterpret_cast<jint*>(elems), mode);
3447              break;
3448            case Primitive::kPrimLong:
3449              baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3450                                                     reinterpret_cast<jlong*>(elems), mode);
3451              break;
3452            case Primitive::kPrimFloat:
3453              baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3454                                                      reinterpret_cast<jfloat*>(elems), mode);
3455              break;
3456            case Primitive::kPrimDouble:
3457              baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3458                                                       reinterpret_cast<jdouble*>(elems), mode);
3459              break;
3460            default:
3461              LOG(FATAL) << "Unexpected primitive type: " << type;
3462          }
3463          JniValueType result;
3464          result.V = nullptr;
3465          sc.Check(soa, false, "V", &result);
3466        }
3467      }
3468    }
3469  }
3470
3471  static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3472                                      jarray array, jsize start, jsize len, void* buf) {
3473    ScopedObjectAccess soa(env);
3474    ScopedCheck sc(kFlag_Default, function_name);
3475    JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3476    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3477    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3478    if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3479      switch (type) {
3480        case Primitive::kPrimBoolean:
3481          baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3482                                              reinterpret_cast<jboolean*>(buf));
3483          break;
3484        case Primitive::kPrimByte:
3485          baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3486                                           reinterpret_cast<jbyte*>(buf));
3487          break;
3488        case Primitive::kPrimChar:
3489          baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3490                                           reinterpret_cast<jchar*>(buf));
3491          break;
3492        case Primitive::kPrimShort:
3493          baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3494                                            reinterpret_cast<jshort*>(buf));
3495          break;
3496        case Primitive::kPrimInt:
3497          baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3498                                          reinterpret_cast<jint*>(buf));
3499          break;
3500        case Primitive::kPrimLong:
3501          baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3502                                           reinterpret_cast<jlong*>(buf));
3503          break;
3504        case Primitive::kPrimFloat:
3505          baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3506                                            reinterpret_cast<jfloat*>(buf));
3507          break;
3508        case Primitive::kPrimDouble:
3509          baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3510                                             reinterpret_cast<jdouble*>(buf));
3511          break;
3512        default:
3513          LOG(FATAL) << "Unexpected primitive type: " << type;
3514      }
3515      JniValueType result;
3516      result.V = nullptr;
3517      sc.Check(soa, false, "V", &result);
3518    }
3519  }
3520
3521  static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3522                                      jarray array, jsize start, jsize len, const void* buf) {
3523    ScopedObjectAccess soa(env);
3524    ScopedCheck sc(kFlag_Default, function_name);
3525    JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3526    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3527    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3528    if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3529      switch (type) {
3530        case Primitive::kPrimBoolean:
3531          baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3532                                              reinterpret_cast<const jboolean*>(buf));
3533          break;
3534        case Primitive::kPrimByte:
3535          baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3536                                           reinterpret_cast<const jbyte*>(buf));
3537          break;
3538        case Primitive::kPrimChar:
3539          baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3540                                           reinterpret_cast<const jchar*>(buf));
3541          break;
3542        case Primitive::kPrimShort:
3543          baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3544                                              reinterpret_cast<const jshort*>(buf));
3545          break;
3546        case Primitive::kPrimInt:
3547          baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3548                                          reinterpret_cast<const jint*>(buf));
3549          break;
3550        case Primitive::kPrimLong:
3551          baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3552                                              reinterpret_cast<const jlong*>(buf));
3553          break;
3554        case Primitive::kPrimFloat:
3555          baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3556                                            reinterpret_cast<const jfloat*>(buf));
3557          break;
3558        case Primitive::kPrimDouble:
3559          baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3560                                             reinterpret_cast<const jdouble*>(buf));
3561          break;
3562        default:
3563          LOG(FATAL) << "Unexpected primitive type: " << type;
3564      }
3565      JniValueType result;
3566      result.V = nullptr;
3567      sc.Check(soa, false, "V", &result);
3568    }
3569  }
3570};
3571
3572const JNINativeInterface gCheckNativeInterface = {
3573  nullptr,  // reserved0.
3574  nullptr,  // reserved1.
3575  nullptr,  // reserved2.
3576  nullptr,  // reserved3.
3577  CheckJNI::GetVersion,
3578  CheckJNI::DefineClass,
3579  CheckJNI::FindClass,
3580  CheckJNI::FromReflectedMethod,
3581  CheckJNI::FromReflectedField,
3582  CheckJNI::ToReflectedMethod,
3583  CheckJNI::GetSuperclass,
3584  CheckJNI::IsAssignableFrom,
3585  CheckJNI::ToReflectedField,
3586  CheckJNI::Throw,
3587  CheckJNI::ThrowNew,
3588  CheckJNI::ExceptionOccurred,
3589  CheckJNI::ExceptionDescribe,
3590  CheckJNI::ExceptionClear,
3591  CheckJNI::FatalError,
3592  CheckJNI::PushLocalFrame,
3593  CheckJNI::PopLocalFrame,
3594  CheckJNI::NewGlobalRef,
3595  CheckJNI::DeleteGlobalRef,
3596  CheckJNI::DeleteLocalRef,
3597  CheckJNI::IsSameObject,
3598  CheckJNI::NewLocalRef,
3599  CheckJNI::EnsureLocalCapacity,
3600  CheckJNI::AllocObject,
3601  CheckJNI::NewObject,
3602  CheckJNI::NewObjectV,
3603  CheckJNI::NewObjectA,
3604  CheckJNI::GetObjectClass,
3605  CheckJNI::IsInstanceOf,
3606  CheckJNI::GetMethodID,
3607  CheckJNI::CallObjectMethod,
3608  CheckJNI::CallObjectMethodV,
3609  CheckJNI::CallObjectMethodA,
3610  CheckJNI::CallBooleanMethod,
3611  CheckJNI::CallBooleanMethodV,
3612  CheckJNI::CallBooleanMethodA,
3613  CheckJNI::CallByteMethod,
3614  CheckJNI::CallByteMethodV,
3615  CheckJNI::CallByteMethodA,
3616  CheckJNI::CallCharMethod,
3617  CheckJNI::CallCharMethodV,
3618  CheckJNI::CallCharMethodA,
3619  CheckJNI::CallShortMethod,
3620  CheckJNI::CallShortMethodV,
3621  CheckJNI::CallShortMethodA,
3622  CheckJNI::CallIntMethod,
3623  CheckJNI::CallIntMethodV,
3624  CheckJNI::CallIntMethodA,
3625  CheckJNI::CallLongMethod,
3626  CheckJNI::CallLongMethodV,
3627  CheckJNI::CallLongMethodA,
3628  CheckJNI::CallFloatMethod,
3629  CheckJNI::CallFloatMethodV,
3630  CheckJNI::CallFloatMethodA,
3631  CheckJNI::CallDoubleMethod,
3632  CheckJNI::CallDoubleMethodV,
3633  CheckJNI::CallDoubleMethodA,
3634  CheckJNI::CallVoidMethod,
3635  CheckJNI::CallVoidMethodV,
3636  CheckJNI::CallVoidMethodA,
3637  CheckJNI::CallNonvirtualObjectMethod,
3638  CheckJNI::CallNonvirtualObjectMethodV,
3639  CheckJNI::CallNonvirtualObjectMethodA,
3640  CheckJNI::CallNonvirtualBooleanMethod,
3641  CheckJNI::CallNonvirtualBooleanMethodV,
3642  CheckJNI::CallNonvirtualBooleanMethodA,
3643  CheckJNI::CallNonvirtualByteMethod,
3644  CheckJNI::CallNonvirtualByteMethodV,
3645  CheckJNI::CallNonvirtualByteMethodA,
3646  CheckJNI::CallNonvirtualCharMethod,
3647  CheckJNI::CallNonvirtualCharMethodV,
3648  CheckJNI::CallNonvirtualCharMethodA,
3649  CheckJNI::CallNonvirtualShortMethod,
3650  CheckJNI::CallNonvirtualShortMethodV,
3651  CheckJNI::CallNonvirtualShortMethodA,
3652  CheckJNI::CallNonvirtualIntMethod,
3653  CheckJNI::CallNonvirtualIntMethodV,
3654  CheckJNI::CallNonvirtualIntMethodA,
3655  CheckJNI::CallNonvirtualLongMethod,
3656  CheckJNI::CallNonvirtualLongMethodV,
3657  CheckJNI::CallNonvirtualLongMethodA,
3658  CheckJNI::CallNonvirtualFloatMethod,
3659  CheckJNI::CallNonvirtualFloatMethodV,
3660  CheckJNI::CallNonvirtualFloatMethodA,
3661  CheckJNI::CallNonvirtualDoubleMethod,
3662  CheckJNI::CallNonvirtualDoubleMethodV,
3663  CheckJNI::CallNonvirtualDoubleMethodA,
3664  CheckJNI::CallNonvirtualVoidMethod,
3665  CheckJNI::CallNonvirtualVoidMethodV,
3666  CheckJNI::CallNonvirtualVoidMethodA,
3667  CheckJNI::GetFieldID,
3668  CheckJNI::GetObjectField,
3669  CheckJNI::GetBooleanField,
3670  CheckJNI::GetByteField,
3671  CheckJNI::GetCharField,
3672  CheckJNI::GetShortField,
3673  CheckJNI::GetIntField,
3674  CheckJNI::GetLongField,
3675  CheckJNI::GetFloatField,
3676  CheckJNI::GetDoubleField,
3677  CheckJNI::SetObjectField,
3678  CheckJNI::SetBooleanField,
3679  CheckJNI::SetByteField,
3680  CheckJNI::SetCharField,
3681  CheckJNI::SetShortField,
3682  CheckJNI::SetIntField,
3683  CheckJNI::SetLongField,
3684  CheckJNI::SetFloatField,
3685  CheckJNI::SetDoubleField,
3686  CheckJNI::GetStaticMethodID,
3687  CheckJNI::CallStaticObjectMethod,
3688  CheckJNI::CallStaticObjectMethodV,
3689  CheckJNI::CallStaticObjectMethodA,
3690  CheckJNI::CallStaticBooleanMethod,
3691  CheckJNI::CallStaticBooleanMethodV,
3692  CheckJNI::CallStaticBooleanMethodA,
3693  CheckJNI::CallStaticByteMethod,
3694  CheckJNI::CallStaticByteMethodV,
3695  CheckJNI::CallStaticByteMethodA,
3696  CheckJNI::CallStaticCharMethod,
3697  CheckJNI::CallStaticCharMethodV,
3698  CheckJNI::CallStaticCharMethodA,
3699  CheckJNI::CallStaticShortMethod,
3700  CheckJNI::CallStaticShortMethodV,
3701  CheckJNI::CallStaticShortMethodA,
3702  CheckJNI::CallStaticIntMethod,
3703  CheckJNI::CallStaticIntMethodV,
3704  CheckJNI::CallStaticIntMethodA,
3705  CheckJNI::CallStaticLongMethod,
3706  CheckJNI::CallStaticLongMethodV,
3707  CheckJNI::CallStaticLongMethodA,
3708  CheckJNI::CallStaticFloatMethod,
3709  CheckJNI::CallStaticFloatMethodV,
3710  CheckJNI::CallStaticFloatMethodA,
3711  CheckJNI::CallStaticDoubleMethod,
3712  CheckJNI::CallStaticDoubleMethodV,
3713  CheckJNI::CallStaticDoubleMethodA,
3714  CheckJNI::CallStaticVoidMethod,
3715  CheckJNI::CallStaticVoidMethodV,
3716  CheckJNI::CallStaticVoidMethodA,
3717  CheckJNI::GetStaticFieldID,
3718  CheckJNI::GetStaticObjectField,
3719  CheckJNI::GetStaticBooleanField,
3720  CheckJNI::GetStaticByteField,
3721  CheckJNI::GetStaticCharField,
3722  CheckJNI::GetStaticShortField,
3723  CheckJNI::GetStaticIntField,
3724  CheckJNI::GetStaticLongField,
3725  CheckJNI::GetStaticFloatField,
3726  CheckJNI::GetStaticDoubleField,
3727  CheckJNI::SetStaticObjectField,
3728  CheckJNI::SetStaticBooleanField,
3729  CheckJNI::SetStaticByteField,
3730  CheckJNI::SetStaticCharField,
3731  CheckJNI::SetStaticShortField,
3732  CheckJNI::SetStaticIntField,
3733  CheckJNI::SetStaticLongField,
3734  CheckJNI::SetStaticFloatField,
3735  CheckJNI::SetStaticDoubleField,
3736  CheckJNI::NewString,
3737  CheckJNI::GetStringLength,
3738  CheckJNI::GetStringChars,
3739  CheckJNI::ReleaseStringChars,
3740  CheckJNI::NewStringUTF,
3741  CheckJNI::GetStringUTFLength,
3742  CheckJNI::GetStringUTFChars,
3743  CheckJNI::ReleaseStringUTFChars,
3744  CheckJNI::GetArrayLength,
3745  CheckJNI::NewObjectArray,
3746  CheckJNI::GetObjectArrayElement,
3747  CheckJNI::SetObjectArrayElement,
3748  CheckJNI::NewBooleanArray,
3749  CheckJNI::NewByteArray,
3750  CheckJNI::NewCharArray,
3751  CheckJNI::NewShortArray,
3752  CheckJNI::NewIntArray,
3753  CheckJNI::NewLongArray,
3754  CheckJNI::NewFloatArray,
3755  CheckJNI::NewDoubleArray,
3756  CheckJNI::GetBooleanArrayElements,
3757  CheckJNI::GetByteArrayElements,
3758  CheckJNI::GetCharArrayElements,
3759  CheckJNI::GetShortArrayElements,
3760  CheckJNI::GetIntArrayElements,
3761  CheckJNI::GetLongArrayElements,
3762  CheckJNI::GetFloatArrayElements,
3763  CheckJNI::GetDoubleArrayElements,
3764  CheckJNI::ReleaseBooleanArrayElements,
3765  CheckJNI::ReleaseByteArrayElements,
3766  CheckJNI::ReleaseCharArrayElements,
3767  CheckJNI::ReleaseShortArrayElements,
3768  CheckJNI::ReleaseIntArrayElements,
3769  CheckJNI::ReleaseLongArrayElements,
3770  CheckJNI::ReleaseFloatArrayElements,
3771  CheckJNI::ReleaseDoubleArrayElements,
3772  CheckJNI::GetBooleanArrayRegion,
3773  CheckJNI::GetByteArrayRegion,
3774  CheckJNI::GetCharArrayRegion,
3775  CheckJNI::GetShortArrayRegion,
3776  CheckJNI::GetIntArrayRegion,
3777  CheckJNI::GetLongArrayRegion,
3778  CheckJNI::GetFloatArrayRegion,
3779  CheckJNI::GetDoubleArrayRegion,
3780  CheckJNI::SetBooleanArrayRegion,
3781  CheckJNI::SetByteArrayRegion,
3782  CheckJNI::SetCharArrayRegion,
3783  CheckJNI::SetShortArrayRegion,
3784  CheckJNI::SetIntArrayRegion,
3785  CheckJNI::SetLongArrayRegion,
3786  CheckJNI::SetFloatArrayRegion,
3787  CheckJNI::SetDoubleArrayRegion,
3788  CheckJNI::RegisterNatives,
3789  CheckJNI::UnregisterNatives,
3790  CheckJNI::MonitorEnter,
3791  CheckJNI::MonitorExit,
3792  CheckJNI::GetJavaVM,
3793  CheckJNI::GetStringRegion,
3794  CheckJNI::GetStringUTFRegion,
3795  CheckJNI::GetPrimitiveArrayCritical,
3796  CheckJNI::ReleasePrimitiveArrayCritical,
3797  CheckJNI::GetStringCritical,
3798  CheckJNI::ReleaseStringCritical,
3799  CheckJNI::NewWeakGlobalRef,
3800  CheckJNI::DeleteWeakGlobalRef,
3801  CheckJNI::ExceptionCheck,
3802  CheckJNI::NewDirectByteBuffer,
3803  CheckJNI::GetDirectBufferAddress,
3804  CheckJNI::GetDirectBufferCapacity,
3805  CheckJNI::GetObjectRefType,
3806};
3807
3808const JNINativeInterface* GetCheckJniNativeInterface() {
3809  return &gCheckNativeInterface;
3810}
3811
3812class CheckJII {
3813 public:
3814  static jint DestroyJavaVM(JavaVM* vm) {
3815    ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3816    JniValueType args[1] = {{.v = vm}};
3817    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3818    JniValueType result;
3819    result.i = BaseVm(vm)->DestroyJavaVM(vm);
3820    // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3821    // which will delete the JavaVMExt.
3822    sc.CheckNonHeap(nullptr, false, "i", &result);
3823    return result.i;
3824  }
3825
3826  static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
3827    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3828    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3829    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3830    JniValueType result;
3831    result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3832    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3833    return result.i;
3834  }
3835
3836  static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
3837    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3838    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3839    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3840    JniValueType result;
3841    result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3842    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3843    return result.i;
3844  }
3845
3846  static jint DetachCurrentThread(JavaVM* vm) {
3847    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3848    JniValueType args[1] = {{.v = vm}};
3849    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3850    JniValueType result;
3851    result.i = BaseVm(vm)->DetachCurrentThread(vm);
3852    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3853    return result.i;
3854  }
3855
3856  static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3857    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3858    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3859    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3860    JniValueType result;
3861    result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3862    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3863    return result.i;
3864  }
3865
3866 private:
3867  static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3868    return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
3869  }
3870};
3871
3872const JNIInvokeInterface gCheckInvokeInterface = {
3873  nullptr,  // reserved0
3874  nullptr,  // reserved1
3875  nullptr,  // reserved2
3876  CheckJII::DestroyJavaVM,
3877  CheckJII::AttachCurrentThread,
3878  CheckJII::DetachCurrentThread,
3879  CheckJII::GetEnv,
3880  CheckJII::AttachCurrentThreadAsDaemon
3881};
3882
3883const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3884  return &gCheckInvokeInterface;
3885}
3886
3887}  // namespace art
3888