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