blob: c6940d3b5b1034c9d7722ba0c28991c9dd7bd178 [file] [log] [blame]
Elliott Hughesa2501992011-08-26 19:39:54 -07001/*
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
Andreas Gampe277ccbd2014-11-03 21:36:10 -080017#include "check_jni.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070018
19#include <sys/mman.h>
20#include <zlib.h>
21
Mathieu Chartierc7853442015-03-27 14:35:38 -070022#include "art_field-inl.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080023#include "base/logging.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070024#include "base/to_str.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070025#include "class_linker.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080026#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070027#include "dex_file-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070028#include "gc/space/space.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070029#include "java_vm_ext.h"
Andreas Gampe277ccbd2014-11-03 21:36:10 -080030#include "jni_internal.h"
Brian Carlstromea46f952013-07-30 01:26:50 -070031#include "mirror/art_method-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080032#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080033#include "mirror/object-inl.h"
34#include "mirror/object_array-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070035#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080036#include "mirror/throwable.h"
Jeff Hao58df3272013-04-22 15:28:53 -070037#include "runtime.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070038#include "scoped_thread_state_change.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070039#include "thread.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070040#include "well_known_classes.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070041
42namespace art {
43
Elliott Hughesa2501992011-08-26 19:39:54 -070044/*
45 * ===========================================================================
46 * JNI function helpers
47 * ===========================================================================
48 */
49
Elliott Hughes3f6635a2012-06-19 13:37:49 -070050// Flags passed into ScopedCheck.
Elliott Hughesa2501992011-08-26 19:39:54 -070051#define kFlag_Default 0x0000
52
Elliott Hughes3f6635a2012-06-19 13:37:49 -070053#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.
Elliott Hughesa2501992011-08-26 19:39:54 -070058
Elliott Hughes3f6635a2012-06-19 13:37:49 -070059#define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed.
60#define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed.
Elliott Hughesa2501992011-08-26 19:39:54 -070061
Elliott Hughes3f6635a2012-06-19 13:37:49 -070062#define kFlag_Release 0x0010 // Are we in a non-critical release function?
63#define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable?
Elliott Hughesa2501992011-08-26 19:39:54 -070064
Elliott Hughes3f6635a2012-06-19 13:37:49 -070065#define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*).
Elliott Hughesa2501992011-08-26 19:39:54 -070066
Elliott Hughes485cac42011-12-09 17:49:35 -080067#define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call.
Ian Rogers68d8b422014-07-17 11:09:10 -070068/*
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 */
102union 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;
Elliott Hughesa0957642011-09-02 14:27:33 -0700128};
129
Elliott Hughesa2501992011-08-26 19:39:54 -0700130class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800131 public:
Ian Rogers68d8b422014-07-17 11:09:10 -0700132 explicit ScopedCheck(int flags, const char* functionName, bool has_method = true)
133 : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700134 }
135
Ian Rogers68d8b422014-07-17 11:09:10 -0700136 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700137
Elliott Hughes81ff3182012-03-23 20:35:56 -0700138 // 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.
Ian Rogers68d8b422014-07-17 11:09:10 -0700142 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700143 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700144 AbortF("illegal class name '%s'\n"
145 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
146 class_name);
147 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700148 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700149 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700150 }
151
152 /*
153 * Verify that this instance field ID is valid for this object.
154 *
155 * Assumes "jobj" has already been validated.
156 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700157 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700158 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700159 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)) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700165 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700166 AbortF("field operation on invalid %s: %p",
167 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
168 java_object);
169 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700170 }
171
Mathieu Chartierc7853442015-03-27 14:35:38 -0700172 ArtField* f = CheckFieldID(soa, fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800173 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700174 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700175 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800176 mirror::Class* c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700177 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700178 AbortF("jfieldID %s not valid for an object of class %s",
179 PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
180 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700181 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700182 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700183 }
184
185 /*
186 * Verify that the pointer value is non-NULL.
187 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700188 bool CheckNonNull(const void* ptr) {
189 if (UNLIKELY(ptr == nullptr)) {
190 AbortF("non-nullable argument was NULL");
191 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700192 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700193 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700194 }
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 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700200 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
201 jmethodID mid, Primitive::Type type, InvokeType invoke)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700202 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700203 mirror::ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800204 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700205 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700206 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700207 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;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700210 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700211 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_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700216 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700217 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;
Elliott Hughesa2501992011-08-26 19:39:54 -0700228 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700229 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700230 if (invoke != kStatic) {
231 mirror::Object* o = soa.Decode<mirror::Object*>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700232 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())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700236 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;
Elliott Hughesa2501992011-08-26 19:39:54 -0700241 }
242
243 /*
244 * Verify that this static field ID is valid for this class.
245 *
246 * Assumes "java_class" has already been validated.
247 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700248 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700249 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700250 mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
Mathieu Chartierc7853442015-03-27 14:35:38 -0700251 ArtField* f = CheckFieldID(soa, fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800252 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700253 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700254 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700255 if (f->GetDeclaringClass() != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700256 AbortF("static jfieldID %p not valid for class %s", fid, PrettyClass(c).c_str());
257 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700258 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700259 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700260 }
261
262 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700263 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700264 *
265 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700266 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700267 * allow bad code in the system though.
268 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700269 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700270 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700271 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700272 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700273 mirror::ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800274 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700275 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700276 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700277 mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700278 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700279 AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str());
280 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700281 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700282 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700283 }
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 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700292 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700293 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700294 mirror::ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800295 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700296 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700297 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700298 mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700299 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())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700303 AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
304 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700305 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700306 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700307 }
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)
Elliott Hughes78090d12011-10-07 14:31:47 -0700337 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700338 * 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 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700345 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
346 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800347 mirror::ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700348 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700349 // 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.
Elliott Hughesa0957642011-09-02 14:27:33 -0700351 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800352 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
353 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700354 }
355 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700356
Ian Rogersef7d42f2014-01-06 12:55:46 -0800357 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700358 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700359 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700360 for (size_t i = 0; fmt[i] != '\0'; ++i) {
361 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
362 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700363 StringAppendF(&msg, ", ");
364 }
365 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700366
Elliott Hughes485cac42011-12-09 17:49:35 -0800367 if ((flags_ & kFlag_ForceTrace) != 0) {
368 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
369 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700370 if (has_method_) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700371 std::string methodName(PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700372 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
373 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700374 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700375 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
376 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700377 }
378 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700379 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700380 }
381 }
382
383 // We always do the thorough checks on entry, and never on exit...
384 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700385 for (size_t i = 0; fmt[i] != '\0'; ++i) {
386 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
387 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700388 }
389 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700390 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700391 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700392 }
393
Ian Rogers68d8b422014-07-17 11:09:10 -0700394 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
395 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800396 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700397 // 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 mirror::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 mirror::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
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
463 bool CheckConstructor(ScopedObjectAccess& soa, jmethodID mid)
464 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
465 mirror::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", PrettyTypeOf(method).c_str(), mid);
472 return false;
473 }
474 return true;
475 }
476
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
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
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
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700515 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700516 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
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
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
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 }
Mathieu Chartierc7853442015-03-27 14:35:38 -0700568 ArtField* field = soa.DecodeField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700569 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:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800606 enum InstanceKind {
607 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700608 kDirectByteBuffer,
609 kObject,
610 kString,
611 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800612 };
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 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700621 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700622 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800623 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800624 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:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700641 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800642 }
643
Ian Rogersef7d42f2014-01-06 12:55:46 -0800644 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700645 if (null_ok) {
646 return true;
647 } else {
648 AbortF("%s received NULL %s", function_name_, what);
649 return false;
650 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800651 }
652
Ian Rogers68d8b422014-07-17 11:09:10 -0700653 mirror::Object* obj = soa.Decode<mirror::Object*>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700654 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
Mathieu Chartier590fee92013-09-13 13:46:47 -0700672 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700673 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700674 AbortF("%s is an invalid %s: %p (%p)",
675 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
676 java_object, obj);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800677 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) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700698 AbortF("%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800699 return false;
700 }
701
702 return true;
703 }
704
Ian Rogers68d8b422014-07-17 11:09:10 -0700705 /*
706 * Verify that the "mode" argument passed to a primitive array Release
707 * function is one of the valid values.
708 */
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;
Elliott Hughesa2501992011-08-26 19:39:54 -0700715 }
716
Ian Rogers68d8b422014-07-17 11:09:10 -0700717 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
743 bool CheckNonHeapValue(char fmt, JniValueType arg) {
744 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700745 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
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";
Ian Rogersc0542af2014-09-03 16:16:56 -0700805 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700806 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;
Mathieu Chartierc7853442015-03-27 14:35:38 -0700819 ArtField* f = soa.DecodeField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700820 *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 mirror::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
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;
Ian Rogers68d8b422014-07-17 11:09:10 -0700939 default:
940 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
941 }
942 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700943 /*
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 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700948 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;
Elliott Hughesa2501992011-08-26 19:39:54 -0700953 }
954
Ian Rogers68d8b422014-07-17 11:09:10 -0700955 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
956 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700957 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700958 AbortF("jarray is an invalid %s: %p (%p)",
959 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
960 java_array, a);
961 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700962 } else if (!a->IsArrayInstance()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700963 AbortF("jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
964 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700965 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700966 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700967 }
968
Ian Rogers68d8b422014-07-17 11:09:10 -0700969 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
977 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700978 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700979 AbortF("negative jsize: %d", length);
980 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700981 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700982 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700983 }
984
Mathieu Chartierc7853442015-03-27 14:35:38 -0700985 ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
Ian Rogers68d8b422014-07-17 11:09:10 -0700986 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800987 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700988 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -0800989 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700990 }
Mathieu Chartierc7853442015-03-27 14:35:38 -0700991 ArtField* f = soa.DecodeField(fid);
992 // TODO: Better check here.
993 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass())) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700994 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700995 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800996 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700997 }
998 return f;
999 }
1000
Ian Rogers68d8b422014-07-17 11:09:10 -07001001 mirror::ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
1002 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001003 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001004 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001005 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001006 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001007 mirror::ArtMethod* m = soa.DecodeMethod(mid);
Mathieu Chartier590fee92013-09-13 13:46:47 -07001008 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m) || !m->IsArtMethod()) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -07001009 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001010 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001011 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001012 }
1013 return m;
1014 }
1015
Ian Rogers68d8b422014-07-17 11:09:10 -07001016 bool CheckThread(JNIEnv* env) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001017 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001018 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001019 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1020 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001021 }
1022
1023 // Get the *correct* JNIEnv by going through our TLS pointer.
1024 JNIEnvExt* threadEnv = self->GetJniEnv();
1025
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001026 // Verify that the current thread is (a) attached and (b) associated with
1027 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001028 if (env != threadEnv) {
1029 AbortF("thread %s using JNIEnv* from thread %s",
1030 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*self).c_str());
1031 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001032 }
1033
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001034 // Verify that, if this thread previously made a critical "get" call, we
1035 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001036 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001037 case kFlag_CritOkay: // okay to call this method
1038 break;
1039 case kFlag_CritBad: // not okay to call
1040 if (threadEnv->critical) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001041 AbortF("thread %s using JNI after critical get",
1042 ToStr<Thread>(*self).c_str());
1043 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001044 }
1045 break;
1046 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001047 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -07001048 threadEnv->critical++;
1049 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001050 case kFlag_CritRelease: // this is a "release" call
Elliott Hughesa2501992011-08-26 19:39:54 -07001051 threadEnv->critical--;
1052 if (threadEnv->critical < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001053 AbortF("thread %s called too many critical releases",
1054 ToStr<Thread>(*self).c_str());
1055 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001056 }
1057 break;
1058 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001059 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001060 }
1061
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001062 // Verify that, if an exception has been raised, the native code doesn't
1063 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001064 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001065 mirror::Throwable* exception = self->GetException();
1066 AbortF("JNI %s called with pending exception %s",
1067 function_name_,
1068 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001069 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001070 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001071 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001072 }
1073
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001074 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001075 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001076 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001077 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001078 AbortF("non-nullable const char* was NULL");
1079 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001080 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001081 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001082 }
1083
Ian Rogersef7d42f2014-01-06 12:55:46 -08001084 const char* errorKind = nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001085 uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001086 if (errorKind != nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001087 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
1088 " string: '%s'", errorKind, utf8, bytes);
1089 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001090 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001091 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001092 }
1093
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001094 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1095 // sequences in place of encoded surrogate pairs.
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001096 static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001097 while (*bytes != '\0') {
1098 uint8_t utf8 = *(bytes++);
1099 // Switch on the high four bits.
1100 switch (utf8 >> 4) {
1101 case 0x00:
1102 case 0x01:
1103 case 0x02:
1104 case 0x03:
1105 case 0x04:
1106 case 0x05:
1107 case 0x06:
1108 case 0x07:
1109 // Bit pattern 0xxx. No need for any extra bytes.
1110 break;
1111 case 0x08:
1112 case 0x09:
1113 case 0x0a:
1114 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001115 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001116 *errorKind = "start";
1117 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001118 case 0x0f:
1119 // Bit pattern 1111, which might be the start of a 4 byte sequence.
1120 if ((utf8 & 0x08) == 0) {
1121 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1122 // We consume one continuation byte here, and fall through to consume two more.
1123 utf8 = *(bytes++);
1124 if ((utf8 & 0xc0) != 0x80) {
1125 *errorKind = "continuation";
1126 return utf8;
1127 }
1128 } else {
1129 *errorKind = "start";
1130 return utf8;
1131 }
1132
1133 // Fall through to the cases below to consume two more continuation bytes.
1134 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001135 case 0x0e:
1136 // Bit pattern 1110, so there are two additional bytes.
1137 utf8 = *(bytes++);
1138 if ((utf8 & 0xc0) != 0x80) {
1139 *errorKind = "continuation";
1140 return utf8;
1141 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001142
1143 // Fall through to consume one more continuation byte.
1144 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001145 case 0x0c:
1146 case 0x0d:
1147 // Bit pattern 110x, so there is one additional byte.
1148 utf8 = *(bytes++);
1149 if ((utf8 & 0xc0) != 0x80) {
1150 *errorKind = "continuation";
1151 return utf8;
1152 }
1153 break;
1154 }
1155 }
1156 return 0;
1157 }
1158
Ian Rogers68d8b422014-07-17 11:09:10 -07001159 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1160 va_list args;
1161 va_start(args, fmt);
1162 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1163 va_end(args);
1164 }
1165
1166 // The name of the JNI function being checked.
1167 const char* const function_name_;
1168
1169 const int flags_;
Elliott Hughes92cb4982011-12-16 16:57:28 -08001170 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001171
Ian Rogers68d8b422014-07-17 11:09:10 -07001172 const bool has_method_;
1173
Elliott Hughesa2501992011-08-26 19:39:54 -07001174 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1175};
1176
Elliott Hughesa2501992011-08-26 19:39:54 -07001177/*
1178 * ===========================================================================
1179 * Guarded arrays
1180 * ===========================================================================
1181 */
1182
Elliott Hughesa2501992011-08-26 19:39:54 -07001183/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001184class GuardedCopy {
1185 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001186 /*
1187 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1188 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001189 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001190 static void* Create(const void* original_buf, size_t len, bool mod_okay) {
1191 const size_t new_len = LengthIncludingRedZones(len);
1192 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001193
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001194 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001195 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001196 if (!mod_okay) {
1197 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001198 }
1199
Ian Rogers68d8b422014-07-17 11:09:10 -07001200 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001201
Ian Rogers68d8b422014-07-17 11:09:10 -07001202 // Fill begin region with canary pattern.
1203 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1204 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1205 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1206 if (kCanary[j] == '\0') {
1207 j = 0;
1208 }
1209 }
1210
1211 // Copy the data in; note "len" could be zero.
1212 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1213
1214 // Fill end region with canary pattern.
1215 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1216 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1217 if (kCanary[j] == '\0') {
1218 j = 0;
1219 }
1220 }
1221
1222 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001223 }
1224
1225 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001226 * Create a guarded copy of a primitive array. Modifications to the copied
1227 * data are allowed. Returns a pointer to the copied data.
1228 */
1229 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy) {
1230 ScopedObjectAccess soa(env);
1231
1232 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1233 size_t component_size = a->GetClass()->GetComponentSize();
1234 size_t byte_count = a->GetLength() * component_size;
1235 void* result = Create(a->GetRawData(component_size, 0), byte_count, true);
1236 if (is_copy != nullptr) {
1237 *is_copy = JNI_TRUE;
1238 }
1239 return result;
1240 }
1241
1242 /*
1243 * Perform the array "release" operation, which may or may not copy data
1244 * back into the managed heap, and may or may not release the underlying storage.
1245 */
1246 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env, jarray java_array,
1247 void* embedded_buf, int mode) {
1248 ScopedObjectAccess soa(env);
1249 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1250
1251 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1252 return nullptr;
1253 }
1254 if (mode != JNI_ABORT) {
1255 size_t len = FromEmbedded(embedded_buf)->original_length_;
1256 memcpy(a->GetRawData(a->GetClass()->GetComponentSize(), 0), embedded_buf, len);
1257 }
1258 if (mode != JNI_COMMIT) {
1259 return Destroy(embedded_buf);
1260 }
1261 return embedded_buf;
1262 }
1263
1264
1265 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001266 * Free up the guard buffer, scrub it, and return the original pointer.
1267 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001268 static void* Destroy(void* embedded_buf) {
1269 GuardedCopy* copy = FromEmbedded(embedded_buf);
1270 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1271 size_t len = LengthIncludingRedZones(copy->original_length_);
1272 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001273 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001274 }
1275
1276 /*
1277 * Verify the guard area and, if "modOkay" is false, that the data itself
1278 * has not been altered.
1279 *
1280 * The caller has already checked that "dataBuf" is non-NULL.
1281 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001282 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1283 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1284 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001285 }
1286
1287 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07001288 GuardedCopy(const void* original_buf, size_t len, uLong adler) :
1289 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1290 }
1291
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001292 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001293 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001294 if (result == MAP_FAILED) {
1295 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1296 }
1297 return reinterpret_cast<uint8_t*>(result);
1298 }
1299
Ian Rogers68d8b422014-07-17 11:09:10 -07001300 static void DebugFree(void* buf, size_t len) {
1301 if (munmap(buf, len) != 0) {
1302 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001303 }
1304 }
1305
Ian Rogers68d8b422014-07-17 11:09:10 -07001306 static size_t LengthIncludingRedZones(size_t len) {
1307 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001308 }
1309
Ian Rogers68d8b422014-07-17 11:09:10 -07001310 // Get the GuardedCopy from the interior pointer.
1311 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1312 return reinterpret_cast<GuardedCopy*>(
1313 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001314 }
1315
Ian Rogers68d8b422014-07-17 11:09:10 -07001316 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1317 return reinterpret_cast<const GuardedCopy*>(
1318 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001319 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001320
1321 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1322 va_list args;
1323 va_start(args, fmt);
1324 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1325 va_end(args);
1326 }
1327
1328 bool CheckHeader(const char* function_name, bool mod_okay) const {
1329 static const uint32_t kMagicCmp = kGuardMagic;
1330
1331 // Before we do anything with "pExtra", check the magic number. We
1332 // do the check with memcmp rather than "==" in case the pointer is
1333 // unaligned. If it points to completely bogus memory we're going
1334 // to crash, but there's no easy way around that.
1335 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1336 uint8_t buf[4];
1337 memcpy(buf, &magic_, 4);
1338 AbortF(function_name,
1339 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1340 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1341 return false;
1342 }
1343
1344 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1345 // told the client that we made a copy, there's no reason they can't alter the buffer.
1346 if (!mod_okay) {
1347 uLong computed_adler =
1348 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1349 if (computed_adler != adler_) {
1350 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1351 computed_adler, adler_, this);
1352 return false;
1353 }
1354 }
1355 return true;
1356 }
1357
1358 bool CheckRedZones(const char* function_name) const {
1359 // Check the begin red zone.
1360 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1361 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1362 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1363 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1364 return false;
1365 }
1366 if (kCanary[j] == '\0') {
1367 j = 0;
1368 }
1369 }
1370
1371 // Check end region.
1372 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1373 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1374 size_t offset_from_buffer_start =
1375 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1376 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1377 offset_from_buffer_start);
1378 return false;
1379 }
1380 if (kCanary[j] == '\0') {
1381 j = 0;
1382 }
1383 }
1384 return true;
1385 }
1386
1387 // Location that canary value will be written before the guarded region.
1388 const char* StartRedZone() const {
1389 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1390 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1391 }
1392
1393 // Return the interior embedded buffer.
1394 const uint8_t* BufferWithinRedZones() const {
1395 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1396 return embedded_buf;
1397 }
1398
1399 // Location that canary value will be written after the guarded region.
1400 const char* EndRedZone() const {
1401 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1402 size_t buf_len = LengthIncludingRedZones(original_length_);
1403 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1404 }
1405
1406 static constexpr size_t kRedZoneSize = 512;
1407 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1408
1409 // Value written before and after the guarded array.
1410 static const char* const kCanary;
1411
1412 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1413
1414 const uint32_t magic_;
1415 const uLong adler_;
1416 const void* const original_ptr_;
1417 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001418};
Ian Rogers68d8b422014-07-17 11:09:10 -07001419const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001420
1421/*
1422 * ===========================================================================
1423 * JNI functions
1424 * ===========================================================================
1425 */
1426
1427class CheckJNI {
1428 public:
1429 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001430 ScopedObjectAccess soa(env);
1431 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1432 JniValueType args[1] = {{.E = env }};
1433 if (sc.Check(soa, true, "E", args)) {
1434 JniValueType result;
1435 result.I = baseEnv(env)->GetVersion(env);
1436 if (sc.Check(soa, false, "I", &result)) {
1437 return result.I;
1438 }
1439 }
1440 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001441 }
1442
Ian Rogers68d8b422014-07-17 11:09:10 -07001443 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1444 ScopedObjectAccess soa(env);
1445 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1446 JniValueType args[2] = {{.E = env }, {.p = vm}};
1447 if (sc.Check(soa, true, "Ep", args)) {
1448 JniValueType result;
1449 result.i = baseEnv(env)->GetJavaVM(env, vm);
1450 if (sc.Check(soa, false, "i", &result)) {
1451 return result.i;
1452 }
1453 }
1454 return JNI_ERR;
1455 }
1456
1457 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1458 ScopedObjectAccess soa(env);
1459 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1460 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1461 if (sc.Check(soa, true, "EcpI", args)) {
1462 JniValueType result;
1463 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1464 if (sc.Check(soa, false, "i", &result)) {
1465 return result.i;
1466 }
1467 }
1468 return JNI_ERR;
1469 }
1470
1471 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1472 ScopedObjectAccess soa(env);
1473 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1474 JniValueType args[2] = {{.E = env }, {.c = c}};
1475 if (sc.Check(soa, true, "Ec", args)) {
1476 JniValueType result;
1477 result.i = baseEnv(env)->UnregisterNatives(env, c);
1478 if (sc.Check(soa, false, "i", &result)) {
1479 return result.i;
1480 }
1481 }
1482 return JNI_ERR;
1483 }
1484
1485 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001486 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1487 // know the object is invalid. The spec says that passing invalid objects or even ones that
1488 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001489 ScopedObjectAccess soa(env);
1490 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001491 JniValueType args[2] = {{.E = env }, {.L = obj}};
1492 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001493 JniValueType result;
1494 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1495 if (sc.Check(soa, false, "w", &result)) {
1496 return result.w;
1497 }
1498 }
1499 return JNIInvalidRefType;
1500 }
1501
1502 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1503 jsize bufLen) {
1504 ScopedObjectAccess soa(env);
1505 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1506 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1507 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1508 JniValueType result;
1509 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1510 if (sc.Check(soa, false, "c", &result)) {
1511 return result.c;
1512 }
1513 }
1514 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001515 }
1516
1517 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001518 ScopedObjectAccess soa(env);
1519 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1520 JniValueType args[2] = {{.E = env}, {.u = name}};
1521 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1522 JniValueType result;
1523 result.c = baseEnv(env)->FindClass(env, name);
1524 if (sc.Check(soa, false, "c", &result)) {
1525 return result.c;
1526 }
1527 }
1528 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001529 }
1530
Elliott Hughese84278b2012-03-22 10:06:53 -07001531 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001532 ScopedObjectAccess soa(env);
1533 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1534 JniValueType args[2] = {{.E = env}, {.c = c}};
1535 if (sc.Check(soa, true, "Ec", args)) {
1536 JniValueType result;
1537 result.c = baseEnv(env)->GetSuperclass(env, c);
1538 if (sc.Check(soa, false, "c", &result)) {
1539 return result.c;
1540 }
1541 }
1542 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001543 }
1544
Elliott Hughese84278b2012-03-22 10:06:53 -07001545 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001546 ScopedObjectAccess soa(env);
1547 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1548 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1549 if (sc.Check(soa, true, "Ecc", args)) {
1550 JniValueType result;
1551 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1552 if (sc.Check(soa, false, "b", &result)) {
1553 return result.b;
1554 }
1555 }
1556 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001557 }
1558
1559 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001560 ScopedObjectAccess soa(env);
1561 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1562 JniValueType args[2] = {{.E = env}, {.L = method}};
1563 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1564 JniValueType result;
1565 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1566 if (sc.Check(soa, false, "m", &result)) {
1567 return result.m;
1568 }
1569 }
1570 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001571 }
1572
1573 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001574 ScopedObjectAccess soa(env);
1575 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1576 JniValueType args[2] = {{.E = env}, {.L = field}};
1577 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1578 JniValueType result;
1579 result.f = baseEnv(env)->FromReflectedField(env, field);
1580 if (sc.Check(soa, false, "f", &result)) {
1581 return result.f;
1582 }
1583 }
1584 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001585 }
1586
1587 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001588 ScopedObjectAccess soa(env);
1589 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1590 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1591 if (sc.Check(soa, true, "Ecmb", args)) {
1592 JniValueType result;
1593 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1594 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1595 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1596 return result.L;
1597 }
1598 }
1599 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001600 }
1601
1602 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001603 ScopedObjectAccess soa(env);
1604 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1605 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1606 if (sc.Check(soa, true, "Ecfb", args)) {
1607 JniValueType result;
1608 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1609 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1610 DCHECK(sc.CheckReflectedField(soa, result.L));
1611 return result.L;
1612 }
1613 }
1614 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001615 }
1616
1617 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001618 ScopedObjectAccess soa(env);
1619 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1620 JniValueType args[2] = {{.E = env}, {.t = obj}};
1621 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1622 JniValueType result;
1623 result.i = baseEnv(env)->Throw(env, obj);
1624 if (sc.Check(soa, false, "i", &result)) {
1625 return result.i;
1626 }
1627 }
1628 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001629 }
1630
Elliott Hughese84278b2012-03-22 10:06:53 -07001631 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001632 ScopedObjectAccess soa(env);
1633 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001634 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001635 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1636 JniValueType result;
1637 result.i = baseEnv(env)->ThrowNew(env, c, message);
1638 if (sc.Check(soa, false, "i", &result)) {
1639 return result.i;
1640 }
1641 }
1642 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001643 }
1644
1645 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001646 ScopedObjectAccess soa(env);
1647 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1648 JniValueType args[1] = {{.E = env}};
1649 if (sc.Check(soa, true, "E", args)) {
1650 JniValueType result;
1651 result.t = baseEnv(env)->ExceptionOccurred(env);
1652 if (sc.Check(soa, false, "t", &result)) {
1653 return result.t;
1654 }
1655 }
1656 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001657 }
1658
1659 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001660 ScopedObjectAccess soa(env);
1661 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1662 JniValueType args[1] = {{.E = env}};
1663 if (sc.Check(soa, true, "E", args)) {
1664 JniValueType result;
1665 baseEnv(env)->ExceptionDescribe(env);
1666 result.V = nullptr;
1667 sc.Check(soa, false, "V", &result);
1668 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001669 }
1670
1671 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001672 ScopedObjectAccess soa(env);
1673 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1674 JniValueType args[1] = {{.E = env}};
1675 if (sc.Check(soa, true, "E", args)) {
1676 JniValueType result;
1677 baseEnv(env)->ExceptionClear(env);
1678 result.V = nullptr;
1679 sc.Check(soa, false, "V", &result);
1680 }
1681 }
1682
1683 static jboolean ExceptionCheck(JNIEnv* env) {
1684 ScopedObjectAccess soa(env);
1685 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1686 JniValueType args[1] = {{.E = env}};
1687 if (sc.Check(soa, true, "E", args)) {
1688 JniValueType result;
1689 result.b = baseEnv(env)->ExceptionCheck(env);
1690 if (sc.Check(soa, false, "b", &result)) {
1691 return result.b;
1692 }
1693 }
1694 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001695 }
1696
1697 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001698 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1699 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1700 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001701 ScopedObjectAccess soa(env);
1702 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1703 JniValueType args[2] = {{.E = env}, {.u = msg}};
1704 if (sc.Check(soa, true, "Eu", args)) {
1705 JniValueType result;
1706 baseEnv(env)->FatalError(env, msg);
1707 // Unreachable.
1708 result.V = nullptr;
1709 sc.Check(soa, false, "V", &result);
1710 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001711 }
1712
1713 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001714 ScopedObjectAccess soa(env);
1715 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1716 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1717 if (sc.Check(soa, true, "EI", args)) {
1718 JniValueType result;
1719 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1720 if (sc.Check(soa, false, "i", &result)) {
1721 return result.i;
1722 }
1723 }
1724 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001725 }
1726
1727 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001728 ScopedObjectAccess soa(env);
1729 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1730 JniValueType args[2] = {{.E = env}, {.L = res}};
1731 if (sc.Check(soa, true, "EL", args)) {
1732 JniValueType result;
1733 result.L = baseEnv(env)->PopLocalFrame(env, res);
1734 sc.Check(soa, false, "L", &result);
1735 return result.L;
1736 }
1737 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001738 }
1739
1740 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001741 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001742 }
1743
Ian Rogers68d8b422014-07-17 11:09:10 -07001744 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1745 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001746 }
1747
1748 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001749 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001750 }
1751
Ian Rogers68d8b422014-07-17 11:09:10 -07001752 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1753 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001754 }
1755
Ian Rogers68d8b422014-07-17 11:09:10 -07001756 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1757 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1758 }
1759
1760 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1761 DeleteRef(__FUNCTION__, env, obj, kLocal);
1762 }
1763
1764 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1765 ScopedObjectAccess soa(env);
1766 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1767 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1768 if (sc.Check(soa, true, "EI", args)) {
1769 JniValueType result;
1770 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1771 if (sc.Check(soa, false, "i", &result)) {
1772 return result.i;
1773 }
1774 }
1775 return JNI_ERR;
1776 }
1777
1778 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1779 ScopedObjectAccess soa(env);
1780 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1781 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1782 if (sc.Check(soa, true, "ELL", args)) {
1783 JniValueType result;
1784 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1785 if (sc.Check(soa, false, "b", &result)) {
1786 return result.b;
1787 }
1788 }
1789 return JNI_FALSE;
1790 }
1791
1792 static jobject AllocObject(JNIEnv* env, jclass c) {
1793 ScopedObjectAccess soa(env);
1794 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1795 JniValueType args[2] = {{.E = env}, {.c = c}};
1796 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1797 JniValueType result;
1798 result.L = baseEnv(env)->AllocObject(env, c);
1799 if (sc.Check(soa, false, "L", &result)) {
1800 return result.L;
1801 }
1802 }
1803 return nullptr;
1804 }
1805
1806 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1807 ScopedObjectAccess soa(env);
1808 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1809 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001810 if (sc.Check(soa, true, "Ecm", args) && sc.CheckInstantiableNonArray(soa, c) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07001811 sc.CheckConstructor(soa, mid)) {
1812 JniValueType result;
1813 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
1814 if (sc.Check(soa, false, "L", &result)) {
1815 return result.L;
1816 }
1817 }
1818 return nullptr;
1819 }
1820
1821 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1822 va_list args;
1823 va_start(args, mid);
1824 jobject result = NewObjectV(env, c, mid, args);
1825 va_end(args);
1826 return result;
1827 }
1828
1829 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
1830 ScopedObjectAccess soa(env);
1831 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1832 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001833 if (sc.Check(soa, true, "Ecm", args) && sc.CheckInstantiableNonArray(soa, c) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07001834 sc.CheckConstructor(soa, mid)) {
1835 JniValueType result;
1836 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
1837 if (sc.Check(soa, false, "L", &result)) {
1838 return result.L;
1839 }
1840 }
1841 return nullptr;
1842 }
1843
1844 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1845 ScopedObjectAccess soa(env);
1846 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1847 JniValueType args[2] = {{.E = env}, {.L = obj}};
1848 if (sc.Check(soa, true, "EL", args)) {
1849 JniValueType result;
1850 result.c = baseEnv(env)->GetObjectClass(env, obj);
1851 if (sc.Check(soa, false, "c", &result)) {
1852 return result.c;
1853 }
1854 }
1855 return nullptr;
1856 }
1857
1858 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
1859 ScopedObjectAccess soa(env);
1860 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1861 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
1862 if (sc.Check(soa, true, "ELc", args)) {
1863 JniValueType result;
1864 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
1865 if (sc.Check(soa, false, "b", &result)) {
1866 return result.b;
1867 }
1868 }
1869 return JNI_FALSE;
1870 }
1871
1872 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1873 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
1874 }
1875
1876 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1877 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
1878 }
1879
1880 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1881 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
1882 }
1883
1884 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1885 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
1886 }
1887
1888#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
1889 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
1890 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
1891 } \
1892 \
1893 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1894 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
1895 } \
1896 \
1897 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
1898 JniValueType value; \
1899 value.shorty = v; \
1900 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
1901 } \
1902 \
1903 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
1904 JniValueType value; \
1905 value.shorty = v; \
1906 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
1907 }
1908
1909 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
1910 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
1911 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
1912 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
1913 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
1914 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
1915 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
1916 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
1917 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
1918#undef FIELD_ACCESSORS
1919
1920 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
1921 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1922 }
1923
1924 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
1925 jvalue* vargs) {
1926 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1927 }
1928
1929 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01001930 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07001931 }
1932
1933 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
1934 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1935 }
1936
1937 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
1938 va_list vargs) {
1939 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1940 }
1941
1942 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1943 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
1944 }
1945
1946 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1947 va_list vargs;
1948 va_start(vargs, mid);
1949 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1950 va_end(vargs);
1951 }
1952
1953 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
1954 va_list vargs;
1955 va_start(vargs, mid);
1956 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1957 va_end(vargs);
1958 }
1959
1960 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
1961 va_list vargs;
1962 va_start(vargs, mid);
1963 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
1964 va_end(vargs);
1965 }
1966
1967#define CALL(rtype, name, ptype, shorty) \
1968 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
1969 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1970 } \
1971 \
1972 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1973 jvalue* vargs) { \
1974 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1975 } \
1976 \
1977 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
1978 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
1979 } \
1980 \
1981 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
1982 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1983 } \
1984 \
1985 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1986 va_list vargs) { \
1987 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1988 } \
1989 \
1990 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
1991 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
1992 } \
1993 \
1994 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
1995 va_list vargs; \
1996 va_start(vargs, mid); \
1997 rtype result = \
1998 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1999 va_end(vargs); \
2000 return result; \
2001 } \
2002 \
2003 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2004 ...) { \
2005 va_list vargs; \
2006 va_start(vargs, mid); \
2007 rtype result = \
2008 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2009 va_end(vargs); \
2010 return result; \
2011 } \
2012 \
2013 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2014 va_list vargs; \
2015 va_start(vargs, mid); \
2016 rtype result = \
2017 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2018 va_end(vargs); \
2019 return result; \
2020 }
2021
2022 CALL(jobject, Object, Primitive::kPrimNot, L)
2023 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2024 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2025 CALL(jchar, Char, Primitive::kPrimChar, C)
2026 CALL(jshort, Short, Primitive::kPrimShort, S)
2027 CALL(jint, Int, Primitive::kPrimInt, I)
2028 CALL(jlong, Long, Primitive::kPrimLong, J)
2029 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2030 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2031#undef CALL
2032
2033 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2034 ScopedObjectAccess soa(env);
2035 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2036 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2037 if (sc.Check(soa, true, "Epz", args)) {
2038 JniValueType result;
2039 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2040 if (sc.Check(soa, false, "s", &result)) {
2041 return result.s;
2042 }
2043 }
2044 return nullptr;
2045 }
2046
2047 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2048 ScopedObjectAccess soa(env);
2049 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2050 JniValueType args[2] = {{.E = env}, {.u = chars}};
2051 if (sc.Check(soa, true, "Eu", args)) {
2052 JniValueType result;
2053 // TODO: stale? show pointer and truncate string.
2054 result.s = baseEnv(env)->NewStringUTF(env, chars);
2055 if (sc.Check(soa, false, "s", &result)) {
2056 return result.s;
2057 }
2058 }
2059 return nullptr;
2060 }
2061
2062 static jsize GetStringLength(JNIEnv* env, jstring string) {
2063 ScopedObjectAccess soa(env);
2064 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2065 JniValueType args[2] = {{.E = env}, {.s = string}};
2066 if (sc.Check(soa, true, "Es", args)) {
2067 JniValueType result;
2068 result.z = baseEnv(env)->GetStringLength(env, string);
2069 if (sc.Check(soa, false, "z", &result)) {
2070 return result.z;
2071 }
2072 }
2073 return JNI_ERR;
2074 }
2075
2076 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2077 ScopedObjectAccess soa(env);
2078 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2079 JniValueType args[2] = {{.E = env}, {.s = string}};
2080 if (sc.Check(soa, true, "Es", args)) {
2081 JniValueType result;
2082 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2083 if (sc.Check(soa, false, "z", &result)) {
2084 return result.z;
2085 }
2086 }
2087 return JNI_ERR;
2088 }
2089
2090 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2091 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2092 is_copy, false, false));
2093 }
2094
2095 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2096 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2097 is_copy, true, false));
2098 }
2099
2100 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2101 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2102 is_copy, false, true));
2103 }
2104
2105 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2106 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2107 }
2108
2109 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2110 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2111 }
2112
2113 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2114 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2115 }
2116
2117 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2118 ScopedObjectAccess soa(env);
2119 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2120 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2121 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2122 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2123 if (sc.Check(soa, true, "EsIIp", args)) {
2124 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2125 JniValueType result;
2126 result.V = nullptr;
2127 sc.Check(soa, false, "V", &result);
2128 }
2129 }
2130
2131 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2132 ScopedObjectAccess soa(env);
2133 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2134 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2135 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2136 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2137 if (sc.Check(soa, true, "EsIIp", args)) {
2138 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2139 JniValueType result;
2140 result.V = nullptr;
2141 sc.Check(soa, false, "V", &result);
2142 }
2143 }
2144
2145 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2146 ScopedObjectAccess soa(env);
2147 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2148 JniValueType args[2] = {{.E = env}, {.a = array}};
2149 if (sc.Check(soa, true, "Ea", args)) {
2150 JniValueType result;
2151 result.z = baseEnv(env)->GetArrayLength(env, array);
2152 if (sc.Check(soa, false, "z", &result)) {
2153 return result.z;
2154 }
2155 }
2156 return JNI_ERR;
2157 }
2158
2159 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2160 jobject initial_element) {
2161 ScopedObjectAccess soa(env);
2162 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2163 JniValueType args[4] =
2164 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2165 if (sc.Check(soa, true, "EzcL", args)) {
2166 JniValueType result;
2167 // Note: assignability tests of initial_element are done in the base implementation.
2168 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2169 if (sc.Check(soa, false, "a", &result)) {
2170 return down_cast<jobjectArray>(result.a);
2171 }
2172 }
2173 return nullptr;
2174 }
2175
2176 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2177 ScopedObjectAccess soa(env);
2178 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2179 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2180 if (sc.Check(soa, true, "Eaz", args)) {
2181 JniValueType result;
2182 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2183 if (sc.Check(soa, false, "L", &result)) {
2184 return result.L;
2185 }
2186 }
2187 return nullptr;
2188 }
2189
2190 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2191 ScopedObjectAccess soa(env);
2192 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2193 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2194 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2195 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2196 // in ArrayStoreExceptions.
2197 if (sc.Check(soa, true, "EaIL", args)) {
2198 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2199 JniValueType result;
2200 result.V = nullptr;
2201 sc.Check(soa, false, "V", &result);
2202 }
2203 }
2204
2205 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2206 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2207 Primitive::kPrimBoolean));
2208 }
2209
2210 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2211 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2212 Primitive::kPrimByte));
2213 }
2214
2215 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2216 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2217 Primitive::kPrimChar));
2218 }
2219
2220 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2221 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2222 Primitive::kPrimShort));
2223 }
2224
2225 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2226 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2227 }
2228
2229 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2230 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2231 Primitive::kPrimLong));
2232 }
2233
2234 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2235 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2236 Primitive::kPrimFloat));
2237 }
2238
2239 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2240 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2241 Primitive::kPrimDouble));
2242 }
2243
2244#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
2245 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { \
2246 return reinterpret_cast<ctype*>( \
2247 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2248 } \
2249 \
2250 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, \
2251 jint mode) { \
2252 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2253 } \
2254 \
2255 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2256 ctype* buf) { \
2257 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2258 } \
2259 \
2260 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2261 const ctype* buf) { \
2262 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2263 }
2264
2265 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2266 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2267 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2268 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2269 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2270 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2271 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2272 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2273#undef PRIMITIVE_ARRAY_FUNCTIONS
2274
2275 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2276 ScopedObjectAccess soa(env);
2277 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2278 JniValueType args[2] = {{.E = env}, {.L = obj}};
2279 if (sc.Check(soa, true, "EL", args)) {
2280 JniValueType result;
2281 result.i = baseEnv(env)->MonitorEnter(env, obj);
2282 if (sc.Check(soa, false, "i", &result)) {
2283 return result.i;
2284 }
2285 }
2286 return JNI_ERR;
2287 }
2288
2289 static jint MonitorExit(JNIEnv* env, jobject obj) {
2290 ScopedObjectAccess soa(env);
2291 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2292 JniValueType args[2] = {{.E = env}, {.L = obj}};
2293 if (sc.Check(soa, true, "EL", args)) {
2294 JniValueType result;
2295 result.i = baseEnv(env)->MonitorExit(env, obj);
2296 if (sc.Check(soa, false, "i", &result)) {
2297 return result.i;
2298 }
2299 }
2300 return JNI_ERR;
2301 }
2302
2303 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2304 ScopedObjectAccess soa(env);
2305 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2306 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2307 if (sc.Check(soa, true, "Eap", args)) {
2308 JniValueType result;
2309 result.p = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2310 if (result.p != nullptr && soa.ForceCopy()) {
2311 result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy);
2312 }
2313 if (sc.Check(soa, false, "p", &result)) {
2314 return const_cast<void*>(result.p);
2315 }
2316 }
2317 return nullptr;
2318 }
2319
2320 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2321 ScopedObjectAccess soa(env);
2322 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2323 sc.CheckNonNull(carray);
2324 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2325 if (sc.Check(soa, true, "Eapr", args)) {
2326 if (soa.ForceCopy()) {
2327 GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
2328 }
2329 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2330 JniValueType result;
2331 result.V = nullptr;
2332 sc.Check(soa, false, "V", &result);
2333 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002334 }
2335
2336 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002337 ScopedObjectAccess soa(env);
2338 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2339 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2340 if (sc.Check(soa, true, "EpJ", args)) {
2341 JniValueType result;
2342 // Note: the validity of address and capacity are checked in the base implementation.
2343 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2344 if (sc.Check(soa, false, "L", &result)) {
2345 return result.L;
2346 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002347 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002348 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002349 }
2350
2351 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002352 ScopedObjectAccess soa(env);
2353 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2354 JniValueType args[2] = {{.E = env}, {.L = buf}};
2355 if (sc.Check(soa, true, "EL", args)) {
2356 JniValueType result;
2357 // Note: this is implemented in the base environment by a GetLongField which will sanity
2358 // check the type of buf in GetLongField above.
2359 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2360 if (sc.Check(soa, false, "p", &result)) {
2361 return const_cast<void*>(result.p);
2362 }
2363 }
2364 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002365 }
2366
2367 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002368 ScopedObjectAccess soa(env);
2369 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2370 JniValueType args[2] = {{.E = env}, {.L = buf}};
2371 if (sc.Check(soa, true, "EL", args)) {
2372 JniValueType result;
2373 // Note: this is implemented in the base environment by a GetIntField which will sanity
2374 // check the type of buf in GetIntField above.
2375 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2376 if (sc.Check(soa, false, "J", &result)) {
2377 return result.J;
2378 }
2379 }
2380 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002381 }
2382
2383 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002384 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2385 return reinterpret_cast<JNIEnvExt*>(env)->vm;
2386 }
2387
2388 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002389 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2390 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002391
2392 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2393 ScopedObjectAccess soa(env);
2394 ScopedCheck sc(kFlag_Default, function_name);
2395 JniValueType args[2] = {{.E = env}, {.L = obj}};
2396 if (sc.Check(soa, true, "EL", args)) {
2397 JniValueType result;
2398 switch (kind) {
2399 case kGlobal:
2400 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2401 break;
2402 case kLocal:
2403 result.L = baseEnv(env)->NewLocalRef(env, obj);
2404 break;
2405 case kWeakGlobal:
2406 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2407 break;
2408 default:
2409 LOG(FATAL) << "Unexpected reference kind: " << kind;
2410 }
2411 if (sc.Check(soa, false, "L", &result)) {
2412 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002413 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002414 return result.L;
2415 }
2416 }
2417 return nullptr;
2418 }
2419
2420 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2421 ScopedObjectAccess soa(env);
2422 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2423 JniValueType args[2] = {{.E = env}, {.L = obj}};
2424 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002425 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002426 JniValueType result;
2427 switch (kind) {
2428 case kGlobal:
2429 baseEnv(env)->DeleteGlobalRef(env, obj);
2430 break;
2431 case kLocal:
2432 baseEnv(env)->DeleteLocalRef(env, obj);
2433 break;
2434 case kWeakGlobal:
2435 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2436 break;
2437 default:
2438 LOG(FATAL) << "Unexpected reference kind: " << kind;
2439 }
2440 result.V = nullptr;
2441 sc.Check(soa, false, "V", &result);
2442 }
2443 }
2444
2445 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2446 const char* name, const char* sig, bool is_static) {
2447 ScopedObjectAccess soa(env);
2448 ScopedCheck sc(kFlag_Default, function_name);
2449 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2450 if (sc.Check(soa, true, "Ecuu", args)) {
2451 JniValueType result;
2452 if (is_static) {
2453 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2454 } else {
2455 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2456 }
2457 if (sc.Check(soa, false, "m", &result)) {
2458 return result.m;
2459 }
2460 }
2461 return nullptr;
2462 }
2463
2464 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2465 const char* name, const char* sig, bool is_static) {
2466 ScopedObjectAccess soa(env);
2467 ScopedCheck sc(kFlag_Default, function_name);
2468 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2469 if (sc.Check(soa, true, "Ecuu", args)) {
2470 JniValueType result;
2471 if (is_static) {
2472 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2473 } else {
2474 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2475 }
2476 if (sc.Check(soa, false, "f", &result)) {
2477 return result.f;
2478 }
2479 }
2480 return nullptr;
2481 }
2482
2483 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2484 bool is_static, Primitive::Type type) {
2485 ScopedObjectAccess soa(env);
2486 ScopedCheck sc(kFlag_Default, function_name);
2487 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2488 JniValueType result;
2489 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2490 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2491 const char* result_check = nullptr;
2492 switch (type) {
2493 case Primitive::kPrimNot:
2494 if (is_static) {
2495 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2496 } else {
2497 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2498 }
2499 result_check = "L";
2500 break;
2501 case Primitive::kPrimBoolean:
2502 if (is_static) {
2503 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2504 } else {
2505 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2506 }
2507 result_check = "Z";
2508 break;
2509 case Primitive::kPrimByte:
2510 if (is_static) {
2511 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2512 } else {
2513 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2514 }
2515 result_check = "B";
2516 break;
2517 case Primitive::kPrimChar:
2518 if (is_static) {
2519 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2520 } else {
2521 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2522 }
2523 result_check = "C";
2524 break;
2525 case Primitive::kPrimShort:
2526 if (is_static) {
2527 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2528 } else {
2529 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2530 }
2531 result_check = "S";
2532 break;
2533 case Primitive::kPrimInt:
2534 if (is_static) {
2535 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2536 } else {
2537 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2538 }
2539 result_check = "I";
2540 break;
2541 case Primitive::kPrimLong:
2542 if (is_static) {
2543 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2544 } else {
2545 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2546 }
2547 result_check = "J";
2548 break;
2549 case Primitive::kPrimFloat:
2550 if (is_static) {
2551 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2552 } else {
2553 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2554 }
2555 result_check = "F";
2556 break;
2557 case Primitive::kPrimDouble:
2558 if (is_static) {
2559 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2560 } else {
2561 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2562 }
2563 result_check = "D";
2564 break;
2565 case Primitive::kPrimVoid:
2566 LOG(FATAL) << "Unexpected type: " << type;
2567 break;
2568 }
2569 if (sc.Check(soa, false, result_check, &result)) {
2570 return result;
2571 }
2572 }
2573 result.J = 0;
2574 return result;
2575 }
2576
2577 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2578 bool is_static, Primitive::Type type, JniValueType value) {
2579 ScopedObjectAccess soa(env);
2580 ScopedCheck sc(kFlag_Default, function_name);
2581 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2582 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2583 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2584 if (sc.Check(soa, true, sig, args) &&
2585 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2586 switch (type) {
2587 case Primitive::kPrimNot:
2588 if (is_static) {
2589 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2590 } else {
2591 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2592 }
2593 break;
2594 case Primitive::kPrimBoolean:
2595 if (is_static) {
2596 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2597 } else {
2598 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2599 }
2600 break;
2601 case Primitive::kPrimByte:
2602 if (is_static) {
2603 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2604 } else {
2605 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2606 }
2607 break;
2608 case Primitive::kPrimChar:
2609 if (is_static) {
2610 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2611 } else {
2612 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2613 }
2614 break;
2615 case Primitive::kPrimShort:
2616 if (is_static) {
2617 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2618 } else {
2619 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2620 }
2621 break;
2622 case Primitive::kPrimInt:
2623 if (is_static) {
2624 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2625 } else {
2626 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2627 }
2628 break;
2629 case Primitive::kPrimLong:
2630 if (is_static) {
2631 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2632 } else {
2633 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2634 }
2635 break;
2636 case Primitive::kPrimFloat:
2637 if (is_static) {
2638 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2639 } else {
2640 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2641 }
2642 break;
2643 case Primitive::kPrimDouble:
2644 if (is_static) {
2645 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2646 } else {
2647 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2648 }
2649 break;
2650 case Primitive::kPrimVoid:
2651 LOG(FATAL) << "Unexpected type: " << type;
2652 break;
2653 }
2654 JniValueType result;
2655 result.V = nullptr;
2656 sc.Check(soa, false, "V", &result);
2657 }
2658 }
2659
2660 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
2661 jclass c, jmethodID mid, InvokeType invoke)
2662 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2663 bool checked;
2664 switch (invoke) {
2665 case kVirtual: {
2666 DCHECK(c == nullptr);
2667 JniValueType args[3] = {{.E = env}, {.L = obj}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07002668 checked = sc.Check(soa, true, "ELm", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002669 break;
2670 }
2671 case kDirect: {
2672 JniValueType args[4] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07002673 checked = sc.Check(soa, true, "ELcm", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002674 break;
2675 }
2676 case kStatic: {
2677 DCHECK(obj == nullptr);
2678 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07002679 checked = sc.Check(soa, true, "Ecm", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002680 break;
2681 }
2682 default:
2683 LOG(FATAL) << "Unexpected invoke: " << invoke;
2684 checked = false;
2685 break;
2686 }
2687 return checked;
2688 }
2689
2690 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2691 jmethodID mid, jvalue* vargs, Primitive::Type type,
2692 InvokeType invoke) {
2693 ScopedObjectAccess soa(env);
2694 ScopedCheck sc(kFlag_Default, function_name);
2695 JniValueType result;
2696 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
2697 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2698 const char* result_check;
2699 switch (type) {
2700 case Primitive::kPrimNot:
2701 result_check = "L";
2702 switch (invoke) {
2703 case kVirtual:
2704 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2705 break;
2706 case kDirect:
2707 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2708 break;
2709 case kStatic:
2710 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2711 break;
2712 default:
2713 break;
2714 }
2715 break;
2716 case Primitive::kPrimBoolean:
2717 result_check = "Z";
2718 switch (invoke) {
2719 case kVirtual:
2720 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2721 break;
2722 case kDirect:
2723 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2724 break;
2725 case kStatic:
2726 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2727 break;
2728 default:
2729 break;
2730 }
2731 break;
2732 case Primitive::kPrimByte:
2733 result_check = "B";
2734 switch (invoke) {
2735 case kVirtual:
2736 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2737 break;
2738 case kDirect:
2739 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2740 break;
2741 case kStatic:
2742 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2743 break;
2744 default:
2745 break;
2746 }
2747 break;
2748 case Primitive::kPrimChar:
2749 result_check = "C";
2750 switch (invoke) {
2751 case kVirtual:
2752 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2753 break;
2754 case kDirect:
2755 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2756 break;
2757 case kStatic:
2758 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2759 break;
2760 default:
2761 break;
2762 }
2763 break;
2764 case Primitive::kPrimShort:
2765 result_check = "S";
2766 switch (invoke) {
2767 case kVirtual:
2768 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2769 break;
2770 case kDirect:
2771 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2772 break;
2773 case kStatic:
2774 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2775 break;
2776 default:
2777 break;
2778 }
2779 break;
2780 case Primitive::kPrimInt:
2781 result_check = "I";
2782 switch (invoke) {
2783 case kVirtual:
2784 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2785 break;
2786 case kDirect:
2787 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2788 break;
2789 case kStatic:
2790 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
2791 break;
2792 default:
2793 break;
2794 }
2795 break;
2796 case Primitive::kPrimLong:
2797 result_check = "J";
2798 switch (invoke) {
2799 case kVirtual:
2800 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
2801 break;
2802 case kDirect:
2803 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
2804 break;
2805 case kStatic:
2806 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
2807 break;
2808 default:
2809 break;
2810 }
2811 break;
2812 case Primitive::kPrimFloat:
2813 result_check = "F";
2814 switch (invoke) {
2815 case kVirtual:
2816 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
2817 break;
2818 case kDirect:
2819 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
2820 break;
2821 case kStatic:
2822 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
2823 break;
2824 default:
2825 break;
2826 }
2827 break;
2828 case Primitive::kPrimDouble:
2829 result_check = "D";
2830 switch (invoke) {
2831 case kVirtual:
2832 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
2833 break;
2834 case kDirect:
2835 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
2836 break;
2837 case kStatic:
2838 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
2839 break;
2840 default:
2841 break;
2842 }
2843 break;
2844 case Primitive::kPrimVoid:
2845 result_check = "V";
2846 result.V = nullptr;
2847 switch (invoke) {
2848 case kVirtual:
2849 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
2850 break;
2851 case kDirect:
2852 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
2853 break;
2854 case kStatic:
2855 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
2856 break;
2857 default:
2858 LOG(FATAL) << "Unexpected invoke: " << invoke;
2859 }
2860 break;
2861 default:
2862 LOG(FATAL) << "Unexpected return type: " << type;
2863 result_check = nullptr;
2864 }
2865 if (sc.Check(soa, false, result_check, &result)) {
2866 return result;
2867 }
2868 }
2869 result.J = 0;
2870 return result;
2871 }
2872
2873 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2874 jmethodID mid, va_list vargs, Primitive::Type type,
2875 InvokeType invoke) {
2876 ScopedObjectAccess soa(env);
2877 ScopedCheck sc(kFlag_Default, function_name);
2878 JniValueType result;
2879 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
2880 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2881 const char* result_check;
2882 switch (type) {
2883 case Primitive::kPrimNot:
2884 result_check = "L";
2885 switch (invoke) {
2886 case kVirtual:
2887 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
2888 break;
2889 case kDirect:
2890 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
2891 break;
2892 case kStatic:
2893 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
2894 break;
2895 default:
2896 LOG(FATAL) << "Unexpected invoke: " << invoke;
2897 }
2898 break;
2899 case Primitive::kPrimBoolean:
2900 result_check = "Z";
2901 switch (invoke) {
2902 case kVirtual:
2903 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
2904 break;
2905 case kDirect:
2906 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
2907 break;
2908 case kStatic:
2909 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
2910 break;
2911 default:
2912 LOG(FATAL) << "Unexpected invoke: " << invoke;
2913 }
2914 break;
2915 case Primitive::kPrimByte:
2916 result_check = "B";
2917 switch (invoke) {
2918 case kVirtual:
2919 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
2920 break;
2921 case kDirect:
2922 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
2923 break;
2924 case kStatic:
2925 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
2926 break;
2927 default:
2928 LOG(FATAL) << "Unexpected invoke: " << invoke;
2929 }
2930 break;
2931 case Primitive::kPrimChar:
2932 result_check = "C";
2933 switch (invoke) {
2934 case kVirtual:
2935 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
2936 break;
2937 case kDirect:
2938 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
2939 break;
2940 case kStatic:
2941 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
2942 break;
2943 default:
2944 LOG(FATAL) << "Unexpected invoke: " << invoke;
2945 }
2946 break;
2947 case Primitive::kPrimShort:
2948 result_check = "S";
2949 switch (invoke) {
2950 case kVirtual:
2951 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
2952 break;
2953 case kDirect:
2954 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
2955 break;
2956 case kStatic:
2957 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
2958 break;
2959 default:
2960 LOG(FATAL) << "Unexpected invoke: " << invoke;
2961 }
2962 break;
2963 case Primitive::kPrimInt:
2964 result_check = "I";
2965 switch (invoke) {
2966 case kVirtual:
2967 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
2968 break;
2969 case kDirect:
2970 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
2971 break;
2972 case kStatic:
2973 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
2974 break;
2975 default:
2976 LOG(FATAL) << "Unexpected invoke: " << invoke;
2977 }
2978 break;
2979 case Primitive::kPrimLong:
2980 result_check = "J";
2981 switch (invoke) {
2982 case kVirtual:
2983 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
2984 break;
2985 case kDirect:
2986 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
2987 break;
2988 case kStatic:
2989 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
2990 break;
2991 default:
2992 LOG(FATAL) << "Unexpected invoke: " << invoke;
2993 }
2994 break;
2995 case Primitive::kPrimFloat:
2996 result_check = "F";
2997 switch (invoke) {
2998 case kVirtual:
2999 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3000 break;
3001 case kDirect:
3002 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3003 break;
3004 case kStatic:
3005 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3006 break;
3007 default:
3008 LOG(FATAL) << "Unexpected invoke: " << invoke;
3009 }
3010 break;
3011 case Primitive::kPrimDouble:
3012 result_check = "D";
3013 switch (invoke) {
3014 case kVirtual:
3015 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3016 break;
3017 case kDirect:
3018 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3019 break;
3020 case kStatic:
3021 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3022 break;
3023 default:
3024 LOG(FATAL) << "Unexpected invoke: " << invoke;
3025 }
3026 break;
3027 case Primitive::kPrimVoid:
3028 result_check = "V";
3029 result.V = nullptr;
3030 switch (invoke) {
3031 case kVirtual:
3032 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3033 break;
3034 case kDirect:
3035 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3036 break;
3037 case kStatic:
3038 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3039 break;
3040 default:
3041 LOG(FATAL) << "Unexpected invoke: " << invoke;
3042 }
3043 break;
3044 default:
3045 LOG(FATAL) << "Unexpected return type: " << type;
3046 result_check = nullptr;
3047 }
3048 if (sc.Check(soa, false, result_check, &result)) {
3049 return result;
3050 }
3051 }
3052 result.J = 0;
3053 return result;
3054 }
3055
3056 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3057 jboolean* is_copy, bool utf, bool critical) {
3058 ScopedObjectAccess soa(env);
3059 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3060 ScopedCheck sc(flags, function_name);
3061 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3062 if (sc.Check(soa, true, "Esp", args)) {
3063 JniValueType result;
3064 if (utf) {
3065 CHECK(!critical);
3066 result.u = baseEnv(env)->GetStringUTFChars(env, string, is_copy);
3067 } else {
3068 if (critical) {
3069 result.p = baseEnv(env)->GetStringCritical(env, string, is_copy);
3070 } else {
3071 result.p = baseEnv(env)->GetStringChars(env, string, is_copy);
3072 }
3073 }
3074 // TODO: could we be smarter about not copying when local_is_copy?
3075 if (result.p != nullptr && soa.ForceCopy()) {
3076 if (utf) {
3077 size_t length_in_bytes = strlen(result.u) + 1;
3078 result.u =
3079 reinterpret_cast<const char*>(GuardedCopy::Create(result.u, length_in_bytes, false));
3080 } else {
3081 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3082 result.p =
3083 reinterpret_cast<const jchar*>(GuardedCopy::Create(result.p, length_in_bytes, false));
3084 }
3085 if (is_copy != nullptr) {
3086 *is_copy = JNI_TRUE;
3087 }
3088 }
3089 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3090 return utf ? result.u : result.p;
3091 }
3092 }
3093 return nullptr;
3094 }
3095
3096 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3097 const void* chars, bool utf, bool critical) {
3098 ScopedObjectAccess soa(env);
3099 int flags = kFlag_ExcepOkay | kFlag_Release;
3100 if (critical) {
3101 flags |= kFlag_CritRelease;
3102 }
3103 ScopedCheck sc(flags, function_name);
3104 sc.CheckNonNull(chars);
3105 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3106 if (force_copy_ok && soa.ForceCopy()) {
3107 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3108 }
3109 if (force_copy_ok) {
3110 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3111 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3112 if (utf) {
3113 CHECK(!critical);
3114 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3115 } else {
3116 if (critical) {
3117 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3118 } else {
3119 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3120 }
3121 }
3122 JniValueType result;
3123 sc.Check(soa, false, "V", &result);
3124 }
3125 }
3126 }
3127
3128 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3129 Primitive::Type type) {
3130 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003131 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003132 JniValueType args[2] = {{.E = env}, {.z = length}};
3133 if (sc.Check(soa, true, "Ez", args)) {
3134 JniValueType result;
3135 switch (type) {
3136 case Primitive::kPrimBoolean:
3137 result.a = baseEnv(env)->NewBooleanArray(env, length);
3138 break;
3139 case Primitive::kPrimByte:
3140 result.a = baseEnv(env)->NewByteArray(env, length);
3141 break;
3142 case Primitive::kPrimChar:
3143 result.a = baseEnv(env)->NewCharArray(env, length);
3144 break;
3145 case Primitive::kPrimShort:
3146 result.a = baseEnv(env)->NewShortArray(env, length);
3147 break;
3148 case Primitive::kPrimInt:
3149 result.a = baseEnv(env)->NewIntArray(env, length);
3150 break;
3151 case Primitive::kPrimLong:
3152 result.a = baseEnv(env)->NewLongArray(env, length);
3153 break;
3154 case Primitive::kPrimFloat:
3155 result.a = baseEnv(env)->NewFloatArray(env, length);
3156 break;
3157 case Primitive::kPrimDouble:
3158 result.a = baseEnv(env)->NewDoubleArray(env, length);
3159 break;
3160 default:
3161 LOG(FATAL) << "Unexpected primitive type: " << type;
3162 }
3163 if (sc.Check(soa, false, "a", &result)) {
3164 return result.a;
3165 }
3166 }
3167 return nullptr;
3168 }
3169
3170 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3171 JNIEnv* env, jarray array, jboolean* is_copy) {
3172 ScopedObjectAccess soa(env);
3173 ScopedCheck sc(kFlag_Default, function_name);
3174 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3175 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3176 JniValueType result;
3177 switch (type) {
3178 case Primitive::kPrimBoolean:
3179 result.p = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3180 is_copy);
3181 break;
3182 case Primitive::kPrimByte:
3183 result.p = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array),
3184 is_copy);
3185 break;
3186 case Primitive::kPrimChar:
3187 result.p = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array),
3188 is_copy);
3189 break;
3190 case Primitive::kPrimShort:
3191 result.p = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array),
3192 is_copy);
3193 break;
3194 case Primitive::kPrimInt:
3195 result.p = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
3196 break;
3197 case Primitive::kPrimLong:
3198 result.p = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array),
3199 is_copy);
3200 break;
3201 case Primitive::kPrimFloat:
3202 result.p = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array),
3203 is_copy);
3204 break;
3205 case Primitive::kPrimDouble:
3206 result.p = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3207 is_copy);
3208 break;
3209 default:
3210 LOG(FATAL) << "Unexpected primitive type: " << type;
3211 }
3212 if (result.p != nullptr && soa.ForceCopy()) {
3213 result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy);
3214 if (is_copy != nullptr) {
3215 *is_copy = JNI_TRUE;
3216 }
3217 }
3218 if (sc.Check(soa, false, "p", &result)) {
3219 return const_cast<void*>(result.p);
3220 }
3221 }
3222 return nullptr;
3223 }
3224
3225 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3226 JNIEnv* env, jarray array, void* elems, jint mode) {
3227 ScopedObjectAccess soa(env);
3228 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3229 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3230 if (soa.ForceCopy()) {
3231 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3232 }
3233 if (!soa.ForceCopy() || elems != nullptr) {
3234 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3235 if (sc.Check(soa, true, "Eapr", args)) {
3236 switch (type) {
3237 case Primitive::kPrimBoolean:
3238 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3239 reinterpret_cast<jboolean*>(elems), mode);
3240 break;
3241 case Primitive::kPrimByte:
3242 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3243 reinterpret_cast<jbyte*>(elems), mode);
3244 break;
3245 case Primitive::kPrimChar:
3246 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3247 reinterpret_cast<jchar*>(elems), mode);
3248 break;
3249 case Primitive::kPrimShort:
3250 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3251 reinterpret_cast<jshort*>(elems), mode);
3252 break;
3253 case Primitive::kPrimInt:
3254 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3255 reinterpret_cast<jint*>(elems), mode);
3256 break;
3257 case Primitive::kPrimLong:
3258 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3259 reinterpret_cast<jlong*>(elems), mode);
3260 break;
3261 case Primitive::kPrimFloat:
3262 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3263 reinterpret_cast<jfloat*>(elems), mode);
3264 break;
3265 case Primitive::kPrimDouble:
3266 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3267 reinterpret_cast<jdouble*>(elems), mode);
3268 break;
3269 default:
3270 LOG(FATAL) << "Unexpected primitive type: " << type;
3271 }
3272 JniValueType result;
3273 result.V = nullptr;
3274 sc.Check(soa, false, "V", &result);
3275 }
3276 }
3277 }
3278 }
3279
3280 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3281 jarray array, jsize start, jsize len, void* buf) {
3282 ScopedObjectAccess soa(env);
3283 ScopedCheck sc(kFlag_Default, function_name);
3284 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3285 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3286 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3287 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3288 switch (type) {
3289 case Primitive::kPrimBoolean:
3290 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3291 reinterpret_cast<jboolean*>(buf));
3292 break;
3293 case Primitive::kPrimByte:
3294 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3295 reinterpret_cast<jbyte*>(buf));
3296 break;
3297 case Primitive::kPrimChar:
3298 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3299 reinterpret_cast<jchar*>(buf));
3300 break;
3301 case Primitive::kPrimShort:
3302 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3303 reinterpret_cast<jshort*>(buf));
3304 break;
3305 case Primitive::kPrimInt:
3306 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3307 reinterpret_cast<jint*>(buf));
3308 break;
3309 case Primitive::kPrimLong:
3310 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3311 reinterpret_cast<jlong*>(buf));
3312 break;
3313 case Primitive::kPrimFloat:
3314 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3315 reinterpret_cast<jfloat*>(buf));
3316 break;
3317 case Primitive::kPrimDouble:
3318 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3319 reinterpret_cast<jdouble*>(buf));
3320 break;
3321 default:
3322 LOG(FATAL) << "Unexpected primitive type: " << type;
3323 }
3324 JniValueType result;
3325 result.V = nullptr;
3326 sc.Check(soa, false, "V", &result);
3327 }
3328 }
3329
3330 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3331 jarray array, jsize start, jsize len, const void* buf) {
3332 ScopedObjectAccess soa(env);
3333 ScopedCheck sc(kFlag_Default, function_name);
3334 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3335 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3336 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3337 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3338 switch (type) {
3339 case Primitive::kPrimBoolean:
3340 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3341 reinterpret_cast<const jboolean*>(buf));
3342 break;
3343 case Primitive::kPrimByte:
3344 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3345 reinterpret_cast<const jbyte*>(buf));
3346 break;
3347 case Primitive::kPrimChar:
3348 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3349 reinterpret_cast<const jchar*>(buf));
3350 break;
3351 case Primitive::kPrimShort:
3352 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3353 reinterpret_cast<const jshort*>(buf));
3354 break;
3355 case Primitive::kPrimInt:
3356 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3357 reinterpret_cast<const jint*>(buf));
3358 break;
3359 case Primitive::kPrimLong:
3360 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3361 reinterpret_cast<const jlong*>(buf));
3362 break;
3363 case Primitive::kPrimFloat:
3364 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3365 reinterpret_cast<const jfloat*>(buf));
3366 break;
3367 case Primitive::kPrimDouble:
3368 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3369 reinterpret_cast<const jdouble*>(buf));
3370 break;
3371 default:
3372 LOG(FATAL) << "Unexpected primitive type: " << type;
3373 }
3374 JniValueType result;
3375 result.V = nullptr;
3376 sc.Check(soa, false, "V", &result);
3377 }
3378 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003379};
3380
3381const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003382 nullptr, // reserved0.
3383 nullptr, // reserved1.
3384 nullptr, // reserved2.
3385 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003386 CheckJNI::GetVersion,
3387 CheckJNI::DefineClass,
3388 CheckJNI::FindClass,
3389 CheckJNI::FromReflectedMethod,
3390 CheckJNI::FromReflectedField,
3391 CheckJNI::ToReflectedMethod,
3392 CheckJNI::GetSuperclass,
3393 CheckJNI::IsAssignableFrom,
3394 CheckJNI::ToReflectedField,
3395 CheckJNI::Throw,
3396 CheckJNI::ThrowNew,
3397 CheckJNI::ExceptionOccurred,
3398 CheckJNI::ExceptionDescribe,
3399 CheckJNI::ExceptionClear,
3400 CheckJNI::FatalError,
3401 CheckJNI::PushLocalFrame,
3402 CheckJNI::PopLocalFrame,
3403 CheckJNI::NewGlobalRef,
3404 CheckJNI::DeleteGlobalRef,
3405 CheckJNI::DeleteLocalRef,
3406 CheckJNI::IsSameObject,
3407 CheckJNI::NewLocalRef,
3408 CheckJNI::EnsureLocalCapacity,
3409 CheckJNI::AllocObject,
3410 CheckJNI::NewObject,
3411 CheckJNI::NewObjectV,
3412 CheckJNI::NewObjectA,
3413 CheckJNI::GetObjectClass,
3414 CheckJNI::IsInstanceOf,
3415 CheckJNI::GetMethodID,
3416 CheckJNI::CallObjectMethod,
3417 CheckJNI::CallObjectMethodV,
3418 CheckJNI::CallObjectMethodA,
3419 CheckJNI::CallBooleanMethod,
3420 CheckJNI::CallBooleanMethodV,
3421 CheckJNI::CallBooleanMethodA,
3422 CheckJNI::CallByteMethod,
3423 CheckJNI::CallByteMethodV,
3424 CheckJNI::CallByteMethodA,
3425 CheckJNI::CallCharMethod,
3426 CheckJNI::CallCharMethodV,
3427 CheckJNI::CallCharMethodA,
3428 CheckJNI::CallShortMethod,
3429 CheckJNI::CallShortMethodV,
3430 CheckJNI::CallShortMethodA,
3431 CheckJNI::CallIntMethod,
3432 CheckJNI::CallIntMethodV,
3433 CheckJNI::CallIntMethodA,
3434 CheckJNI::CallLongMethod,
3435 CheckJNI::CallLongMethodV,
3436 CheckJNI::CallLongMethodA,
3437 CheckJNI::CallFloatMethod,
3438 CheckJNI::CallFloatMethodV,
3439 CheckJNI::CallFloatMethodA,
3440 CheckJNI::CallDoubleMethod,
3441 CheckJNI::CallDoubleMethodV,
3442 CheckJNI::CallDoubleMethodA,
3443 CheckJNI::CallVoidMethod,
3444 CheckJNI::CallVoidMethodV,
3445 CheckJNI::CallVoidMethodA,
3446 CheckJNI::CallNonvirtualObjectMethod,
3447 CheckJNI::CallNonvirtualObjectMethodV,
3448 CheckJNI::CallNonvirtualObjectMethodA,
3449 CheckJNI::CallNonvirtualBooleanMethod,
3450 CheckJNI::CallNonvirtualBooleanMethodV,
3451 CheckJNI::CallNonvirtualBooleanMethodA,
3452 CheckJNI::CallNonvirtualByteMethod,
3453 CheckJNI::CallNonvirtualByteMethodV,
3454 CheckJNI::CallNonvirtualByteMethodA,
3455 CheckJNI::CallNonvirtualCharMethod,
3456 CheckJNI::CallNonvirtualCharMethodV,
3457 CheckJNI::CallNonvirtualCharMethodA,
3458 CheckJNI::CallNonvirtualShortMethod,
3459 CheckJNI::CallNonvirtualShortMethodV,
3460 CheckJNI::CallNonvirtualShortMethodA,
3461 CheckJNI::CallNonvirtualIntMethod,
3462 CheckJNI::CallNonvirtualIntMethodV,
3463 CheckJNI::CallNonvirtualIntMethodA,
3464 CheckJNI::CallNonvirtualLongMethod,
3465 CheckJNI::CallNonvirtualLongMethodV,
3466 CheckJNI::CallNonvirtualLongMethodA,
3467 CheckJNI::CallNonvirtualFloatMethod,
3468 CheckJNI::CallNonvirtualFloatMethodV,
3469 CheckJNI::CallNonvirtualFloatMethodA,
3470 CheckJNI::CallNonvirtualDoubleMethod,
3471 CheckJNI::CallNonvirtualDoubleMethodV,
3472 CheckJNI::CallNonvirtualDoubleMethodA,
3473 CheckJNI::CallNonvirtualVoidMethod,
3474 CheckJNI::CallNonvirtualVoidMethodV,
3475 CheckJNI::CallNonvirtualVoidMethodA,
3476 CheckJNI::GetFieldID,
3477 CheckJNI::GetObjectField,
3478 CheckJNI::GetBooleanField,
3479 CheckJNI::GetByteField,
3480 CheckJNI::GetCharField,
3481 CheckJNI::GetShortField,
3482 CheckJNI::GetIntField,
3483 CheckJNI::GetLongField,
3484 CheckJNI::GetFloatField,
3485 CheckJNI::GetDoubleField,
3486 CheckJNI::SetObjectField,
3487 CheckJNI::SetBooleanField,
3488 CheckJNI::SetByteField,
3489 CheckJNI::SetCharField,
3490 CheckJNI::SetShortField,
3491 CheckJNI::SetIntField,
3492 CheckJNI::SetLongField,
3493 CheckJNI::SetFloatField,
3494 CheckJNI::SetDoubleField,
3495 CheckJNI::GetStaticMethodID,
3496 CheckJNI::CallStaticObjectMethod,
3497 CheckJNI::CallStaticObjectMethodV,
3498 CheckJNI::CallStaticObjectMethodA,
3499 CheckJNI::CallStaticBooleanMethod,
3500 CheckJNI::CallStaticBooleanMethodV,
3501 CheckJNI::CallStaticBooleanMethodA,
3502 CheckJNI::CallStaticByteMethod,
3503 CheckJNI::CallStaticByteMethodV,
3504 CheckJNI::CallStaticByteMethodA,
3505 CheckJNI::CallStaticCharMethod,
3506 CheckJNI::CallStaticCharMethodV,
3507 CheckJNI::CallStaticCharMethodA,
3508 CheckJNI::CallStaticShortMethod,
3509 CheckJNI::CallStaticShortMethodV,
3510 CheckJNI::CallStaticShortMethodA,
3511 CheckJNI::CallStaticIntMethod,
3512 CheckJNI::CallStaticIntMethodV,
3513 CheckJNI::CallStaticIntMethodA,
3514 CheckJNI::CallStaticLongMethod,
3515 CheckJNI::CallStaticLongMethodV,
3516 CheckJNI::CallStaticLongMethodA,
3517 CheckJNI::CallStaticFloatMethod,
3518 CheckJNI::CallStaticFloatMethodV,
3519 CheckJNI::CallStaticFloatMethodA,
3520 CheckJNI::CallStaticDoubleMethod,
3521 CheckJNI::CallStaticDoubleMethodV,
3522 CheckJNI::CallStaticDoubleMethodA,
3523 CheckJNI::CallStaticVoidMethod,
3524 CheckJNI::CallStaticVoidMethodV,
3525 CheckJNI::CallStaticVoidMethodA,
3526 CheckJNI::GetStaticFieldID,
3527 CheckJNI::GetStaticObjectField,
3528 CheckJNI::GetStaticBooleanField,
3529 CheckJNI::GetStaticByteField,
3530 CheckJNI::GetStaticCharField,
3531 CheckJNI::GetStaticShortField,
3532 CheckJNI::GetStaticIntField,
3533 CheckJNI::GetStaticLongField,
3534 CheckJNI::GetStaticFloatField,
3535 CheckJNI::GetStaticDoubleField,
3536 CheckJNI::SetStaticObjectField,
3537 CheckJNI::SetStaticBooleanField,
3538 CheckJNI::SetStaticByteField,
3539 CheckJNI::SetStaticCharField,
3540 CheckJNI::SetStaticShortField,
3541 CheckJNI::SetStaticIntField,
3542 CheckJNI::SetStaticLongField,
3543 CheckJNI::SetStaticFloatField,
3544 CheckJNI::SetStaticDoubleField,
3545 CheckJNI::NewString,
3546 CheckJNI::GetStringLength,
3547 CheckJNI::GetStringChars,
3548 CheckJNI::ReleaseStringChars,
3549 CheckJNI::NewStringUTF,
3550 CheckJNI::GetStringUTFLength,
3551 CheckJNI::GetStringUTFChars,
3552 CheckJNI::ReleaseStringUTFChars,
3553 CheckJNI::GetArrayLength,
3554 CheckJNI::NewObjectArray,
3555 CheckJNI::GetObjectArrayElement,
3556 CheckJNI::SetObjectArrayElement,
3557 CheckJNI::NewBooleanArray,
3558 CheckJNI::NewByteArray,
3559 CheckJNI::NewCharArray,
3560 CheckJNI::NewShortArray,
3561 CheckJNI::NewIntArray,
3562 CheckJNI::NewLongArray,
3563 CheckJNI::NewFloatArray,
3564 CheckJNI::NewDoubleArray,
3565 CheckJNI::GetBooleanArrayElements,
3566 CheckJNI::GetByteArrayElements,
3567 CheckJNI::GetCharArrayElements,
3568 CheckJNI::GetShortArrayElements,
3569 CheckJNI::GetIntArrayElements,
3570 CheckJNI::GetLongArrayElements,
3571 CheckJNI::GetFloatArrayElements,
3572 CheckJNI::GetDoubleArrayElements,
3573 CheckJNI::ReleaseBooleanArrayElements,
3574 CheckJNI::ReleaseByteArrayElements,
3575 CheckJNI::ReleaseCharArrayElements,
3576 CheckJNI::ReleaseShortArrayElements,
3577 CheckJNI::ReleaseIntArrayElements,
3578 CheckJNI::ReleaseLongArrayElements,
3579 CheckJNI::ReleaseFloatArrayElements,
3580 CheckJNI::ReleaseDoubleArrayElements,
3581 CheckJNI::GetBooleanArrayRegion,
3582 CheckJNI::GetByteArrayRegion,
3583 CheckJNI::GetCharArrayRegion,
3584 CheckJNI::GetShortArrayRegion,
3585 CheckJNI::GetIntArrayRegion,
3586 CheckJNI::GetLongArrayRegion,
3587 CheckJNI::GetFloatArrayRegion,
3588 CheckJNI::GetDoubleArrayRegion,
3589 CheckJNI::SetBooleanArrayRegion,
3590 CheckJNI::SetByteArrayRegion,
3591 CheckJNI::SetCharArrayRegion,
3592 CheckJNI::SetShortArrayRegion,
3593 CheckJNI::SetIntArrayRegion,
3594 CheckJNI::SetLongArrayRegion,
3595 CheckJNI::SetFloatArrayRegion,
3596 CheckJNI::SetDoubleArrayRegion,
3597 CheckJNI::RegisterNatives,
3598 CheckJNI::UnregisterNatives,
3599 CheckJNI::MonitorEnter,
3600 CheckJNI::MonitorExit,
3601 CheckJNI::GetJavaVM,
3602 CheckJNI::GetStringRegion,
3603 CheckJNI::GetStringUTFRegion,
3604 CheckJNI::GetPrimitiveArrayCritical,
3605 CheckJNI::ReleasePrimitiveArrayCritical,
3606 CheckJNI::GetStringCritical,
3607 CheckJNI::ReleaseStringCritical,
3608 CheckJNI::NewWeakGlobalRef,
3609 CheckJNI::DeleteWeakGlobalRef,
3610 CheckJNI::ExceptionCheck,
3611 CheckJNI::NewDirectByteBuffer,
3612 CheckJNI::GetDirectBufferAddress,
3613 CheckJNI::GetDirectBufferCapacity,
3614 CheckJNI::GetObjectRefType,
3615};
3616
3617const JNINativeInterface* GetCheckJniNativeInterface() {
3618 return &gCheckNativeInterface;
3619}
3620
3621class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003622 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003623 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003624 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3625 JniValueType args[1] = {{.v = vm}};
3626 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3627 JniValueType result;
3628 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08003629 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3630 // which will delete the JavaVMExt.
3631 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07003632 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003633 }
3634
3635 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003636 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3637 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3638 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3639 JniValueType result;
3640 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3641 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3642 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003643 }
3644
3645 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003646 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3647 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3648 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3649 JniValueType result;
3650 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3651 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3652 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003653 }
3654
3655 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003656 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3657 JniValueType args[1] = {{.v = vm}};
3658 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3659 JniValueType result;
3660 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3661 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3662 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003663 }
3664
Ian Rogers68d8b422014-07-17 11:09:10 -07003665 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3666 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3667 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3668 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3669 JniValueType result;
3670 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3671 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3672 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003673 }
3674
3675 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003676 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3677 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003678 }
3679};
3680
3681const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003682 nullptr, // reserved0
3683 nullptr, // reserved1
3684 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003685 CheckJII::DestroyJavaVM,
3686 CheckJII::AttachCurrentThread,
3687 CheckJII::DetachCurrentThread,
3688 CheckJII::GetEnv,
3689 CheckJII::AttachCurrentThreadAsDaemon
3690};
3691
3692const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3693 return &gCheckInvokeInterface;
3694}
3695
3696} // namespace art