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