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