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