blob: 0ae32f4785cdc54bb1728b26e34c5678ed5faff4 [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"
Mathieu Chartiere401d142015-04-22 13:56:20 -070023#include "art_method-inl.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080024#include "base/logging.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070025#include "base/to_str.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070026#include "class_linker.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080027#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070028#include "dex_file-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070029#include "gc/space/space.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070030#include "java_vm_ext.h"
Andreas Gampe277ccbd2014-11-03 21:36:10 -080031#include "jni_internal.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 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700186 * Verify that the pointer value is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -0700187 */
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_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700203 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_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700273 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_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700294 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_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700347 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);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700402 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700403 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);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700421 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700422 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_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700465 ArtMethod* method = soa.DecodeMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700466 if (method == nullptr) {
467 AbortF("expected non-null constructor");
468 return false;
469 }
470 if (!method->IsConstructor() || method->IsStatic()) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700471 AbortF("expected a constructor but %s: %p", PrettyMethod(method).c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700472 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 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700615 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800616 * 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;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700828 ArtMethod* m = soa.DecodeMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700829 *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 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700944 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -0700945 *
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
Mathieu Chartiere401d142015-04-22 13:56:20 -07001001 ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
Ian Rogers68d8b422014-07-17 11:09:10 -07001002 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 }
Mathieu Chartiere401d142015-04-22 13:56:20 -07001007 ArtMethod* m = soa.DecodeMethod(mid);
1008 // TODO: Better check here.
1009 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -07001010 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001011 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001012 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001013 }
1014 return m;
1015 }
1016
Ian Rogers68d8b422014-07-17 11:09:10 -07001017 bool CheckThread(JNIEnv* env) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001018 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001019 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001020 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1021 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001022 }
1023
1024 // Get the *correct* JNIEnv by going through our TLS pointer.
1025 JNIEnvExt* threadEnv = self->GetJniEnv();
1026
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001027 // Verify that the current thread is (a) attached and (b) associated with
1028 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001029 if (env != threadEnv) {
1030 AbortF("thread %s using JNIEnv* from thread %s",
1031 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*self).c_str());
1032 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001033 }
1034
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001035 // Verify that, if this thread previously made a critical "get" call, we
1036 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001037 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001038 case kFlag_CritOkay: // okay to call this method
1039 break;
1040 case kFlag_CritBad: // not okay to call
1041 if (threadEnv->critical) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001042 AbortF("thread %s using JNI after critical get",
1043 ToStr<Thread>(*self).c_str());
1044 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001045 }
1046 break;
1047 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001048 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -07001049 threadEnv->critical++;
1050 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001051 case kFlag_CritRelease: // this is a "release" call
Elliott Hughesa2501992011-08-26 19:39:54 -07001052 threadEnv->critical--;
1053 if (threadEnv->critical < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001054 AbortF("thread %s called too many critical releases",
1055 ToStr<Thread>(*self).c_str());
1056 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001057 }
1058 break;
1059 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001060 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001061 }
1062
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001063 // Verify that, if an exception has been raised, the native code doesn't
1064 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001065 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001066 mirror::Throwable* exception = self->GetException();
1067 AbortF("JNI %s called with pending exception %s",
1068 function_name_,
1069 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001070 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001071 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001072 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001073 }
1074
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001075 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001076 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001077 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001078 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001079 AbortF("non-nullable const char* was NULL");
1080 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001081 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001082 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001083 }
1084
Ian Rogersef7d42f2014-01-06 12:55:46 -08001085 const char* errorKind = nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001086 uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001087 if (errorKind != nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001088 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
1089 " string: '%s'", errorKind, utf8, bytes);
1090 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001091 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001092 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001093 }
1094
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001095 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1096 // sequences in place of encoded surrogate pairs.
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001097 static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001098 while (*bytes != '\0') {
1099 uint8_t utf8 = *(bytes++);
1100 // Switch on the high four bits.
1101 switch (utf8 >> 4) {
1102 case 0x00:
1103 case 0x01:
1104 case 0x02:
1105 case 0x03:
1106 case 0x04:
1107 case 0x05:
1108 case 0x06:
1109 case 0x07:
1110 // Bit pattern 0xxx. No need for any extra bytes.
1111 break;
1112 case 0x08:
1113 case 0x09:
1114 case 0x0a:
1115 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001116 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001117 *errorKind = "start";
1118 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001119 case 0x0f:
1120 // Bit pattern 1111, which might be the start of a 4 byte sequence.
1121 if ((utf8 & 0x08) == 0) {
1122 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1123 // We consume one continuation byte here, and fall through to consume two more.
1124 utf8 = *(bytes++);
1125 if ((utf8 & 0xc0) != 0x80) {
1126 *errorKind = "continuation";
1127 return utf8;
1128 }
1129 } else {
1130 *errorKind = "start";
1131 return utf8;
1132 }
1133
1134 // Fall through to the cases below to consume two more continuation bytes.
1135 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001136 case 0x0e:
1137 // Bit pattern 1110, so there are two additional bytes.
1138 utf8 = *(bytes++);
1139 if ((utf8 & 0xc0) != 0x80) {
1140 *errorKind = "continuation";
1141 return utf8;
1142 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001143
1144 // Fall through to consume one more continuation byte.
1145 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001146 case 0x0c:
1147 case 0x0d:
1148 // Bit pattern 110x, so there is one additional byte.
1149 utf8 = *(bytes++);
1150 if ((utf8 & 0xc0) != 0x80) {
1151 *errorKind = "continuation";
1152 return utf8;
1153 }
1154 break;
1155 }
1156 }
1157 return 0;
1158 }
1159
Ian Rogers68d8b422014-07-17 11:09:10 -07001160 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1161 va_list args;
1162 va_start(args, fmt);
1163 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1164 va_end(args);
1165 }
1166
1167 // The name of the JNI function being checked.
1168 const char* const function_name_;
1169
1170 const int flags_;
Elliott Hughes92cb4982011-12-16 16:57:28 -08001171 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001172
Ian Rogers68d8b422014-07-17 11:09:10 -07001173 const bool has_method_;
1174
Elliott Hughesa2501992011-08-26 19:39:54 -07001175 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1176};
1177
Elliott Hughesa2501992011-08-26 19:39:54 -07001178/*
1179 * ===========================================================================
1180 * Guarded arrays
1181 * ===========================================================================
1182 */
1183
Elliott Hughesa2501992011-08-26 19:39:54 -07001184/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001185class GuardedCopy {
1186 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001187 /*
1188 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1189 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001190 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001191 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001192 const size_t new_len = LengthIncludingRedZones(len);
1193 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001194
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001195 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001196 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001197 if (!mod_okay) {
1198 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001199 }
1200
Ian Rogers68d8b422014-07-17 11:09:10 -07001201 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001202
Ian Rogers68d8b422014-07-17 11:09:10 -07001203 // Fill begin region with canary pattern.
1204 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1205 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1206 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1207 if (kCanary[j] == '\0') {
1208 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001209 } else {
1210 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001211 }
1212 }
1213
1214 // Copy the data in; note "len" could be zero.
1215 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1216
1217 // Fill end region with canary pattern.
1218 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1219 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1220 if (kCanary[j] == '\0') {
1221 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001222 } else {
1223 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001224 }
1225 }
1226
1227 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001228 }
1229
1230 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001231 * Create a guarded copy of a primitive array. Modifications to the copied
1232 * data are allowed. Returns a pointer to the copied data.
1233 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001234 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1235 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001236 ScopedObjectAccess soa(env);
1237
1238 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1239 size_t component_size = a->GetClass()->GetComponentSize();
1240 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001241 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001242 if (is_copy != nullptr) {
1243 *is_copy = JNI_TRUE;
1244 }
1245 return result;
1246 }
1247
1248 /*
1249 * Perform the array "release" operation, which may or may not copy data
1250 * back into the managed heap, and may or may not release the underlying storage.
1251 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001252 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1253 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1254 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001255 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001256 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1257 return nullptr;
1258 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001259 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1260 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001261 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001262 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001263 }
1264 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001265 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001266 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001267 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001268 }
1269
1270
1271 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001272 * Free up the guard buffer, scrub it, and return the original pointer.
1273 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001274 static void* Destroy(void* embedded_buf) {
1275 GuardedCopy* copy = FromEmbedded(embedded_buf);
1276 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1277 size_t len = LengthIncludingRedZones(copy->original_length_);
1278 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001279 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001280 }
1281
1282 /*
1283 * Verify the guard area and, if "modOkay" is false, that the data itself
1284 * has not been altered.
1285 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001286 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001287 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001288 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1289 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1290 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001291 }
1292
1293 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001294 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001295 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1296 }
1297
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001298 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001299 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001300 if (result == MAP_FAILED) {
1301 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1302 }
1303 return reinterpret_cast<uint8_t*>(result);
1304 }
1305
Ian Rogers68d8b422014-07-17 11:09:10 -07001306 static void DebugFree(void* buf, size_t len) {
1307 if (munmap(buf, len) != 0) {
1308 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001309 }
1310 }
1311
Ian Rogers68d8b422014-07-17 11:09:10 -07001312 static size_t LengthIncludingRedZones(size_t len) {
1313 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001314 }
1315
Ian Rogers68d8b422014-07-17 11:09:10 -07001316 // Get the GuardedCopy from the interior pointer.
1317 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1318 return reinterpret_cast<GuardedCopy*>(
1319 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001320 }
1321
Ian Rogers68d8b422014-07-17 11:09:10 -07001322 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1323 return reinterpret_cast<const GuardedCopy*>(
1324 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001325 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001326
1327 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1328 va_list args;
1329 va_start(args, fmt);
1330 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1331 va_end(args);
1332 }
1333
1334 bool CheckHeader(const char* function_name, bool mod_okay) const {
1335 static const uint32_t kMagicCmp = kGuardMagic;
1336
1337 // Before we do anything with "pExtra", check the magic number. We
1338 // do the check with memcmp rather than "==" in case the pointer is
1339 // unaligned. If it points to completely bogus memory we're going
1340 // to crash, but there's no easy way around that.
1341 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1342 uint8_t buf[4];
1343 memcpy(buf, &magic_, 4);
1344 AbortF(function_name,
1345 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1346 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1347 return false;
1348 }
1349
1350 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1351 // told the client that we made a copy, there's no reason they can't alter the buffer.
1352 if (!mod_okay) {
1353 uLong computed_adler =
1354 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1355 if (computed_adler != adler_) {
1356 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1357 computed_adler, adler_, this);
1358 return false;
1359 }
1360 }
1361 return true;
1362 }
1363
1364 bool CheckRedZones(const char* function_name) const {
1365 // Check the begin red zone.
1366 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1367 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1368 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1369 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1370 return false;
1371 }
1372 if (kCanary[j] == '\0') {
1373 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001374 } else {
1375 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001376 }
1377 }
1378
1379 // Check end region.
1380 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1381 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1382 size_t offset_from_buffer_start =
1383 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1384 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1385 offset_from_buffer_start);
1386 return false;
1387 }
1388 if (kCanary[j] == '\0') {
1389 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001390 } else {
1391 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001392 }
1393 }
1394 return true;
1395 }
1396
1397 // Location that canary value will be written before the guarded region.
1398 const char* StartRedZone() const {
1399 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1400 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1401 }
1402
1403 // Return the interior embedded buffer.
1404 const uint8_t* BufferWithinRedZones() const {
1405 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1406 return embedded_buf;
1407 }
1408
1409 // Location that canary value will be written after the guarded region.
1410 const char* EndRedZone() const {
1411 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1412 size_t buf_len = LengthIncludingRedZones(original_length_);
1413 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1414 }
1415
1416 static constexpr size_t kRedZoneSize = 512;
1417 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1418
1419 // Value written before and after the guarded array.
1420 static const char* const kCanary;
1421
1422 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1423
1424 const uint32_t magic_;
1425 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001426 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001427 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001428};
Ian Rogers68d8b422014-07-17 11:09:10 -07001429const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001430
1431/*
1432 * ===========================================================================
1433 * JNI functions
1434 * ===========================================================================
1435 */
1436
1437class CheckJNI {
1438 public:
1439 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001440 ScopedObjectAccess soa(env);
1441 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1442 JniValueType args[1] = {{.E = env }};
1443 if (sc.Check(soa, true, "E", args)) {
1444 JniValueType result;
1445 result.I = baseEnv(env)->GetVersion(env);
1446 if (sc.Check(soa, false, "I", &result)) {
1447 return result.I;
1448 }
1449 }
1450 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001451 }
1452
Ian Rogers68d8b422014-07-17 11:09:10 -07001453 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1454 ScopedObjectAccess soa(env);
1455 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1456 JniValueType args[2] = {{.E = env }, {.p = vm}};
1457 if (sc.Check(soa, true, "Ep", args)) {
1458 JniValueType result;
1459 result.i = baseEnv(env)->GetJavaVM(env, vm);
1460 if (sc.Check(soa, false, "i", &result)) {
1461 return result.i;
1462 }
1463 }
1464 return JNI_ERR;
1465 }
1466
1467 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1468 ScopedObjectAccess soa(env);
1469 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1470 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1471 if (sc.Check(soa, true, "EcpI", args)) {
1472 JniValueType result;
1473 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1474 if (sc.Check(soa, false, "i", &result)) {
1475 return result.i;
1476 }
1477 }
1478 return JNI_ERR;
1479 }
1480
1481 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1482 ScopedObjectAccess soa(env);
1483 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1484 JniValueType args[2] = {{.E = env }, {.c = c}};
1485 if (sc.Check(soa, true, "Ec", args)) {
1486 JniValueType result;
1487 result.i = baseEnv(env)->UnregisterNatives(env, c);
1488 if (sc.Check(soa, false, "i", &result)) {
1489 return result.i;
1490 }
1491 }
1492 return JNI_ERR;
1493 }
1494
1495 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001496 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1497 // know the object is invalid. The spec says that passing invalid objects or even ones that
1498 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001499 ScopedObjectAccess soa(env);
1500 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001501 JniValueType args[2] = {{.E = env }, {.L = obj}};
1502 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001503 JniValueType result;
1504 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1505 if (sc.Check(soa, false, "w", &result)) {
1506 return result.w;
1507 }
1508 }
1509 return JNIInvalidRefType;
1510 }
1511
1512 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1513 jsize bufLen) {
1514 ScopedObjectAccess soa(env);
1515 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1516 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1517 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1518 JniValueType result;
1519 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1520 if (sc.Check(soa, false, "c", &result)) {
1521 return result.c;
1522 }
1523 }
1524 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001525 }
1526
1527 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001528 ScopedObjectAccess soa(env);
1529 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1530 JniValueType args[2] = {{.E = env}, {.u = name}};
1531 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1532 JniValueType result;
1533 result.c = baseEnv(env)->FindClass(env, name);
1534 if (sc.Check(soa, false, "c", &result)) {
1535 return result.c;
1536 }
1537 }
1538 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001539 }
1540
Elliott Hughese84278b2012-03-22 10:06:53 -07001541 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001542 ScopedObjectAccess soa(env);
1543 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1544 JniValueType args[2] = {{.E = env}, {.c = c}};
1545 if (sc.Check(soa, true, "Ec", args)) {
1546 JniValueType result;
1547 result.c = baseEnv(env)->GetSuperclass(env, c);
1548 if (sc.Check(soa, false, "c", &result)) {
1549 return result.c;
1550 }
1551 }
1552 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001553 }
1554
Elliott Hughese84278b2012-03-22 10:06:53 -07001555 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001556 ScopedObjectAccess soa(env);
1557 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1558 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1559 if (sc.Check(soa, true, "Ecc", args)) {
1560 JniValueType result;
1561 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1562 if (sc.Check(soa, false, "b", &result)) {
1563 return result.b;
1564 }
1565 }
1566 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001567 }
1568
1569 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001570 ScopedObjectAccess soa(env);
1571 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1572 JniValueType args[2] = {{.E = env}, {.L = method}};
1573 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1574 JniValueType result;
1575 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1576 if (sc.Check(soa, false, "m", &result)) {
1577 return result.m;
1578 }
1579 }
1580 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001581 }
1582
1583 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001584 ScopedObjectAccess soa(env);
1585 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1586 JniValueType args[2] = {{.E = env}, {.L = field}};
1587 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1588 JniValueType result;
1589 result.f = baseEnv(env)->FromReflectedField(env, field);
1590 if (sc.Check(soa, false, "f", &result)) {
1591 return result.f;
1592 }
1593 }
1594 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001595 }
1596
1597 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001598 ScopedObjectAccess soa(env);
1599 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1600 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1601 if (sc.Check(soa, true, "Ecmb", args)) {
1602 JniValueType result;
1603 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1604 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1605 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1606 return result.L;
1607 }
1608 }
1609 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001610 }
1611
1612 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001613 ScopedObjectAccess soa(env);
1614 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1615 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1616 if (sc.Check(soa, true, "Ecfb", args)) {
1617 JniValueType result;
1618 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1619 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1620 DCHECK(sc.CheckReflectedField(soa, result.L));
1621 return result.L;
1622 }
1623 }
1624 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001625 }
1626
1627 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001628 ScopedObjectAccess soa(env);
1629 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1630 JniValueType args[2] = {{.E = env}, {.t = obj}};
1631 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1632 JniValueType result;
1633 result.i = baseEnv(env)->Throw(env, obj);
1634 if (sc.Check(soa, false, "i", &result)) {
1635 return result.i;
1636 }
1637 }
1638 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001639 }
1640
Elliott Hughese84278b2012-03-22 10:06:53 -07001641 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001642 ScopedObjectAccess soa(env);
1643 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001644 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001645 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1646 JniValueType result;
1647 result.i = baseEnv(env)->ThrowNew(env, c, message);
1648 if (sc.Check(soa, false, "i", &result)) {
1649 return result.i;
1650 }
1651 }
1652 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001653 }
1654
1655 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001656 ScopedObjectAccess soa(env);
1657 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1658 JniValueType args[1] = {{.E = env}};
1659 if (sc.Check(soa, true, "E", args)) {
1660 JniValueType result;
1661 result.t = baseEnv(env)->ExceptionOccurred(env);
1662 if (sc.Check(soa, false, "t", &result)) {
1663 return result.t;
1664 }
1665 }
1666 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001667 }
1668
1669 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001670 ScopedObjectAccess soa(env);
1671 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1672 JniValueType args[1] = {{.E = env}};
1673 if (sc.Check(soa, true, "E", args)) {
1674 JniValueType result;
1675 baseEnv(env)->ExceptionDescribe(env);
1676 result.V = nullptr;
1677 sc.Check(soa, false, "V", &result);
1678 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001679 }
1680
1681 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001682 ScopedObjectAccess soa(env);
1683 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1684 JniValueType args[1] = {{.E = env}};
1685 if (sc.Check(soa, true, "E", args)) {
1686 JniValueType result;
1687 baseEnv(env)->ExceptionClear(env);
1688 result.V = nullptr;
1689 sc.Check(soa, false, "V", &result);
1690 }
1691 }
1692
1693 static jboolean ExceptionCheck(JNIEnv* env) {
1694 ScopedObjectAccess soa(env);
1695 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1696 JniValueType args[1] = {{.E = env}};
1697 if (sc.Check(soa, true, "E", args)) {
1698 JniValueType result;
1699 result.b = baseEnv(env)->ExceptionCheck(env);
1700 if (sc.Check(soa, false, "b", &result)) {
1701 return result.b;
1702 }
1703 }
1704 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001705 }
1706
1707 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001708 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1709 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1710 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001711 ScopedObjectAccess soa(env);
1712 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1713 JniValueType args[2] = {{.E = env}, {.u = msg}};
1714 if (sc.Check(soa, true, "Eu", args)) {
1715 JniValueType result;
1716 baseEnv(env)->FatalError(env, msg);
1717 // Unreachable.
1718 result.V = nullptr;
1719 sc.Check(soa, false, "V", &result);
1720 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001721 }
1722
1723 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001724 ScopedObjectAccess soa(env);
1725 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1726 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1727 if (sc.Check(soa, true, "EI", args)) {
1728 JniValueType result;
1729 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1730 if (sc.Check(soa, false, "i", &result)) {
1731 return result.i;
1732 }
1733 }
1734 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001735 }
1736
1737 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001738 ScopedObjectAccess soa(env);
1739 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1740 JniValueType args[2] = {{.E = env}, {.L = res}};
1741 if (sc.Check(soa, true, "EL", args)) {
1742 JniValueType result;
1743 result.L = baseEnv(env)->PopLocalFrame(env, res);
1744 sc.Check(soa, false, "L", &result);
1745 return result.L;
1746 }
1747 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001748 }
1749
1750 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001751 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001752 }
1753
Ian Rogers68d8b422014-07-17 11:09:10 -07001754 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1755 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001756 }
1757
1758 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001759 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001760 }
1761
Ian Rogers68d8b422014-07-17 11:09:10 -07001762 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1763 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001764 }
1765
Ian Rogers68d8b422014-07-17 11:09:10 -07001766 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1767 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1768 }
1769
1770 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1771 DeleteRef(__FUNCTION__, env, obj, kLocal);
1772 }
1773
1774 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1775 ScopedObjectAccess soa(env);
1776 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1777 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1778 if (sc.Check(soa, true, "EI", args)) {
1779 JniValueType result;
1780 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1781 if (sc.Check(soa, false, "i", &result)) {
1782 return result.i;
1783 }
1784 }
1785 return JNI_ERR;
1786 }
1787
1788 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1789 ScopedObjectAccess soa(env);
1790 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1791 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1792 if (sc.Check(soa, true, "ELL", args)) {
1793 JniValueType result;
1794 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1795 if (sc.Check(soa, false, "b", &result)) {
1796 return result.b;
1797 }
1798 }
1799 return JNI_FALSE;
1800 }
1801
1802 static jobject AllocObject(JNIEnv* env, jclass c) {
1803 ScopedObjectAccess soa(env);
1804 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1805 JniValueType args[2] = {{.E = env}, {.c = c}};
1806 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1807 JniValueType result;
1808 result.L = baseEnv(env)->AllocObject(env, c);
1809 if (sc.Check(soa, false, "L", &result)) {
1810 return result.L;
1811 }
1812 }
1813 return nullptr;
1814 }
1815
1816 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1817 ScopedObjectAccess soa(env);
1818 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1819 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001820 if (sc.Check(soa, true, "Ecm", args) && sc.CheckInstantiableNonArray(soa, c) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07001821 sc.CheckConstructor(soa, mid)) {
1822 JniValueType result;
1823 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
1824 if (sc.Check(soa, false, "L", &result)) {
1825 return result.L;
1826 }
1827 }
1828 return nullptr;
1829 }
1830
1831 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1832 va_list args;
1833 va_start(args, mid);
1834 jobject result = NewObjectV(env, c, mid, args);
1835 va_end(args);
1836 return result;
1837 }
1838
1839 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
1840 ScopedObjectAccess soa(env);
1841 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1842 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001843 if (sc.Check(soa, true, "Ecm", args) && sc.CheckInstantiableNonArray(soa, c) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07001844 sc.CheckConstructor(soa, mid)) {
1845 JniValueType result;
1846 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
1847 if (sc.Check(soa, false, "L", &result)) {
1848 return result.L;
1849 }
1850 }
1851 return nullptr;
1852 }
1853
1854 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1855 ScopedObjectAccess soa(env);
1856 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1857 JniValueType args[2] = {{.E = env}, {.L = obj}};
1858 if (sc.Check(soa, true, "EL", args)) {
1859 JniValueType result;
1860 result.c = baseEnv(env)->GetObjectClass(env, obj);
1861 if (sc.Check(soa, false, "c", &result)) {
1862 return result.c;
1863 }
1864 }
1865 return nullptr;
1866 }
1867
1868 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
1869 ScopedObjectAccess soa(env);
1870 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1871 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
1872 if (sc.Check(soa, true, "ELc", args)) {
1873 JniValueType result;
1874 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
1875 if (sc.Check(soa, false, "b", &result)) {
1876 return result.b;
1877 }
1878 }
1879 return JNI_FALSE;
1880 }
1881
1882 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1883 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
1884 }
1885
1886 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1887 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
1888 }
1889
1890 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1891 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
1892 }
1893
1894 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1895 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
1896 }
1897
1898#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
1899 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
1900 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
1901 } \
1902 \
1903 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1904 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
1905 } \
1906 \
1907 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
1908 JniValueType value; \
1909 value.shorty = v; \
1910 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
1911 } \
1912 \
1913 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
1914 JniValueType value; \
1915 value.shorty = v; \
1916 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
1917 }
1918
1919 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
1920 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
1921 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
1922 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
1923 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
1924 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
1925 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
1926 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
1927 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
1928#undef FIELD_ACCESSORS
1929
1930 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
1931 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1932 }
1933
1934 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
1935 jvalue* vargs) {
1936 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1937 }
1938
1939 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01001940 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07001941 }
1942
1943 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
1944 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1945 }
1946
1947 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
1948 va_list vargs) {
1949 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1950 }
1951
1952 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1953 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
1954 }
1955
1956 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1957 va_list vargs;
1958 va_start(vargs, mid);
1959 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1960 va_end(vargs);
1961 }
1962
1963 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
1964 va_list vargs;
1965 va_start(vargs, mid);
1966 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1967 va_end(vargs);
1968 }
1969
1970 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
1971 va_list vargs;
1972 va_start(vargs, mid);
1973 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
1974 va_end(vargs);
1975 }
1976
1977#define CALL(rtype, name, ptype, shorty) \
1978 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
1979 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1980 } \
1981 \
1982 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1983 jvalue* vargs) { \
1984 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1985 } \
1986 \
1987 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
1988 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
1989 } \
1990 \
1991 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
1992 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1993 } \
1994 \
1995 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1996 va_list vargs) { \
1997 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1998 } \
1999 \
2000 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2001 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2002 } \
2003 \
2004 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2005 va_list vargs; \
2006 va_start(vargs, mid); \
2007 rtype result = \
2008 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2009 va_end(vargs); \
2010 return result; \
2011 } \
2012 \
2013 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2014 ...) { \
2015 va_list vargs; \
2016 va_start(vargs, mid); \
2017 rtype result = \
2018 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2019 va_end(vargs); \
2020 return result; \
2021 } \
2022 \
2023 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2024 va_list vargs; \
2025 va_start(vargs, mid); \
2026 rtype result = \
2027 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2028 va_end(vargs); \
2029 return result; \
2030 }
2031
2032 CALL(jobject, Object, Primitive::kPrimNot, L)
2033 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2034 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2035 CALL(jchar, Char, Primitive::kPrimChar, C)
2036 CALL(jshort, Short, Primitive::kPrimShort, S)
2037 CALL(jint, Int, Primitive::kPrimInt, I)
2038 CALL(jlong, Long, Primitive::kPrimLong, J)
2039 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2040 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2041#undef CALL
2042
2043 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2044 ScopedObjectAccess soa(env);
2045 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2046 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2047 if (sc.Check(soa, true, "Epz", args)) {
2048 JniValueType result;
2049 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2050 if (sc.Check(soa, false, "s", &result)) {
2051 return result.s;
2052 }
2053 }
2054 return nullptr;
2055 }
2056
2057 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2058 ScopedObjectAccess soa(env);
2059 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2060 JniValueType args[2] = {{.E = env}, {.u = chars}};
2061 if (sc.Check(soa, true, "Eu", args)) {
2062 JniValueType result;
2063 // TODO: stale? show pointer and truncate string.
2064 result.s = baseEnv(env)->NewStringUTF(env, chars);
2065 if (sc.Check(soa, false, "s", &result)) {
2066 return result.s;
2067 }
2068 }
2069 return nullptr;
2070 }
2071
2072 static jsize GetStringLength(JNIEnv* env, jstring string) {
2073 ScopedObjectAccess soa(env);
2074 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2075 JniValueType args[2] = {{.E = env}, {.s = string}};
2076 if (sc.Check(soa, true, "Es", args)) {
2077 JniValueType result;
2078 result.z = baseEnv(env)->GetStringLength(env, string);
2079 if (sc.Check(soa, false, "z", &result)) {
2080 return result.z;
2081 }
2082 }
2083 return JNI_ERR;
2084 }
2085
2086 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2087 ScopedObjectAccess soa(env);
2088 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2089 JniValueType args[2] = {{.E = env}, {.s = string}};
2090 if (sc.Check(soa, true, "Es", args)) {
2091 JniValueType result;
2092 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2093 if (sc.Check(soa, false, "z", &result)) {
2094 return result.z;
2095 }
2096 }
2097 return JNI_ERR;
2098 }
2099
2100 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2101 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2102 is_copy, false, false));
2103 }
2104
2105 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2106 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2107 is_copy, true, false));
2108 }
2109
2110 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2111 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2112 is_copy, false, true));
2113 }
2114
2115 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2116 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2117 }
2118
2119 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2120 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2121 }
2122
2123 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2124 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2125 }
2126
2127 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2128 ScopedObjectAccess soa(env);
2129 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2130 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2131 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2132 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2133 if (sc.Check(soa, true, "EsIIp", args)) {
2134 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2135 JniValueType result;
2136 result.V = nullptr;
2137 sc.Check(soa, false, "V", &result);
2138 }
2139 }
2140
2141 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2142 ScopedObjectAccess soa(env);
2143 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2144 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2145 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2146 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2147 if (sc.Check(soa, true, "EsIIp", args)) {
2148 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2149 JniValueType result;
2150 result.V = nullptr;
2151 sc.Check(soa, false, "V", &result);
2152 }
2153 }
2154
2155 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2156 ScopedObjectAccess soa(env);
2157 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2158 JniValueType args[2] = {{.E = env}, {.a = array}};
2159 if (sc.Check(soa, true, "Ea", args)) {
2160 JniValueType result;
2161 result.z = baseEnv(env)->GetArrayLength(env, array);
2162 if (sc.Check(soa, false, "z", &result)) {
2163 return result.z;
2164 }
2165 }
2166 return JNI_ERR;
2167 }
2168
2169 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2170 jobject initial_element) {
2171 ScopedObjectAccess soa(env);
2172 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2173 JniValueType args[4] =
2174 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2175 if (sc.Check(soa, true, "EzcL", args)) {
2176 JniValueType result;
2177 // Note: assignability tests of initial_element are done in the base implementation.
2178 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2179 if (sc.Check(soa, false, "a", &result)) {
2180 return down_cast<jobjectArray>(result.a);
2181 }
2182 }
2183 return nullptr;
2184 }
2185
2186 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2187 ScopedObjectAccess soa(env);
2188 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2189 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2190 if (sc.Check(soa, true, "Eaz", args)) {
2191 JniValueType result;
2192 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2193 if (sc.Check(soa, false, "L", &result)) {
2194 return result.L;
2195 }
2196 }
2197 return nullptr;
2198 }
2199
2200 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2201 ScopedObjectAccess soa(env);
2202 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2203 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2204 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2205 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2206 // in ArrayStoreExceptions.
2207 if (sc.Check(soa, true, "EaIL", args)) {
2208 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2209 JniValueType result;
2210 result.V = nullptr;
2211 sc.Check(soa, false, "V", &result);
2212 }
2213 }
2214
2215 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2216 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2217 Primitive::kPrimBoolean));
2218 }
2219
2220 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2221 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2222 Primitive::kPrimByte));
2223 }
2224
2225 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2226 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2227 Primitive::kPrimChar));
2228 }
2229
2230 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2231 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2232 Primitive::kPrimShort));
2233 }
2234
2235 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2236 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2237 }
2238
2239 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2240 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2241 Primitive::kPrimLong));
2242 }
2243
2244 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2245 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2246 Primitive::kPrimFloat));
2247 }
2248
2249 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2250 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2251 Primitive::kPrimDouble));
2252 }
2253
2254#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
2255 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { \
2256 return reinterpret_cast<ctype*>( \
2257 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2258 } \
2259 \
2260 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, \
2261 jint mode) { \
2262 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2263 } \
2264 \
2265 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2266 ctype* buf) { \
2267 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2268 } \
2269 \
2270 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2271 const ctype* buf) { \
2272 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2273 }
2274
2275 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2276 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2277 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2278 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2279 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2280 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2281 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2282 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2283#undef PRIMITIVE_ARRAY_FUNCTIONS
2284
2285 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2286 ScopedObjectAccess soa(env);
2287 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2288 JniValueType args[2] = {{.E = env}, {.L = obj}};
2289 if (sc.Check(soa, true, "EL", args)) {
2290 JniValueType result;
2291 result.i = baseEnv(env)->MonitorEnter(env, obj);
2292 if (sc.Check(soa, false, "i", &result)) {
2293 return result.i;
2294 }
2295 }
2296 return JNI_ERR;
2297 }
2298
2299 static jint MonitorExit(JNIEnv* env, jobject obj) {
2300 ScopedObjectAccess soa(env);
2301 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2302 JniValueType args[2] = {{.E = env}, {.L = obj}};
2303 if (sc.Check(soa, true, "EL", args)) {
2304 JniValueType result;
2305 result.i = baseEnv(env)->MonitorExit(env, obj);
2306 if (sc.Check(soa, false, "i", &result)) {
2307 return result.i;
2308 }
2309 }
2310 return JNI_ERR;
2311 }
2312
2313 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2314 ScopedObjectAccess soa(env);
2315 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2316 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2317 if (sc.Check(soa, true, "Eap", args)) {
2318 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002319 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2320 if (ptr != nullptr && soa.ForceCopy()) {
2321 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002322 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002323 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002324 if (sc.Check(soa, false, "p", &result)) {
2325 return const_cast<void*>(result.p);
2326 }
2327 }
2328 return nullptr;
2329 }
2330
2331 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2332 ScopedObjectAccess soa(env);
2333 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2334 sc.CheckNonNull(carray);
2335 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2336 if (sc.Check(soa, true, "Eapr", args)) {
2337 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002338 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002339 }
2340 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2341 JniValueType result;
2342 result.V = nullptr;
2343 sc.Check(soa, false, "V", &result);
2344 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002345 }
2346
2347 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002348 ScopedObjectAccess soa(env);
2349 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2350 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2351 if (sc.Check(soa, true, "EpJ", args)) {
2352 JniValueType result;
2353 // Note: the validity of address and capacity are checked in the base implementation.
2354 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2355 if (sc.Check(soa, false, "L", &result)) {
2356 return result.L;
2357 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002358 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002359 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002360 }
2361
2362 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002363 ScopedObjectAccess soa(env);
2364 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2365 JniValueType args[2] = {{.E = env}, {.L = buf}};
2366 if (sc.Check(soa, true, "EL", args)) {
2367 JniValueType result;
2368 // Note: this is implemented in the base environment by a GetLongField which will sanity
2369 // check the type of buf in GetLongField above.
2370 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2371 if (sc.Check(soa, false, "p", &result)) {
2372 return const_cast<void*>(result.p);
2373 }
2374 }
2375 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002376 }
2377
2378 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002379 ScopedObjectAccess soa(env);
2380 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2381 JniValueType args[2] = {{.E = env}, {.L = buf}};
2382 if (sc.Check(soa, true, "EL", args)) {
2383 JniValueType result;
2384 // Note: this is implemented in the base environment by a GetIntField which will sanity
2385 // check the type of buf in GetIntField above.
2386 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2387 if (sc.Check(soa, false, "J", &result)) {
2388 return result.J;
2389 }
2390 }
2391 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002392 }
2393
2394 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002395 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2396 return reinterpret_cast<JNIEnvExt*>(env)->vm;
2397 }
2398
2399 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002400 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2401 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002402
2403 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2404 ScopedObjectAccess soa(env);
2405 ScopedCheck sc(kFlag_Default, function_name);
2406 JniValueType args[2] = {{.E = env}, {.L = obj}};
2407 if (sc.Check(soa, true, "EL", args)) {
2408 JniValueType result;
2409 switch (kind) {
2410 case kGlobal:
2411 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2412 break;
2413 case kLocal:
2414 result.L = baseEnv(env)->NewLocalRef(env, obj);
2415 break;
2416 case kWeakGlobal:
2417 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2418 break;
2419 default:
2420 LOG(FATAL) << "Unexpected reference kind: " << kind;
2421 }
2422 if (sc.Check(soa, false, "L", &result)) {
2423 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002424 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002425 return result.L;
2426 }
2427 }
2428 return nullptr;
2429 }
2430
2431 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2432 ScopedObjectAccess soa(env);
2433 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2434 JniValueType args[2] = {{.E = env}, {.L = obj}};
2435 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002436 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002437 JniValueType result;
2438 switch (kind) {
2439 case kGlobal:
2440 baseEnv(env)->DeleteGlobalRef(env, obj);
2441 break;
2442 case kLocal:
2443 baseEnv(env)->DeleteLocalRef(env, obj);
2444 break;
2445 case kWeakGlobal:
2446 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2447 break;
2448 default:
2449 LOG(FATAL) << "Unexpected reference kind: " << kind;
2450 }
2451 result.V = nullptr;
2452 sc.Check(soa, false, "V", &result);
2453 }
2454 }
2455
2456 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2457 const char* name, const char* sig, bool is_static) {
2458 ScopedObjectAccess soa(env);
2459 ScopedCheck sc(kFlag_Default, function_name);
2460 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2461 if (sc.Check(soa, true, "Ecuu", args)) {
2462 JniValueType result;
2463 if (is_static) {
2464 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2465 } else {
2466 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2467 }
2468 if (sc.Check(soa, false, "m", &result)) {
2469 return result.m;
2470 }
2471 }
2472 return nullptr;
2473 }
2474
2475 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2476 const char* name, const char* sig, bool is_static) {
2477 ScopedObjectAccess soa(env);
2478 ScopedCheck sc(kFlag_Default, function_name);
2479 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2480 if (sc.Check(soa, true, "Ecuu", args)) {
2481 JniValueType result;
2482 if (is_static) {
2483 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2484 } else {
2485 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2486 }
2487 if (sc.Check(soa, false, "f", &result)) {
2488 return result.f;
2489 }
2490 }
2491 return nullptr;
2492 }
2493
2494 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2495 bool is_static, Primitive::Type type) {
2496 ScopedObjectAccess soa(env);
2497 ScopedCheck sc(kFlag_Default, function_name);
2498 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2499 JniValueType result;
2500 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2501 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2502 const char* result_check = nullptr;
2503 switch (type) {
2504 case Primitive::kPrimNot:
2505 if (is_static) {
2506 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2507 } else {
2508 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2509 }
2510 result_check = "L";
2511 break;
2512 case Primitive::kPrimBoolean:
2513 if (is_static) {
2514 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2515 } else {
2516 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2517 }
2518 result_check = "Z";
2519 break;
2520 case Primitive::kPrimByte:
2521 if (is_static) {
2522 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2523 } else {
2524 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2525 }
2526 result_check = "B";
2527 break;
2528 case Primitive::kPrimChar:
2529 if (is_static) {
2530 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2531 } else {
2532 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2533 }
2534 result_check = "C";
2535 break;
2536 case Primitive::kPrimShort:
2537 if (is_static) {
2538 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2539 } else {
2540 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2541 }
2542 result_check = "S";
2543 break;
2544 case Primitive::kPrimInt:
2545 if (is_static) {
2546 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2547 } else {
2548 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2549 }
2550 result_check = "I";
2551 break;
2552 case Primitive::kPrimLong:
2553 if (is_static) {
2554 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2555 } else {
2556 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2557 }
2558 result_check = "J";
2559 break;
2560 case Primitive::kPrimFloat:
2561 if (is_static) {
2562 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2563 } else {
2564 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2565 }
2566 result_check = "F";
2567 break;
2568 case Primitive::kPrimDouble:
2569 if (is_static) {
2570 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2571 } else {
2572 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2573 }
2574 result_check = "D";
2575 break;
2576 case Primitive::kPrimVoid:
2577 LOG(FATAL) << "Unexpected type: " << type;
2578 break;
2579 }
2580 if (sc.Check(soa, false, result_check, &result)) {
2581 return result;
2582 }
2583 }
2584 result.J = 0;
2585 return result;
2586 }
2587
2588 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2589 bool is_static, Primitive::Type type, JniValueType value) {
2590 ScopedObjectAccess soa(env);
2591 ScopedCheck sc(kFlag_Default, function_name);
2592 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2593 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2594 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2595 if (sc.Check(soa, true, sig, args) &&
2596 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2597 switch (type) {
2598 case Primitive::kPrimNot:
2599 if (is_static) {
2600 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2601 } else {
2602 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2603 }
2604 break;
2605 case Primitive::kPrimBoolean:
2606 if (is_static) {
2607 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2608 } else {
2609 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2610 }
2611 break;
2612 case Primitive::kPrimByte:
2613 if (is_static) {
2614 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2615 } else {
2616 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2617 }
2618 break;
2619 case Primitive::kPrimChar:
2620 if (is_static) {
2621 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2622 } else {
2623 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2624 }
2625 break;
2626 case Primitive::kPrimShort:
2627 if (is_static) {
2628 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2629 } else {
2630 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2631 }
2632 break;
2633 case Primitive::kPrimInt:
2634 if (is_static) {
2635 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2636 } else {
2637 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2638 }
2639 break;
2640 case Primitive::kPrimLong:
2641 if (is_static) {
2642 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2643 } else {
2644 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2645 }
2646 break;
2647 case Primitive::kPrimFloat:
2648 if (is_static) {
2649 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2650 } else {
2651 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2652 }
2653 break;
2654 case Primitive::kPrimDouble:
2655 if (is_static) {
2656 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2657 } else {
2658 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2659 }
2660 break;
2661 case Primitive::kPrimVoid:
2662 LOG(FATAL) << "Unexpected type: " << type;
2663 break;
2664 }
2665 JniValueType result;
2666 result.V = nullptr;
2667 sc.Check(soa, false, "V", &result);
2668 }
2669 }
2670
2671 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
2672 jclass c, jmethodID mid, InvokeType invoke)
2673 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2674 bool checked;
2675 switch (invoke) {
2676 case kVirtual: {
2677 DCHECK(c == nullptr);
2678 JniValueType args[3] = {{.E = env}, {.L = obj}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07002679 checked = sc.Check(soa, true, "ELm", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002680 break;
2681 }
2682 case kDirect: {
2683 JniValueType args[4] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07002684 checked = sc.Check(soa, true, "ELcm", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002685 break;
2686 }
2687 case kStatic: {
2688 DCHECK(obj == nullptr);
2689 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07002690 checked = sc.Check(soa, true, "Ecm", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002691 break;
2692 }
2693 default:
2694 LOG(FATAL) << "Unexpected invoke: " << invoke;
2695 checked = false;
2696 break;
2697 }
2698 return checked;
2699 }
2700
2701 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2702 jmethodID mid, jvalue* vargs, Primitive::Type type,
2703 InvokeType invoke) {
2704 ScopedObjectAccess soa(env);
2705 ScopedCheck sc(kFlag_Default, function_name);
2706 JniValueType result;
2707 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
2708 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2709 const char* result_check;
2710 switch (type) {
2711 case Primitive::kPrimNot:
2712 result_check = "L";
2713 switch (invoke) {
2714 case kVirtual:
2715 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2716 break;
2717 case kDirect:
2718 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2719 break;
2720 case kStatic:
2721 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2722 break;
2723 default:
2724 break;
2725 }
2726 break;
2727 case Primitive::kPrimBoolean:
2728 result_check = "Z";
2729 switch (invoke) {
2730 case kVirtual:
2731 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2732 break;
2733 case kDirect:
2734 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2735 break;
2736 case kStatic:
2737 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2738 break;
2739 default:
2740 break;
2741 }
2742 break;
2743 case Primitive::kPrimByte:
2744 result_check = "B";
2745 switch (invoke) {
2746 case kVirtual:
2747 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2748 break;
2749 case kDirect:
2750 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2751 break;
2752 case kStatic:
2753 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2754 break;
2755 default:
2756 break;
2757 }
2758 break;
2759 case Primitive::kPrimChar:
2760 result_check = "C";
2761 switch (invoke) {
2762 case kVirtual:
2763 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2764 break;
2765 case kDirect:
2766 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2767 break;
2768 case kStatic:
2769 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2770 break;
2771 default:
2772 break;
2773 }
2774 break;
2775 case Primitive::kPrimShort:
2776 result_check = "S";
2777 switch (invoke) {
2778 case kVirtual:
2779 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2780 break;
2781 case kDirect:
2782 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2783 break;
2784 case kStatic:
2785 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2786 break;
2787 default:
2788 break;
2789 }
2790 break;
2791 case Primitive::kPrimInt:
2792 result_check = "I";
2793 switch (invoke) {
2794 case kVirtual:
2795 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2796 break;
2797 case kDirect:
2798 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2799 break;
2800 case kStatic:
2801 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
2802 break;
2803 default:
2804 break;
2805 }
2806 break;
2807 case Primitive::kPrimLong:
2808 result_check = "J";
2809 switch (invoke) {
2810 case kVirtual:
2811 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
2812 break;
2813 case kDirect:
2814 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
2815 break;
2816 case kStatic:
2817 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
2818 break;
2819 default:
2820 break;
2821 }
2822 break;
2823 case Primitive::kPrimFloat:
2824 result_check = "F";
2825 switch (invoke) {
2826 case kVirtual:
2827 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
2828 break;
2829 case kDirect:
2830 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
2831 break;
2832 case kStatic:
2833 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
2834 break;
2835 default:
2836 break;
2837 }
2838 break;
2839 case Primitive::kPrimDouble:
2840 result_check = "D";
2841 switch (invoke) {
2842 case kVirtual:
2843 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
2844 break;
2845 case kDirect:
2846 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
2847 break;
2848 case kStatic:
2849 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
2850 break;
2851 default:
2852 break;
2853 }
2854 break;
2855 case Primitive::kPrimVoid:
2856 result_check = "V";
2857 result.V = nullptr;
2858 switch (invoke) {
2859 case kVirtual:
2860 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
2861 break;
2862 case kDirect:
2863 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
2864 break;
2865 case kStatic:
2866 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
2867 break;
2868 default:
2869 LOG(FATAL) << "Unexpected invoke: " << invoke;
2870 }
2871 break;
2872 default:
2873 LOG(FATAL) << "Unexpected return type: " << type;
2874 result_check = nullptr;
2875 }
2876 if (sc.Check(soa, false, result_check, &result)) {
2877 return result;
2878 }
2879 }
2880 result.J = 0;
2881 return result;
2882 }
2883
2884 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2885 jmethodID mid, va_list vargs, Primitive::Type type,
2886 InvokeType invoke) {
2887 ScopedObjectAccess soa(env);
2888 ScopedCheck sc(kFlag_Default, function_name);
2889 JniValueType result;
2890 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
2891 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2892 const char* result_check;
2893 switch (type) {
2894 case Primitive::kPrimNot:
2895 result_check = "L";
2896 switch (invoke) {
2897 case kVirtual:
2898 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
2899 break;
2900 case kDirect:
2901 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
2902 break;
2903 case kStatic:
2904 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
2905 break;
2906 default:
2907 LOG(FATAL) << "Unexpected invoke: " << invoke;
2908 }
2909 break;
2910 case Primitive::kPrimBoolean:
2911 result_check = "Z";
2912 switch (invoke) {
2913 case kVirtual:
2914 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
2915 break;
2916 case kDirect:
2917 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
2918 break;
2919 case kStatic:
2920 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
2921 break;
2922 default:
2923 LOG(FATAL) << "Unexpected invoke: " << invoke;
2924 }
2925 break;
2926 case Primitive::kPrimByte:
2927 result_check = "B";
2928 switch (invoke) {
2929 case kVirtual:
2930 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
2931 break;
2932 case kDirect:
2933 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
2934 break;
2935 case kStatic:
2936 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
2937 break;
2938 default:
2939 LOG(FATAL) << "Unexpected invoke: " << invoke;
2940 }
2941 break;
2942 case Primitive::kPrimChar:
2943 result_check = "C";
2944 switch (invoke) {
2945 case kVirtual:
2946 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
2947 break;
2948 case kDirect:
2949 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
2950 break;
2951 case kStatic:
2952 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
2953 break;
2954 default:
2955 LOG(FATAL) << "Unexpected invoke: " << invoke;
2956 }
2957 break;
2958 case Primitive::kPrimShort:
2959 result_check = "S";
2960 switch (invoke) {
2961 case kVirtual:
2962 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
2963 break;
2964 case kDirect:
2965 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
2966 break;
2967 case kStatic:
2968 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
2969 break;
2970 default:
2971 LOG(FATAL) << "Unexpected invoke: " << invoke;
2972 }
2973 break;
2974 case Primitive::kPrimInt:
2975 result_check = "I";
2976 switch (invoke) {
2977 case kVirtual:
2978 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
2979 break;
2980 case kDirect:
2981 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
2982 break;
2983 case kStatic:
2984 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
2985 break;
2986 default:
2987 LOG(FATAL) << "Unexpected invoke: " << invoke;
2988 }
2989 break;
2990 case Primitive::kPrimLong:
2991 result_check = "J";
2992 switch (invoke) {
2993 case kVirtual:
2994 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
2995 break;
2996 case kDirect:
2997 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
2998 break;
2999 case kStatic:
3000 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3001 break;
3002 default:
3003 LOG(FATAL) << "Unexpected invoke: " << invoke;
3004 }
3005 break;
3006 case Primitive::kPrimFloat:
3007 result_check = "F";
3008 switch (invoke) {
3009 case kVirtual:
3010 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3011 break;
3012 case kDirect:
3013 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3014 break;
3015 case kStatic:
3016 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3017 break;
3018 default:
3019 LOG(FATAL) << "Unexpected invoke: " << invoke;
3020 }
3021 break;
3022 case Primitive::kPrimDouble:
3023 result_check = "D";
3024 switch (invoke) {
3025 case kVirtual:
3026 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3027 break;
3028 case kDirect:
3029 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3030 break;
3031 case kStatic:
3032 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3033 break;
3034 default:
3035 LOG(FATAL) << "Unexpected invoke: " << invoke;
3036 }
3037 break;
3038 case Primitive::kPrimVoid:
3039 result_check = "V";
3040 result.V = nullptr;
3041 switch (invoke) {
3042 case kVirtual:
3043 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3044 break;
3045 case kDirect:
3046 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3047 break;
3048 case kStatic:
3049 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3050 break;
3051 default:
3052 LOG(FATAL) << "Unexpected invoke: " << invoke;
3053 }
3054 break;
3055 default:
3056 LOG(FATAL) << "Unexpected return type: " << type;
3057 result_check = nullptr;
3058 }
3059 if (sc.Check(soa, false, result_check, &result)) {
3060 return result;
3061 }
3062 }
3063 result.J = 0;
3064 return result;
3065 }
3066
3067 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3068 jboolean* is_copy, bool utf, bool critical) {
3069 ScopedObjectAccess soa(env);
3070 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3071 ScopedCheck sc(flags, function_name);
3072 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3073 if (sc.Check(soa, true, "Esp", args)) {
3074 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003075 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003076 if (utf) {
3077 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003078 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3079 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003080 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003081 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3082 baseEnv(env)->GetStringChars(env, string, is_copy));
3083 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003084 }
3085 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003086 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003087 if (utf) {
3088 size_t length_in_bytes = strlen(result.u) + 1;
3089 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003090 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003091 } else {
3092 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3093 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003094 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003095 }
3096 if (is_copy != nullptr) {
3097 *is_copy = JNI_TRUE;
3098 }
3099 }
3100 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3101 return utf ? result.u : result.p;
3102 }
3103 }
3104 return nullptr;
3105 }
3106
3107 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3108 const void* chars, bool utf, bool critical) {
3109 ScopedObjectAccess soa(env);
3110 int flags = kFlag_ExcepOkay | kFlag_Release;
3111 if (critical) {
3112 flags |= kFlag_CritRelease;
3113 }
3114 ScopedCheck sc(flags, function_name);
3115 sc.CheckNonNull(chars);
3116 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3117 if (force_copy_ok && soa.ForceCopy()) {
3118 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3119 }
3120 if (force_copy_ok) {
3121 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3122 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3123 if (utf) {
3124 CHECK(!critical);
3125 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3126 } else {
3127 if (critical) {
3128 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3129 } else {
3130 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3131 }
3132 }
3133 JniValueType result;
3134 sc.Check(soa, false, "V", &result);
3135 }
3136 }
3137 }
3138
3139 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3140 Primitive::Type type) {
3141 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003142 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003143 JniValueType args[2] = {{.E = env}, {.z = length}};
3144 if (sc.Check(soa, true, "Ez", args)) {
3145 JniValueType result;
3146 switch (type) {
3147 case Primitive::kPrimBoolean:
3148 result.a = baseEnv(env)->NewBooleanArray(env, length);
3149 break;
3150 case Primitive::kPrimByte:
3151 result.a = baseEnv(env)->NewByteArray(env, length);
3152 break;
3153 case Primitive::kPrimChar:
3154 result.a = baseEnv(env)->NewCharArray(env, length);
3155 break;
3156 case Primitive::kPrimShort:
3157 result.a = baseEnv(env)->NewShortArray(env, length);
3158 break;
3159 case Primitive::kPrimInt:
3160 result.a = baseEnv(env)->NewIntArray(env, length);
3161 break;
3162 case Primitive::kPrimLong:
3163 result.a = baseEnv(env)->NewLongArray(env, length);
3164 break;
3165 case Primitive::kPrimFloat:
3166 result.a = baseEnv(env)->NewFloatArray(env, length);
3167 break;
3168 case Primitive::kPrimDouble:
3169 result.a = baseEnv(env)->NewDoubleArray(env, length);
3170 break;
3171 default:
3172 LOG(FATAL) << "Unexpected primitive type: " << type;
3173 }
3174 if (sc.Check(soa, false, "a", &result)) {
3175 return result.a;
3176 }
3177 }
3178 return nullptr;
3179 }
3180
3181 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3182 JNIEnv* env, jarray array, jboolean* is_copy) {
3183 ScopedObjectAccess soa(env);
3184 ScopedCheck sc(kFlag_Default, function_name);
3185 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3186 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3187 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003188 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003189 switch (type) {
3190 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003191 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3192 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003193 break;
3194 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003195 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003196 break;
3197 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003198 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003199 break;
3200 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003201 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003202 break;
3203 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003204 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003205 break;
3206 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003207 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003208 break;
3209 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003210 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003211 break;
3212 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003213 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003214 break;
3215 default:
3216 LOG(FATAL) << "Unexpected primitive type: " << type;
3217 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003218 if (ptr != nullptr && soa.ForceCopy()) {
3219 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003220 if (is_copy != nullptr) {
3221 *is_copy = JNI_TRUE;
3222 }
3223 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003224 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003225 if (sc.Check(soa, false, "p", &result)) {
3226 return const_cast<void*>(result.p);
3227 }
3228 }
3229 return nullptr;
3230 }
3231
3232 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3233 JNIEnv* env, jarray array, void* elems, jint mode) {
3234 ScopedObjectAccess soa(env);
3235 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3236 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3237 if (soa.ForceCopy()) {
3238 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3239 }
3240 if (!soa.ForceCopy() || elems != nullptr) {
3241 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3242 if (sc.Check(soa, true, "Eapr", args)) {
3243 switch (type) {
3244 case Primitive::kPrimBoolean:
3245 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3246 reinterpret_cast<jboolean*>(elems), mode);
3247 break;
3248 case Primitive::kPrimByte:
3249 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3250 reinterpret_cast<jbyte*>(elems), mode);
3251 break;
3252 case Primitive::kPrimChar:
3253 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3254 reinterpret_cast<jchar*>(elems), mode);
3255 break;
3256 case Primitive::kPrimShort:
3257 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3258 reinterpret_cast<jshort*>(elems), mode);
3259 break;
3260 case Primitive::kPrimInt:
3261 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3262 reinterpret_cast<jint*>(elems), mode);
3263 break;
3264 case Primitive::kPrimLong:
3265 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3266 reinterpret_cast<jlong*>(elems), mode);
3267 break;
3268 case Primitive::kPrimFloat:
3269 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3270 reinterpret_cast<jfloat*>(elems), mode);
3271 break;
3272 case Primitive::kPrimDouble:
3273 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3274 reinterpret_cast<jdouble*>(elems), mode);
3275 break;
3276 default:
3277 LOG(FATAL) << "Unexpected primitive type: " << type;
3278 }
3279 JniValueType result;
3280 result.V = nullptr;
3281 sc.Check(soa, false, "V", &result);
3282 }
3283 }
3284 }
3285 }
3286
3287 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3288 jarray array, jsize start, jsize len, void* buf) {
3289 ScopedObjectAccess soa(env);
3290 ScopedCheck sc(kFlag_Default, function_name);
3291 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3292 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3293 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3294 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3295 switch (type) {
3296 case Primitive::kPrimBoolean:
3297 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3298 reinterpret_cast<jboolean*>(buf));
3299 break;
3300 case Primitive::kPrimByte:
3301 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3302 reinterpret_cast<jbyte*>(buf));
3303 break;
3304 case Primitive::kPrimChar:
3305 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3306 reinterpret_cast<jchar*>(buf));
3307 break;
3308 case Primitive::kPrimShort:
3309 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3310 reinterpret_cast<jshort*>(buf));
3311 break;
3312 case Primitive::kPrimInt:
3313 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3314 reinterpret_cast<jint*>(buf));
3315 break;
3316 case Primitive::kPrimLong:
3317 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3318 reinterpret_cast<jlong*>(buf));
3319 break;
3320 case Primitive::kPrimFloat:
3321 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3322 reinterpret_cast<jfloat*>(buf));
3323 break;
3324 case Primitive::kPrimDouble:
3325 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3326 reinterpret_cast<jdouble*>(buf));
3327 break;
3328 default:
3329 LOG(FATAL) << "Unexpected primitive type: " << type;
3330 }
3331 JniValueType result;
3332 result.V = nullptr;
3333 sc.Check(soa, false, "V", &result);
3334 }
3335 }
3336
3337 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3338 jarray array, jsize start, jsize len, const void* buf) {
3339 ScopedObjectAccess soa(env);
3340 ScopedCheck sc(kFlag_Default, function_name);
3341 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3342 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3343 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3344 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3345 switch (type) {
3346 case Primitive::kPrimBoolean:
3347 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3348 reinterpret_cast<const jboolean*>(buf));
3349 break;
3350 case Primitive::kPrimByte:
3351 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3352 reinterpret_cast<const jbyte*>(buf));
3353 break;
3354 case Primitive::kPrimChar:
3355 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3356 reinterpret_cast<const jchar*>(buf));
3357 break;
3358 case Primitive::kPrimShort:
3359 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3360 reinterpret_cast<const jshort*>(buf));
3361 break;
3362 case Primitive::kPrimInt:
3363 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3364 reinterpret_cast<const jint*>(buf));
3365 break;
3366 case Primitive::kPrimLong:
3367 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3368 reinterpret_cast<const jlong*>(buf));
3369 break;
3370 case Primitive::kPrimFloat:
3371 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3372 reinterpret_cast<const jfloat*>(buf));
3373 break;
3374 case Primitive::kPrimDouble:
3375 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3376 reinterpret_cast<const jdouble*>(buf));
3377 break;
3378 default:
3379 LOG(FATAL) << "Unexpected primitive type: " << type;
3380 }
3381 JniValueType result;
3382 result.V = nullptr;
3383 sc.Check(soa, false, "V", &result);
3384 }
3385 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003386};
3387
3388const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003389 nullptr, // reserved0.
3390 nullptr, // reserved1.
3391 nullptr, // reserved2.
3392 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003393 CheckJNI::GetVersion,
3394 CheckJNI::DefineClass,
3395 CheckJNI::FindClass,
3396 CheckJNI::FromReflectedMethod,
3397 CheckJNI::FromReflectedField,
3398 CheckJNI::ToReflectedMethod,
3399 CheckJNI::GetSuperclass,
3400 CheckJNI::IsAssignableFrom,
3401 CheckJNI::ToReflectedField,
3402 CheckJNI::Throw,
3403 CheckJNI::ThrowNew,
3404 CheckJNI::ExceptionOccurred,
3405 CheckJNI::ExceptionDescribe,
3406 CheckJNI::ExceptionClear,
3407 CheckJNI::FatalError,
3408 CheckJNI::PushLocalFrame,
3409 CheckJNI::PopLocalFrame,
3410 CheckJNI::NewGlobalRef,
3411 CheckJNI::DeleteGlobalRef,
3412 CheckJNI::DeleteLocalRef,
3413 CheckJNI::IsSameObject,
3414 CheckJNI::NewLocalRef,
3415 CheckJNI::EnsureLocalCapacity,
3416 CheckJNI::AllocObject,
3417 CheckJNI::NewObject,
3418 CheckJNI::NewObjectV,
3419 CheckJNI::NewObjectA,
3420 CheckJNI::GetObjectClass,
3421 CheckJNI::IsInstanceOf,
3422 CheckJNI::GetMethodID,
3423 CheckJNI::CallObjectMethod,
3424 CheckJNI::CallObjectMethodV,
3425 CheckJNI::CallObjectMethodA,
3426 CheckJNI::CallBooleanMethod,
3427 CheckJNI::CallBooleanMethodV,
3428 CheckJNI::CallBooleanMethodA,
3429 CheckJNI::CallByteMethod,
3430 CheckJNI::CallByteMethodV,
3431 CheckJNI::CallByteMethodA,
3432 CheckJNI::CallCharMethod,
3433 CheckJNI::CallCharMethodV,
3434 CheckJNI::CallCharMethodA,
3435 CheckJNI::CallShortMethod,
3436 CheckJNI::CallShortMethodV,
3437 CheckJNI::CallShortMethodA,
3438 CheckJNI::CallIntMethod,
3439 CheckJNI::CallIntMethodV,
3440 CheckJNI::CallIntMethodA,
3441 CheckJNI::CallLongMethod,
3442 CheckJNI::CallLongMethodV,
3443 CheckJNI::CallLongMethodA,
3444 CheckJNI::CallFloatMethod,
3445 CheckJNI::CallFloatMethodV,
3446 CheckJNI::CallFloatMethodA,
3447 CheckJNI::CallDoubleMethod,
3448 CheckJNI::CallDoubleMethodV,
3449 CheckJNI::CallDoubleMethodA,
3450 CheckJNI::CallVoidMethod,
3451 CheckJNI::CallVoidMethodV,
3452 CheckJNI::CallVoidMethodA,
3453 CheckJNI::CallNonvirtualObjectMethod,
3454 CheckJNI::CallNonvirtualObjectMethodV,
3455 CheckJNI::CallNonvirtualObjectMethodA,
3456 CheckJNI::CallNonvirtualBooleanMethod,
3457 CheckJNI::CallNonvirtualBooleanMethodV,
3458 CheckJNI::CallNonvirtualBooleanMethodA,
3459 CheckJNI::CallNonvirtualByteMethod,
3460 CheckJNI::CallNonvirtualByteMethodV,
3461 CheckJNI::CallNonvirtualByteMethodA,
3462 CheckJNI::CallNonvirtualCharMethod,
3463 CheckJNI::CallNonvirtualCharMethodV,
3464 CheckJNI::CallNonvirtualCharMethodA,
3465 CheckJNI::CallNonvirtualShortMethod,
3466 CheckJNI::CallNonvirtualShortMethodV,
3467 CheckJNI::CallNonvirtualShortMethodA,
3468 CheckJNI::CallNonvirtualIntMethod,
3469 CheckJNI::CallNonvirtualIntMethodV,
3470 CheckJNI::CallNonvirtualIntMethodA,
3471 CheckJNI::CallNonvirtualLongMethod,
3472 CheckJNI::CallNonvirtualLongMethodV,
3473 CheckJNI::CallNonvirtualLongMethodA,
3474 CheckJNI::CallNonvirtualFloatMethod,
3475 CheckJNI::CallNonvirtualFloatMethodV,
3476 CheckJNI::CallNonvirtualFloatMethodA,
3477 CheckJNI::CallNonvirtualDoubleMethod,
3478 CheckJNI::CallNonvirtualDoubleMethodV,
3479 CheckJNI::CallNonvirtualDoubleMethodA,
3480 CheckJNI::CallNonvirtualVoidMethod,
3481 CheckJNI::CallNonvirtualVoidMethodV,
3482 CheckJNI::CallNonvirtualVoidMethodA,
3483 CheckJNI::GetFieldID,
3484 CheckJNI::GetObjectField,
3485 CheckJNI::GetBooleanField,
3486 CheckJNI::GetByteField,
3487 CheckJNI::GetCharField,
3488 CheckJNI::GetShortField,
3489 CheckJNI::GetIntField,
3490 CheckJNI::GetLongField,
3491 CheckJNI::GetFloatField,
3492 CheckJNI::GetDoubleField,
3493 CheckJNI::SetObjectField,
3494 CheckJNI::SetBooleanField,
3495 CheckJNI::SetByteField,
3496 CheckJNI::SetCharField,
3497 CheckJNI::SetShortField,
3498 CheckJNI::SetIntField,
3499 CheckJNI::SetLongField,
3500 CheckJNI::SetFloatField,
3501 CheckJNI::SetDoubleField,
3502 CheckJNI::GetStaticMethodID,
3503 CheckJNI::CallStaticObjectMethod,
3504 CheckJNI::CallStaticObjectMethodV,
3505 CheckJNI::CallStaticObjectMethodA,
3506 CheckJNI::CallStaticBooleanMethod,
3507 CheckJNI::CallStaticBooleanMethodV,
3508 CheckJNI::CallStaticBooleanMethodA,
3509 CheckJNI::CallStaticByteMethod,
3510 CheckJNI::CallStaticByteMethodV,
3511 CheckJNI::CallStaticByteMethodA,
3512 CheckJNI::CallStaticCharMethod,
3513 CheckJNI::CallStaticCharMethodV,
3514 CheckJNI::CallStaticCharMethodA,
3515 CheckJNI::CallStaticShortMethod,
3516 CheckJNI::CallStaticShortMethodV,
3517 CheckJNI::CallStaticShortMethodA,
3518 CheckJNI::CallStaticIntMethod,
3519 CheckJNI::CallStaticIntMethodV,
3520 CheckJNI::CallStaticIntMethodA,
3521 CheckJNI::CallStaticLongMethod,
3522 CheckJNI::CallStaticLongMethodV,
3523 CheckJNI::CallStaticLongMethodA,
3524 CheckJNI::CallStaticFloatMethod,
3525 CheckJNI::CallStaticFloatMethodV,
3526 CheckJNI::CallStaticFloatMethodA,
3527 CheckJNI::CallStaticDoubleMethod,
3528 CheckJNI::CallStaticDoubleMethodV,
3529 CheckJNI::CallStaticDoubleMethodA,
3530 CheckJNI::CallStaticVoidMethod,
3531 CheckJNI::CallStaticVoidMethodV,
3532 CheckJNI::CallStaticVoidMethodA,
3533 CheckJNI::GetStaticFieldID,
3534 CheckJNI::GetStaticObjectField,
3535 CheckJNI::GetStaticBooleanField,
3536 CheckJNI::GetStaticByteField,
3537 CheckJNI::GetStaticCharField,
3538 CheckJNI::GetStaticShortField,
3539 CheckJNI::GetStaticIntField,
3540 CheckJNI::GetStaticLongField,
3541 CheckJNI::GetStaticFloatField,
3542 CheckJNI::GetStaticDoubleField,
3543 CheckJNI::SetStaticObjectField,
3544 CheckJNI::SetStaticBooleanField,
3545 CheckJNI::SetStaticByteField,
3546 CheckJNI::SetStaticCharField,
3547 CheckJNI::SetStaticShortField,
3548 CheckJNI::SetStaticIntField,
3549 CheckJNI::SetStaticLongField,
3550 CheckJNI::SetStaticFloatField,
3551 CheckJNI::SetStaticDoubleField,
3552 CheckJNI::NewString,
3553 CheckJNI::GetStringLength,
3554 CheckJNI::GetStringChars,
3555 CheckJNI::ReleaseStringChars,
3556 CheckJNI::NewStringUTF,
3557 CheckJNI::GetStringUTFLength,
3558 CheckJNI::GetStringUTFChars,
3559 CheckJNI::ReleaseStringUTFChars,
3560 CheckJNI::GetArrayLength,
3561 CheckJNI::NewObjectArray,
3562 CheckJNI::GetObjectArrayElement,
3563 CheckJNI::SetObjectArrayElement,
3564 CheckJNI::NewBooleanArray,
3565 CheckJNI::NewByteArray,
3566 CheckJNI::NewCharArray,
3567 CheckJNI::NewShortArray,
3568 CheckJNI::NewIntArray,
3569 CheckJNI::NewLongArray,
3570 CheckJNI::NewFloatArray,
3571 CheckJNI::NewDoubleArray,
3572 CheckJNI::GetBooleanArrayElements,
3573 CheckJNI::GetByteArrayElements,
3574 CheckJNI::GetCharArrayElements,
3575 CheckJNI::GetShortArrayElements,
3576 CheckJNI::GetIntArrayElements,
3577 CheckJNI::GetLongArrayElements,
3578 CheckJNI::GetFloatArrayElements,
3579 CheckJNI::GetDoubleArrayElements,
3580 CheckJNI::ReleaseBooleanArrayElements,
3581 CheckJNI::ReleaseByteArrayElements,
3582 CheckJNI::ReleaseCharArrayElements,
3583 CheckJNI::ReleaseShortArrayElements,
3584 CheckJNI::ReleaseIntArrayElements,
3585 CheckJNI::ReleaseLongArrayElements,
3586 CheckJNI::ReleaseFloatArrayElements,
3587 CheckJNI::ReleaseDoubleArrayElements,
3588 CheckJNI::GetBooleanArrayRegion,
3589 CheckJNI::GetByteArrayRegion,
3590 CheckJNI::GetCharArrayRegion,
3591 CheckJNI::GetShortArrayRegion,
3592 CheckJNI::GetIntArrayRegion,
3593 CheckJNI::GetLongArrayRegion,
3594 CheckJNI::GetFloatArrayRegion,
3595 CheckJNI::GetDoubleArrayRegion,
3596 CheckJNI::SetBooleanArrayRegion,
3597 CheckJNI::SetByteArrayRegion,
3598 CheckJNI::SetCharArrayRegion,
3599 CheckJNI::SetShortArrayRegion,
3600 CheckJNI::SetIntArrayRegion,
3601 CheckJNI::SetLongArrayRegion,
3602 CheckJNI::SetFloatArrayRegion,
3603 CheckJNI::SetDoubleArrayRegion,
3604 CheckJNI::RegisterNatives,
3605 CheckJNI::UnregisterNatives,
3606 CheckJNI::MonitorEnter,
3607 CheckJNI::MonitorExit,
3608 CheckJNI::GetJavaVM,
3609 CheckJNI::GetStringRegion,
3610 CheckJNI::GetStringUTFRegion,
3611 CheckJNI::GetPrimitiveArrayCritical,
3612 CheckJNI::ReleasePrimitiveArrayCritical,
3613 CheckJNI::GetStringCritical,
3614 CheckJNI::ReleaseStringCritical,
3615 CheckJNI::NewWeakGlobalRef,
3616 CheckJNI::DeleteWeakGlobalRef,
3617 CheckJNI::ExceptionCheck,
3618 CheckJNI::NewDirectByteBuffer,
3619 CheckJNI::GetDirectBufferAddress,
3620 CheckJNI::GetDirectBufferCapacity,
3621 CheckJNI::GetObjectRefType,
3622};
3623
3624const JNINativeInterface* GetCheckJniNativeInterface() {
3625 return &gCheckNativeInterface;
3626}
3627
3628class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003629 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003630 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003631 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3632 JniValueType args[1] = {{.v = vm}};
3633 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3634 JniValueType result;
3635 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08003636 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3637 // which will delete the JavaVMExt.
3638 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07003639 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003640 }
3641
3642 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003643 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3644 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3645 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3646 JniValueType result;
3647 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3648 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3649 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003650 }
3651
3652 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003653 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3654 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3655 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3656 JniValueType result;
3657 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3658 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3659 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003660 }
3661
3662 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003663 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3664 JniValueType args[1] = {{.v = vm}};
3665 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3666 JniValueType result;
3667 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3668 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3669 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003670 }
3671
Ian Rogers68d8b422014-07-17 11:09:10 -07003672 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3673 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3674 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3675 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3676 JniValueType result;
3677 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3678 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3679 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003680 }
3681
3682 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003683 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3684 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003685 }
3686};
3687
3688const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003689 nullptr, // reserved0
3690 nullptr, // reserved1
3691 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003692 CheckJII::DestroyJavaVM,
3693 CheckJII::AttachCurrentThread,
3694 CheckJII::DetachCurrentThread,
3695 CheckJII::GetEnv,
3696 CheckJII::AttachCurrentThreadAsDaemon
3697};
3698
3699const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3700 return &gCheckInvokeInterface;
3701}
3702
3703} // namespace art