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