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