blob: 05f099f3b2a4c1fa44691b507b04c684e91165f2 [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
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070022#include <iomanip>
23
Andreas Gampe57943812017-12-06 21:39:13 -080024#include <android-base/logging.h>
25#include <android-base/stringprintf.h>
Andreas Gampe46ee31b2016-12-14 10:11:49 -080026
Mathieu Chartierc7853442015-03-27 14:35:38 -070027#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070028#include "art_method-inl.h"
Andreas Gampe57943812017-12-06 21:39:13 -080029#include "base/macros.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070030#include "base/to_str.h"
Ian Rogers55256cb2017-12-21 17:07:11 -080031#include "base/time_utils.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080032#include "class_linker-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070033#include "class_linker.h"
David Sehr9e734c72018-01-04 17:56:19 -080034#include "dex/dex_file-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070035#include "gc/space/space.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070036#include "java_vm_ext.h"
Andreas Gampe277ccbd2014-11-03 21:36:10 -080037#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080038#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080039#include "mirror/object-inl.h"
40#include "mirror/object_array-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070041#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080042#include "mirror/throwable.h"
Jeff Hao58df3272013-04-22 15:28:53 -070043#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070044#include "scoped_thread_state_change-inl.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070045#include "thread.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070046#include "well_known_classes.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070047
48namespace art {
Ian Rogersac4d45a2018-02-15 11:19:01 -080049namespace {
Elliott Hughesa2501992011-08-26 19:39:54 -070050
Andreas Gampe46ee31b2016-12-14 10:11:49 -080051using android::base::StringAppendF;
52using android::base::StringPrintf;
53
Elliott Hughesa2501992011-08-26 19:39:54 -070054/*
55 * ===========================================================================
56 * JNI function helpers
57 * ===========================================================================
58 */
59
Ian Rogers55256cb2017-12-21 17:07:11 -080060// Warn if a JNI critical is held for longer than 16ms.
61static constexpr uint64_t kCriticalWarnTimeUs = MsToUs(16);
62static_assert(kCriticalWarnTimeUs > 0, "No JNI critical warn time set");
63
Elliott Hughes3f6635a2012-06-19 13:37:49 -070064// Flags passed into ScopedCheck.
Ian Rogers55256cb2017-12-21 17:07:11 -080065static constexpr uint16_t kFlag_Default = 0x0000;
Elliott Hughesa2501992011-08-26 19:39:54 -070066
Ian Rogers55256cb2017-12-21 17:07:11 -080067// Calling while in critical is not allowed.
68static constexpr uint16_t kFlag_CritBad = 0x0000;
69// Calling while in critical is allowed.
70static constexpr uint16_t kFlag_CritOkay = 0x0001;
71// This is a critical "get".
72static constexpr uint16_t kFlag_CritGet = 0x0002;
73// This is a critical "release".
74static constexpr uint16_t kFlag_CritRelease = 0x0003;
75// Bit mask to get "crit" value.
76static constexpr uint16_t kFlag_CritMask = 0x0003;
Elliott Hughesa2501992011-08-26 19:39:54 -070077
Ian Rogers55256cb2017-12-21 17:07:11 -080078// Raised exceptions are allowed.
79static constexpr uint16_t kFlag_ExcepOkay = 0x0004;
Elliott Hughesa2501992011-08-26 19:39:54 -070080
Ian Rogers55256cb2017-12-21 17:07:11 -080081// Are we in a non-critical release function?
82static constexpr uint16_t kFlag_Release = 0x0010;
83// Are our UTF parameters nullable?
84static constexpr uint16_t kFlag_NullableUtf = 0x0020;
Elliott Hughesa2501992011-08-26 19:39:54 -070085
Ian Rogers55256cb2017-12-21 17:07:11 -080086// Part of the invocation interface (JavaVM*).
87static constexpr uint16_t kFlag_Invocation = 0x0100;
Elliott Hughesa2501992011-08-26 19:39:54 -070088
Ian Rogers55256cb2017-12-21 17:07:11 -080089// Add this to a JNI function's flags if you want to trace every call.
90static constexpr uint16_t kFlag_ForceTrace = 0x8000;
Alex Light48ffe062015-08-19 15:23:23 -070091
92class VarArgs;
Ian Rogers68d8b422014-07-17 11:09:10 -070093/*
94 * Java primitive types:
95 * B - jbyte
96 * C - jchar
97 * D - jdouble
98 * F - jfloat
99 * I - jint
100 * J - jlong
101 * S - jshort
102 * Z - jboolean (shown as true and false)
103 * V - void
104 *
105 * Java reference types:
106 * L - jobject
107 * a - jarray
108 * c - jclass
109 * s - jstring
110 * t - jthrowable
111 *
112 * JNI types:
113 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
114 * f - jfieldID
115 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
116 * m - jmethodID
117 * p - void*
118 * r - jint (for release mode arguments)
119 * u - const char* (Modified UTF-8)
120 * z - jsize (for lengths; use i if negative values are okay)
121 * v - JavaVM*
122 * w - jobjectRefType
123 * E - JNIEnv*
124 * . - no argument; just print "..." (used for varargs JNI calls)
125 *
126 */
127union JniValueType {
128 jarray a;
129 jboolean b;
130 jclass c;
131 jfieldID f;
132 jint i;
133 jmethodID m;
134 const void* p; // Pointer.
135 jint r; // Release mode.
136 jstring s;
137 jthrowable t;
138 const char* u; // Modified UTF-8.
139 JavaVM* v;
140 jobjectRefType w;
141 jsize z;
142 jbyte B;
143 jchar C;
144 jdouble D;
145 JNIEnv* E;
146 jfloat F;
147 jint I;
148 jlong J;
149 jobject L;
150 jshort S;
151 const void* V; // void
152 jboolean Z;
Alex Light48ffe062015-08-19 15:23:23 -0700153 const VarArgs* va;
154};
155
156/*
157 * A structure containing all the information needed to validate varargs arguments.
158 *
159 * Note that actually getting the arguments from this structure mutates it so should only be done on
160 * owned copies.
161 */
162class VarArgs {
163 public:
164 VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
165 va_copy(vargs_, var);
166 }
167
168 VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
169
170 ~VarArgs() {
171 if (type_ == kTypeVaList) {
172 va_end(vargs_);
173 }
174 }
175
176 VarArgs(VarArgs&& other) {
177 m_ = other.m_;
178 cnt_ = other.cnt_;
179 type_ = other.type_;
180 if (other.type_ == kTypeVaList) {
181 va_copy(vargs_, other.vargs_);
182 } else {
183 ptr_ = other.ptr_;
184 }
185 }
186
187 // This method is const because we need to ensure that one only uses the GetValue method on an
188 // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
189 // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
190 // we want to use one we need to Clone() it.
191 VarArgs Clone() const {
192 if (type_ == kTypeVaList) {
193 // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
194 // messed up if the source argument is not the exact type 'va_list'.
195 return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
196 } else {
197 return VarArgs(m_, cnt_, ptr_);
198 }
199 }
200
201 jmethodID GetMethodID() const {
202 return m_;
203 }
204
205 JniValueType GetValue(char fmt) {
206 JniValueType o;
207 if (type_ == kTypeVaList) {
208 switch (fmt) {
209 case 'Z': o.Z = static_cast<jboolean>(va_arg(vargs_, jint)); break;
210 case 'B': o.B = static_cast<jbyte>(va_arg(vargs_, jint)); break;
211 case 'C': o.C = static_cast<jchar>(va_arg(vargs_, jint)); break;
212 case 'S': o.S = static_cast<jshort>(va_arg(vargs_, jint)); break;
213 case 'I': o.I = va_arg(vargs_, jint); break;
214 case 'J': o.J = va_arg(vargs_, jlong); break;
215 case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
216 case 'D': o.D = va_arg(vargs_, jdouble); break;
217 case 'L': o.L = va_arg(vargs_, jobject); break;
218 default:
219 LOG(FATAL) << "Illegal type format char " << fmt;
220 UNREACHABLE();
221 }
222 } else {
223 CHECK(type_ == kTypePtr);
224 jvalue v = ptr_[cnt_];
225 cnt_++;
226 switch (fmt) {
227 case 'Z': o.Z = v.z; break;
228 case 'B': o.B = v.b; break;
229 case 'C': o.C = v.c; break;
230 case 'S': o.S = v.s; break;
231 case 'I': o.I = v.i; break;
232 case 'J': o.J = v.j; break;
233 case 'F': o.F = v.f; break;
234 case 'D': o.D = v.d; break;
235 case 'L': o.L = v.l; break;
236 default:
237 LOG(FATAL) << "Illegal type format char " << fmt;
238 UNREACHABLE();
239 }
240 }
241 return o;
242 }
243
244 private:
245 VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
246 va_copy(vargs_, var);
247 }
248
249 VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
250
251 enum VarArgsType {
252 kTypeVaList,
253 kTypePtr,
254 };
255
256 jmethodID m_;
257 VarArgsType type_;
258 uint32_t cnt_;
259 union {
260 va_list vargs_;
261 const jvalue* ptr_;
262 };
Elliott Hughesa0957642011-09-02 14:27:33 -0700263};
264
Elliott Hughesa2501992011-08-26 19:39:54 -0700265class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800266 public:
Ian Rogers55256cb2017-12-21 17:07:11 -0800267 ScopedCheck(uint16_t flags, const char* functionName, bool has_method = true)
268 : function_name_(functionName), indent_(0), flags_(flags), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700269 }
270
Ian Rogers68d8b422014-07-17 11:09:10 -0700271 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700272
Elliott Hughes81ff3182012-03-23 20:35:56 -0700273 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
274 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
275 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
276 // circumstances, but this is incorrect.
Ian Rogers68d8b422014-07-17 11:09:10 -0700277 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700278 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700279 AbortF("illegal class name '%s'\n"
280 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
281 class_name);
282 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700283 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700284 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700285 }
286
287 /*
288 * Verify that this instance field ID is valid for this object.
289 *
290 * Assumes "jobj" has already been validated.
291 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700292 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700293 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700294 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Ian Rogers68d8b422014-07-17 11:09:10 -0700295 if (o == nullptr) {
296 AbortF("field operation on NULL object: %p", java_object);
297 return false;
298 }
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700299 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700300 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700301 AbortF("field operation on invalid %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700302 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700303 java_object);
304 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700305 }
306
Andreas Gampe08883de2016-11-08 13:20:52 -0800307 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800308 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700309 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700310 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800311 mirror::Class* c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700312 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700313 AbortF("jfieldID %s not valid for an object of class %s",
David Sehr709b0702016-10-13 09:12:37 -0700314 f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700315 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700316 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700317 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700318 }
319
320 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700321 * Verify that the pointer value is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -0700322 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700323 bool CheckNonNull(const void* ptr) {
324 if (UNLIKELY(ptr == nullptr)) {
325 AbortF("non-nullable argument was NULL");
326 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700327 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700328 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700329 }
330
331 /*
332 * Verify that the method's return type matches the type of call.
333 * 'expectedType' will be "L" for all objects, including arrays.
334 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700335 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
336 jmethodID mid, Primitive::Type type, InvokeType invoke)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700337 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800338 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800339 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700340 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700341 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700342 if (type != Primitive::GetType(m->GetShorty()[0])) {
David Sehr709b0702016-10-13 09:12:37 -0700343 AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700344 return false;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700345 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700346 bool is_static = (invoke == kStatic);
347 if (is_static != m->IsStatic()) {
348 if (is_static) {
349 AbortF("calling non-static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700350 m->PrettyMethod().c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700351 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700352 AbortF("calling static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700353 m->PrettyMethod().c_str(), function_name_);
Ian Rogers68d8b422014-07-17 11:09:10 -0700354 }
355 return false;
356 }
357 if (invoke != kVirtual) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700358 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700359 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700360 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
David Sehr709b0702016-10-13 09:12:37 -0700361 m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700362 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700363 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700364 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700365 if (invoke != kStatic) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700366 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700367 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700368 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700369 return false;
370 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700371 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
372 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700373 return false;
374 }
375 }
376 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700377 }
378
379 /*
380 * Verify that this static field ID is valid for this class.
381 *
382 * Assumes "java_class" has already been validated.
383 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700384 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700385 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700386 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Andreas Gampe08883de2016-11-08 13:20:52 -0800387 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800388 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700389 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700390 }
Alex Lighte4033fa2017-12-13 10:32:59 -0800391 if (!f->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700392 AbortF("static jfieldID %p not valid for class %s", fid,
393 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700394 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700395 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700396 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700397 }
398
399 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700400 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700401 *
402 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700403 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700404 * allow bad code in the system though.
405 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700406 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700407 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700408 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700409 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800410 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800411 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700412 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700413 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700414 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700415 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700416 AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
417 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700418 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700419 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700420 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700421 }
422
423 /*
424 * Verify that "mid" is appropriate for "jobj".
425 *
426 * Make sure the object is an instance of the method's declaring class.
427 * (Note the mid might point to a declaration in an interface; this
428 * will be handled automatically by the instanceof check.)
429 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700430 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700431 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800432 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800433 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700434 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700435 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700436 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700437 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700438 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700439 return false;
440 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700441 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
442 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700443 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700444 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700445 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700446 }
447
448 /**
449 * The format string is a sequence of the following characters,
450 * and must be followed by arguments of the corresponding types
451 * in the same order.
452 *
453 * Java primitive types:
454 * B - jbyte
455 * C - jchar
456 * D - jdouble
457 * F - jfloat
458 * I - jint
459 * J - jlong
460 * S - jshort
461 * Z - jboolean (shown as true and false)
462 * V - void
463 *
464 * Java reference types:
465 * L - jobject
466 * a - jarray
467 * c - jclass
468 * s - jstring
469 *
470 * JNI types:
471 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
472 * f - jfieldID
473 * m - jmethodID
474 * p - void*
475 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700476 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700477 * z - jsize (for lengths; use i if negative values are okay)
478 * v - JavaVM*
479 * E - JNIEnv*
Alex Light48ffe062015-08-19 15:23:23 -0700480 * . - VarArgs* for Jni calls with variable length arguments
Elliott Hughesa2501992011-08-26 19:39:54 -0700481 *
482 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
483 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700484 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700485 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700486 ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700487 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700488 // We need to guard some of the invocation interface's calls: a bad caller might
489 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700490 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800491 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
492 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700493 }
494 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700495
Ian Rogersef7d42f2014-01-06 12:55:46 -0800496 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700497 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700498 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700499 for (size_t i = 0; fmt[i] != '\0'; ++i) {
500 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
501 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700502 StringAppendF(&msg, ", ");
503 }
504 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700505
Elliott Hughes485cac42011-12-09 17:49:35 -0800506 if ((flags_ & kFlag_ForceTrace) != 0) {
507 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
508 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700509 if (has_method_) {
David Sehr709b0702016-10-13 09:12:37 -0700510 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700511 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
512 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700513 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700514 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
515 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700516 }
517 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700518 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700519 }
520 }
521
522 // We always do the thorough checks on entry, and never on exit...
523 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700524 for (size_t i = 0; fmt[i] != '\0'; ++i) {
525 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
526 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700527 }
528 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700529 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700530 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700531 }
532
Ian Rogers68d8b422014-07-17 11:09:10 -0700533 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
534 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800535 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700536 // We need to guard some of the invocation interface's calls: a bad caller might
537 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
538 Thread* self = Thread::Current();
539 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
540 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700541 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700542 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
543 }
544 }
545 if (should_trace) {
546 std::string msg;
547 for (size_t i = 0; fmt[i] != '\0'; ++i) {
548 TraceNonHeapValue(fmt[i], args[i], &msg);
549 if (fmt[i + 1] != '\0') {
550 StringAppendF(&msg, ", ");
551 }
552 }
553
554 if ((flags_ & kFlag_ForceTrace) != 0) {
555 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
556 } else if (entry) {
557 if (has_method_) {
558 Thread* self = Thread::Current();
559 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700560 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
David Sehr709b0702016-10-13 09:12:37 -0700561 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Ian Rogers68d8b422014-07-17 11:09:10 -0700562 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
563 indent_ = methodName.size() + 1;
564 } else {
565 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
566 indent_ = 0;
567 }
568 } else {
569 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
570 }
571 }
572
573 // We always do the thorough checks on entry, and never on exit...
574 if (entry) {
575 for (size_t i = 0; fmt[i] != '\0'; ++i) {
576 if (!CheckNonHeapValue(fmt[i], args[i])) {
577 return false;
578 }
579 }
580 }
581 return true;
582 }
583
584 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700585 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700586 ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700587 if (method == nullptr) {
588 AbortF("expected non-null method");
589 return false;
590 }
591 mirror::Class* c = method->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700592 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c &&
593 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700594 AbortF("expected java.lang.reflect.Method or "
595 "java.lang.reflect.Constructor but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700596 method->PrettyTypeOf().c_str(), jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700597 return false;
598 }
599 return true;
600 }
601
Andreas Gampe13b27842016-11-07 16:48:23 -0800602 bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
603 ArtMethod* method = jni::DecodeArtMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700604 if (method == nullptr) {
605 AbortF("expected non-null constructor");
606 return false;
607 }
608 if (!method->IsConstructor() || method->IsStatic()) {
David Sehr709b0702016-10-13 09:12:37 -0700609 AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700610 return false;
611 }
612 return true;
613 }
614
615 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700616 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700617 ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700618 if (field == nullptr) {
619 AbortF("expected non-null java.lang.reflect.Field");
620 return false;
621 }
622 mirror::Class* c = field->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700623 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700624 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700625 field->PrettyTypeOf().c_str(), jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700626 return false;
627 }
628 return true;
629 }
630
631 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700632 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700633 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700634 if (!obj->GetClass()->IsThrowableClass()) {
635 AbortF("expected java.lang.Throwable but got object of type "
David Sehr709b0702016-10-13 09:12:37 -0700636 "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700637 return false;
638 }
639 return true;
640 }
641
642 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700643 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700644 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700645 if (!c->IsThrowableClass()) {
646 AbortF("expected java.lang.Throwable class but got object of "
David Sehr709b0702016-10-13 09:12:37 -0700647 "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700648 return false;
649 }
650 return true;
651 }
652
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700653 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700654 IndirectRefKind found_kind;
655 if (expected_kind == kLocal) {
Andreas Gampedc061d02016-10-24 13:19:37 -0700656 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700657 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
658 found_kind = kLocal;
659 }
660 } else {
Andreas Gampedc061d02016-10-24 13:19:37 -0700661 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700662 }
663 if (obj != nullptr && found_kind != expected_kind) {
664 AbortF("expected reference of kind %s but found %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700665 GetIndirectRefKindString(expected_kind),
666 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700667 obj);
668 return false;
669 }
670 return true;
671 }
672
673 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700674 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700675 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700676 if (!c->IsInstantiableNonArray()) {
David Sehr709b0702016-10-13 09:12:37 -0700677 AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700678 return false;
679 }
680 return true;
681 }
682
683 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700684 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700685 if (!CheckArray(soa, array)) {
686 return false;
687 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700688 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700689 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
690 AbortF("incompatible array type %s expected %s[]: %p",
David Sehr709b0702016-10-13 09:12:37 -0700691 a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700692 return false;
693 }
694 return true;
695 }
696
697 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
698 Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700699 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700700 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
701 return false;
702 }
703 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
704 return false;
705 }
Andreas Gampe08883de2016-11-08 13:20:52 -0800706 ArtField* field = jni::DecodeArtField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700707 DCHECK(field != nullptr); // Already checked by Check.
708 if (is_static != field->IsStatic()) {
709 AbortF("attempt to access %s field %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700710 field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700711 return false;
712 }
713 if (type != field->GetTypeAsPrimitiveType()) {
714 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700715 field->PrettyField().c_str(),
716 PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
Ian Rogers68d8b422014-07-17 11:09:10 -0700717 PrettyDescriptor(type).c_str(), fid);
718 return false;
719 }
720 if (is_static) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700721 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700722 if (o == nullptr || !o->IsClass()) {
723 AbortF("attempt to access static field %s with a class argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700724 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700725 return false;
726 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700727 ObjPtr<mirror::Class> c = o->AsClass();
Alex Lighte4033fa2017-12-13 10:32:59 -0800728 if (!field->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700729 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700730 field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700731 return false;
732 }
733 } else {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700734 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700735 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
736 AbortF("attempt to access field %s from an object argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700737 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700738 return false;
739 }
740 }
741 return true;
742 }
743
744 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800745 enum InstanceKind {
746 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700747 kDirectByteBuffer,
748 kObject,
749 kString,
750 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800751 };
752
753 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700754 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800755 * an instance of expectedClass.
756 *
757 * Because we're looking at an object on the GC heap, we have to switch
758 * to "running" mode before doing the checks.
759 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700760 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700761 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800762 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800763 switch (kind) {
764 case kClass:
765 what = "jclass";
766 break;
767 case kDirectByteBuffer:
768 what = "direct ByteBuffer";
769 break;
770 case kObject:
771 what = "jobject";
772 break;
773 case kString:
774 what = "jstring";
775 break;
776 case kThrowable:
777 what = "jthrowable";
778 break;
779 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700780 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800781 }
782
Ian Rogersef7d42f2014-01-06 12:55:46 -0800783 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700784 if (null_ok) {
785 return true;
786 } else {
787 AbortF("%s received NULL %s", function_name_, what);
788 return false;
789 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800790 }
791
Mathieu Chartier0795f232016-09-27 18:43:30 -0700792 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700793 if (obj == nullptr) {
794 // Either java_object is invalid or is a cleared weak.
795 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
796 bool okay;
Andreas Gampedc061d02016-10-24 13:19:37 -0700797 if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) {
Ian Rogersc0542af2014-09-03 16:16:56 -0700798 okay = false;
799 } else {
800 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
Mathieu Chartierc4f39252016-10-05 18:32:08 -0700801 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
Ian Rogersc0542af2014-09-03 16:16:56 -0700802 }
803 if (!okay) {
804 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700805 what,
806 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
807 java_object,
808 obj.Ptr());
Ian Rogersc0542af2014-09-03 16:16:56 -0700809 return false;
810 }
811 }
812
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700813 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700814 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700815 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700816 what,
817 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
818 java_object,
819 obj.Ptr());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800820 return false;
821 }
822
823 bool okay = true;
824 switch (kind) {
825 case kClass:
826 okay = obj->IsClass();
827 break;
828 case kDirectByteBuffer:
829 UNIMPLEMENTED(FATAL);
830 break;
831 case kString:
832 okay = obj->GetClass()->IsStringClass();
833 break;
834 case kThrowable:
835 okay = obj->GetClass()->IsThrowableClass();
836 break;
837 case kObject:
838 break;
839 }
840 if (!okay) {
David Sehr709b0702016-10-13 09:12:37 -0700841 AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800842 return false;
843 }
844
845 return true;
846 }
847
Ian Rogers68d8b422014-07-17 11:09:10 -0700848 /*
849 * Verify that the "mode" argument passed to a primitive array Release
850 * function is one of the valid values.
851 */
852 bool CheckReleaseMode(jint mode) {
853 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
854 AbortF("unknown value for release mode: %d", mode);
855 return false;
856 }
857 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700858 }
859
Ian Rogers68d8b422014-07-17 11:09:10 -0700860 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700861 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700862 switch (fmt) {
863 case 'a': // jarray
864 return CheckArray(soa, arg.a);
865 case 'c': // jclass
866 return CheckInstance(soa, kClass, arg.c, false);
867 case 'f': // jfieldID
Andreas Gampe08883de2016-11-08 13:20:52 -0800868 return CheckFieldID(arg.f) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700869 case 'm': // jmethodID
Andreas Gampe13b27842016-11-07 16:48:23 -0800870 return CheckMethodID(arg.m) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700871 case 'r': // release int
872 return CheckReleaseMode(arg.r);
873 case 's': // jstring
874 return CheckInstance(soa, kString, arg.s, false);
875 case 't': // jthrowable
876 return CheckInstance(soa, kThrowable, arg.t, false);
877 case 'E': // JNIEnv*
878 return CheckThread(arg.E);
879 case 'L': // jobject
880 return CheckInstance(soa, kObject, arg.L, true);
Alex Light48ffe062015-08-19 15:23:23 -0700881 case '.': // A VarArgs list
882 return CheckVarArgs(soa, arg.va);
Ian Rogers68d8b422014-07-17 11:09:10 -0700883 default:
884 return CheckNonHeapValue(fmt, arg);
885 }
886 }
887
Alex Light48ffe062015-08-19 15:23:23 -0700888 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700889 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Light48ffe062015-08-19 15:23:23 -0700890 CHECK(args_p != nullptr);
891 VarArgs args(args_p->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800892 ArtMethod* m = CheckMethodID(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700893 if (m == nullptr) {
894 return false;
895 }
896 uint32_t len = 0;
897 const char* shorty = m->GetShorty(&len);
898 // Skip the return type
899 CHECK_GE(len, 1u);
900 len--;
901 shorty++;
902 for (uint32_t i = 0; i < len; i++) {
903 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
904 return false;
905 }
906 }
907 return true;
908 }
909
Ian Rogers68d8b422014-07-17 11:09:10 -0700910 bool CheckNonHeapValue(char fmt, JniValueType arg) {
911 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700912 case 'p': // TODO: pointer - null or readable?
913 case 'v': // JavaVM*
914 case 'B': // jbyte
915 case 'C': // jchar
916 case 'D': // jdouble
917 case 'F': // jfloat
918 case 'I': // jint
919 case 'J': // jlong
920 case 'S': // jshort
921 break; // Ignored.
922 case 'b': // jboolean, why two? Fall-through.
923 case 'Z':
924 return CheckBoolean(arg.Z);
925 case 'u': // utf8
926 if ((flags_ & kFlag_Release) != 0) {
927 return CheckNonNull(arg.u);
928 } else {
929 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
930 return CheckUtfString(arg.u, nullable);
931 }
932 case 'w': // jobjectRefType
933 switch (arg.w) {
934 case JNIInvalidRefType:
935 case JNILocalRefType:
936 case JNIGlobalRefType:
937 case JNIWeakGlobalRefType:
938 break;
939 default:
940 AbortF("Unknown reference type");
941 return false;
942 }
943 break;
944 case 'z': // jsize
945 return CheckLengthPositive(arg.z);
946 default:
947 AbortF("unknown format specifier: '%c'", fmt);
948 return false;
949 }
950 return true;
951 }
952
953 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
954 std::string* msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700955 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700956 switch (fmt) {
957 case 'L': // jobject fall-through.
958 case 'a': // jarray fall-through.
959 case 's': // jstring fall-through.
960 case 't': // jthrowable fall-through.
961 if (arg.L == nullptr) {
962 *msg += "NULL";
963 } else {
964 StringAppendF(msg, "%p", arg.L);
965 }
966 break;
967 case 'c': { // jclass
968 jclass jc = arg.c;
Mathieu Chartier0795f232016-09-27 18:43:30 -0700969 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700970 if (c == nullptr) {
971 *msg += "NULL";
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700972 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700973 StringAppendF(msg, "INVALID POINTER:%p", jc);
974 } else if (!c->IsClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700975 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
Ian Rogers68d8b422014-07-17 11:09:10 -0700976 } else {
David Sehr709b0702016-10-13 09:12:37 -0700977 *msg += c->PrettyClass();
Ian Rogers68d8b422014-07-17 11:09:10 -0700978 if (!entry) {
979 StringAppendF(msg, " (%p)", jc);
980 }
981 }
982 break;
983 }
984 case 'f': { // jfieldID
985 jfieldID fid = arg.f;
Andreas Gampe08883de2016-11-08 13:20:52 -0800986 ArtField* f = jni::DecodeArtField(fid);
David Sehr709b0702016-10-13 09:12:37 -0700987 *msg += ArtField::PrettyField(f);
Ian Rogers68d8b422014-07-17 11:09:10 -0700988 if (!entry) {
989 StringAppendF(msg, " (%p)", fid);
990 }
991 break;
992 }
993 case 'm': { // jmethodID
994 jmethodID mid = arg.m;
Andreas Gampe13b27842016-11-07 16:48:23 -0800995 ArtMethod* m = jni::DecodeArtMethod(mid);
David Sehr709b0702016-10-13 09:12:37 -0700996 *msg += ArtMethod::PrettyMethod(m);
Ian Rogers68d8b422014-07-17 11:09:10 -0700997 if (!entry) {
998 StringAppendF(msg, " (%p)", mid);
999 }
1000 break;
1001 }
Alex Light48ffe062015-08-19 15:23:23 -07001002 case '.': {
1003 const VarArgs* va = arg.va;
1004 VarArgs args(va->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -08001005 ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -07001006 uint32_t len;
1007 const char* shorty = m->GetShorty(&len);
1008 CHECK_GE(len, 1u);
1009 // Skip past return value.
1010 len--;
1011 shorty++;
1012 // Remove the previous ', ' from the message.
1013 msg->erase(msg->length() - 2);
1014 for (uint32_t i = 0; i < len; i++) {
1015 *msg += ", ";
1016 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
1017 }
1018 break;
1019 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001020 default:
1021 TraceNonHeapValue(fmt, arg, msg);
1022 break;
1023 }
1024 }
1025
1026 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
1027 switch (fmt) {
1028 case 'B': // jbyte
1029 if (arg.B >= 0 && arg.B < 10) {
1030 StringAppendF(msg, "%d", arg.B);
1031 } else {
1032 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1033 }
1034 break;
1035 case 'C': // jchar
1036 if (arg.C < 0x7f && arg.C >= ' ') {
1037 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1038 } else {
1039 StringAppendF(msg, "U+%x", arg.C);
1040 }
1041 break;
1042 case 'F': // jfloat
1043 StringAppendF(msg, "%g", arg.F);
1044 break;
1045 case 'D': // jdouble
1046 StringAppendF(msg, "%g", arg.D);
1047 break;
1048 case 'S': // jshort
1049 StringAppendF(msg, "%d", arg.S);
1050 break;
1051 case 'i': // jint - fall-through.
1052 case 'I': // jint
1053 StringAppendF(msg, "%d", arg.I);
1054 break;
1055 case 'J': // jlong
1056 StringAppendF(msg, "%" PRId64, arg.J);
1057 break;
1058 case 'Z': // jboolean
1059 case 'b': // jboolean (JNI-style)
1060 *msg += arg.b == JNI_TRUE ? "true" : "false";
1061 break;
1062 case 'V': // void
1063 DCHECK(arg.V == nullptr);
1064 *msg += "void";
1065 break;
1066 case 'v': // JavaVM*
1067 StringAppendF(msg, "(JavaVM*)%p", arg.v);
1068 break;
1069 case 'E':
1070 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1071 break;
1072 case 'z': // non-negative jsize
1073 // You might expect jsize to be size_t, but it's not; it's the same as jint.
1074 // We only treat this specially so we can do the non-negative check.
1075 // TODO: maybe this wasn't worth it?
1076 StringAppendF(msg, "%d", arg.z);
1077 break;
1078 case 'p': // void* ("pointer")
1079 if (arg.p == nullptr) {
1080 *msg += "NULL";
1081 } else {
1082 StringAppendF(msg, "(void*) %p", arg.p);
1083 }
1084 break;
1085 case 'r': { // jint (release mode)
1086 jint releaseMode = arg.r;
1087 if (releaseMode == 0) {
1088 *msg += "0";
1089 } else if (releaseMode == JNI_ABORT) {
1090 *msg += "JNI_ABORT";
1091 } else if (releaseMode == JNI_COMMIT) {
1092 *msg += "JNI_COMMIT";
1093 } else {
1094 StringAppendF(msg, "invalid release mode %d", releaseMode);
1095 }
1096 break;
1097 }
1098 case 'u': // const char* (Modified UTF-8)
1099 if (arg.u == nullptr) {
1100 *msg += "NULL";
1101 } else {
1102 StringAppendF(msg, "\"%s\"", arg.u);
1103 }
1104 break;
1105 case 'w': // jobjectRefType
1106 switch (arg.w) {
1107 case JNIInvalidRefType:
1108 *msg += "invalid reference type";
1109 break;
1110 case JNILocalRefType:
1111 *msg += "local ref type";
1112 break;
1113 case JNIGlobalRefType:
1114 *msg += "global ref type";
1115 break;
1116 case JNIWeakGlobalRefType:
1117 *msg += "weak global ref type";
1118 break;
1119 default:
1120 *msg += "unknown ref type";
1121 break;
1122 }
1123 break;
Ian Rogers68d8b422014-07-17 11:09:10 -07001124 default:
1125 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1126 }
1127 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001128 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001129 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -07001130 *
1131 * Since we're dealing with objects, switch to "running" mode.
1132 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001133 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001134 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001135 if (UNLIKELY(java_array == nullptr)) {
1136 AbortF("jarray was NULL");
1137 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001138 }
1139
Mathieu Chartier0795f232016-09-27 18:43:30 -07001140 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001141 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001142 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001143 AbortF("jarray is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -07001144 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)),
1145 java_array,
1146 a.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -07001147 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001148 } else if (!a->IsArrayInstance()) {
David Sehr709b0702016-10-13 09:12:37 -07001149 AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001150 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001151 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001152 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001153 }
1154
Ian Rogers68d8b422014-07-17 11:09:10 -07001155 bool CheckBoolean(jboolean z) {
1156 if (z != JNI_TRUE && z != JNI_FALSE) {
1157 AbortF("unexpected jboolean value: %d", z);
1158 return false;
1159 }
1160 return true;
1161 }
1162
1163 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001164 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001165 AbortF("negative jsize: %d", length);
1166 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001167 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001168 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001169 }
1170
Andreas Gampe08883de2016-11-08 13:20:52 -08001171 ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001172 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001173 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001174 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001175 }
Andreas Gampe08883de2016-11-08 13:20:52 -08001176 ArtField* f = jni::DecodeArtField(fid);
Mathieu Chartierc7853442015-03-27 14:35:38 -07001177 // TODO: Better check here.
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001178 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001179 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001180 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001181 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001182 }
1183 return f;
1184 }
1185
Andreas Gampe13b27842016-11-07 16:48:23 -08001186 ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001187 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001188 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001189 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001190 }
Andreas Gampe13b27842016-11-07 16:48:23 -08001191 ArtMethod* m = jni::DecodeArtMethod(mid);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001192 // TODO: Better check here.
1193 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001194 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001195 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001196 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001197 }
1198 return m;
1199 }
1200
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001201 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001202 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001203 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001204 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1205 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001206 }
1207
Daniel Erat35e827a2016-05-10 18:07:18 -06001208 // Get the current thread's JNIEnv by going through our TLS pointer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001209 JNIEnvExt* threadEnv = self->GetJniEnv();
1210
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001211 // Verify that the current thread is (a) attached and (b) associated with
1212 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001213 if (env != threadEnv) {
Daniel Erat35e827a2016-05-10 18:07:18 -06001214 // Get the thread owning the JNIEnv that's being used.
Ian Rogersac4d45a2018-02-15 11:19:01 -08001215 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->GetSelf();
Ian Rogers68d8b422014-07-17 11:09:10 -07001216 AbortF("thread %s using JNIEnv* from thread %s",
Daniel Erat35e827a2016-05-10 18:07:18 -06001217 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001218 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001219 }
1220
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001221 // Verify that, if this thread previously made a critical "get" call, we
1222 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001223 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001224 case kFlag_CritOkay: // okay to call this method
1225 break;
1226 case kFlag_CritBad: // not okay to call
Ian Rogersac4d45a2018-02-15 11:19:01 -08001227 if (threadEnv->GetCritical() > 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001228 AbortF("thread %s using JNI after critical get",
1229 ToStr<Thread>(*self).c_str());
1230 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001231 }
1232 break;
1233 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001234 // Don't check here; we allow nested gets.
Ian Rogersac4d45a2018-02-15 11:19:01 -08001235 if (threadEnv->GetCritical() == 0) {
1236 threadEnv->SetCriticalStartUs(self->GetCpuMicroTime());
Ian Rogers55256cb2017-12-21 17:07:11 -08001237 }
Ian Rogersac4d45a2018-02-15 11:19:01 -08001238 threadEnv->SetCritical(threadEnv->GetCritical() + 1);
Elliott Hughesa2501992011-08-26 19:39:54 -07001239 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001240 case kFlag_CritRelease: // this is a "release" call
Ian Rogersac4d45a2018-02-15 11:19:01 -08001241 if (threadEnv->GetCritical() == 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001242 AbortF("thread %s called too many critical releases",
1243 ToStr<Thread>(*self).c_str());
1244 return false;
Ian Rogersac4d45a2018-02-15 11:19:01 -08001245 } else if (threadEnv->GetCritical() == 1) {
Ian Rogers55256cb2017-12-21 17:07:11 -08001246 // Leaving the critical region, possibly warn about long critical regions.
Ian Rogersac4d45a2018-02-15 11:19:01 -08001247 uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->GetCriticalStartUs();
Ian Rogers55256cb2017-12-21 17:07:11 -08001248 if (critical_duration_us > kCriticalWarnTimeUs) {
1249 LOG(WARNING) << "JNI critical lock held for "
1250 << PrettyDuration(UsToNs(critical_duration_us)) << " on " << *self;
1251 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001252 }
Ian Rogersac4d45a2018-02-15 11:19:01 -08001253 threadEnv->SetCritical(threadEnv->GetCritical() - 1);
Elliott Hughesa2501992011-08-26 19:39:54 -07001254 break;
1255 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001256 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001257 }
1258
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001259 // Verify that, if an exception has been raised, the native code doesn't
1260 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001261 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001262 mirror::Throwable* exception = self->GetException();
1263 AbortF("JNI %s called with pending exception %s",
1264 function_name_,
1265 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001266 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001267 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001268 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001269 }
1270
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001271 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001272 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001273 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001274 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001275 AbortF("non-nullable const char* was NULL");
1276 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001277 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001278 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001279 }
1280
Ian Rogersef7d42f2014-01-06 12:55:46 -08001281 const char* errorKind = nullptr;
Andreas Gampeef4afe92015-07-27 21:03:25 -07001282 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001283 if (errorKind != nullptr) {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001284 // This is an expensive loop that will resize often, but this isn't supposed to hit in
1285 // practice anyways.
1286 std::ostringstream oss;
1287 oss << std::hex;
1288 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1289 while (*tmp != 0) {
1290 if (tmp == utf8) {
1291 oss << "<";
1292 }
1293 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1294 if (tmp == utf8) {
1295 oss << '>';
1296 }
1297 tmp++;
1298 if (*tmp != 0) {
1299 oss << ' ';
1300 }
1301 }
1302
Ian Rogers68d8b422014-07-17 11:09:10 -07001303 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
Andreas Gampeef4afe92015-07-27 21:03:25 -07001304 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001305 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001306 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001307 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001308 }
1309
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001310 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1311 // sequences in place of encoded surrogate pairs.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001312 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001313 while (*bytes != '\0') {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001314 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
Elliott Hughesa2501992011-08-26 19:39:54 -07001315 // Switch on the high four bits.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001316 switch (*utf8 >> 4) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001317 case 0x00:
1318 case 0x01:
1319 case 0x02:
1320 case 0x03:
1321 case 0x04:
1322 case 0x05:
1323 case 0x06:
1324 case 0x07:
1325 // Bit pattern 0xxx. No need for any extra bytes.
1326 break;
1327 case 0x08:
1328 case 0x09:
1329 case 0x0a:
1330 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001331 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001332 *errorKind = "start";
1333 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001334 case 0x0f:
1335 // Bit pattern 1111, which might be the start of a 4 byte sequence.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001336 if ((*utf8 & 0x08) == 0) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001337 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1338 // We consume one continuation byte here, and fall through to consume two more.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001339 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1340 if ((*utf8 & 0xc0) != 0x80) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001341 *errorKind = "continuation";
1342 return utf8;
1343 }
1344 } else {
1345 *errorKind = "start";
1346 return utf8;
1347 }
1348
1349 // Fall through to the cases below to consume two more continuation bytes.
1350 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001351 case 0x0e:
1352 // Bit pattern 1110, so there are two additional bytes.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001353 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1354 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001355 *errorKind = "continuation";
1356 return utf8;
1357 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001358
1359 // Fall through to consume one more continuation byte.
1360 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001361 case 0x0c:
1362 case 0x0d:
1363 // Bit pattern 110x, so there is one additional byte.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001364 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1365 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001366 *errorKind = "continuation";
1367 return utf8;
1368 }
1369 break;
1370 }
1371 }
1372 return 0;
1373 }
1374
Ian Rogers68d8b422014-07-17 11:09:10 -07001375 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1376 va_list args;
1377 va_start(args, fmt);
1378 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1379 va_end(args);
1380 }
1381
1382 // The name of the JNI function being checked.
1383 const char* const function_name_;
1384
Elliott Hughes92cb4982011-12-16 16:57:28 -08001385 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001386
Ian Rogers55256cb2017-12-21 17:07:11 -08001387 const uint16_t flags_;
1388
Ian Rogers68d8b422014-07-17 11:09:10 -07001389 const bool has_method_;
1390
Elliott Hughesa2501992011-08-26 19:39:54 -07001391 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1392};
1393
Elliott Hughesa2501992011-08-26 19:39:54 -07001394/*
1395 * ===========================================================================
1396 * Guarded arrays
1397 * ===========================================================================
1398 */
1399
Elliott Hughesa2501992011-08-26 19:39:54 -07001400/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001401class GuardedCopy {
1402 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001403 /*
1404 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1405 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001406 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001407 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001408 const size_t new_len = LengthIncludingRedZones(len);
1409 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001410
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001411 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001412 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001413 if (!mod_okay) {
1414 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001415 }
1416
Ian Rogers68d8b422014-07-17 11:09:10 -07001417 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001418
Ian Rogers68d8b422014-07-17 11:09:10 -07001419 // Fill begin region with canary pattern.
1420 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1421 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1422 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1423 if (kCanary[j] == '\0') {
1424 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001425 } else {
1426 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001427 }
1428 }
1429
1430 // Copy the data in; note "len" could be zero.
1431 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1432
1433 // Fill end region with canary pattern.
1434 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1435 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1436 if (kCanary[j] == '\0') {
1437 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001438 } else {
1439 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001440 }
1441 }
1442
1443 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001444 }
1445
1446 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001447 * Create a guarded copy of a primitive array. Modifications to the copied
1448 * data are allowed. Returns a pointer to the copied data.
1449 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001450 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1451 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001452 ScopedObjectAccess soa(env);
1453
Mathieu Chartier0795f232016-09-27 18:43:30 -07001454 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Ian Rogers68d8b422014-07-17 11:09:10 -07001455 size_t component_size = a->GetClass()->GetComponentSize();
1456 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001457 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001458 if (is_copy != nullptr) {
1459 *is_copy = JNI_TRUE;
1460 }
1461 return result;
1462 }
1463
1464 /*
1465 * Perform the array "release" operation, which may or may not copy data
1466 * back into the managed heap, and may or may not release the underlying storage.
1467 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001468 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1469 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1470 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001471 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001472 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1473 return nullptr;
1474 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001475 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1476 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001477 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001478 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001479 }
1480 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001481 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001482 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001483 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001484 }
1485
1486
1487 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001488 * Free up the guard buffer, scrub it, and return the original pointer.
1489 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001490 static void* Destroy(void* embedded_buf) {
1491 GuardedCopy* copy = FromEmbedded(embedded_buf);
1492 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1493 size_t len = LengthIncludingRedZones(copy->original_length_);
1494 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001495 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001496 }
1497
1498 /*
1499 * Verify the guard area and, if "modOkay" is false, that the data itself
1500 * has not been altered.
1501 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001502 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001503 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001504 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1505 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1506 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001507 }
1508
1509 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001510 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001511 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1512 }
1513
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001514 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001515 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001516 if (result == MAP_FAILED) {
1517 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1518 }
1519 return reinterpret_cast<uint8_t*>(result);
1520 }
1521
Ian Rogers68d8b422014-07-17 11:09:10 -07001522 static void DebugFree(void* buf, size_t len) {
1523 if (munmap(buf, len) != 0) {
1524 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001525 }
1526 }
1527
Ian Rogers68d8b422014-07-17 11:09:10 -07001528 static size_t LengthIncludingRedZones(size_t len) {
1529 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001530 }
1531
Ian Rogers68d8b422014-07-17 11:09:10 -07001532 // Get the GuardedCopy from the interior pointer.
1533 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1534 return reinterpret_cast<GuardedCopy*>(
1535 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001536 }
1537
Ian Rogers68d8b422014-07-17 11:09:10 -07001538 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1539 return reinterpret_cast<const GuardedCopy*>(
1540 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001541 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001542
1543 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1544 va_list args;
1545 va_start(args, fmt);
1546 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1547 va_end(args);
1548 }
1549
1550 bool CheckHeader(const char* function_name, bool mod_okay) const {
1551 static const uint32_t kMagicCmp = kGuardMagic;
1552
1553 // Before we do anything with "pExtra", check the magic number. We
1554 // do the check with memcmp rather than "==" in case the pointer is
1555 // unaligned. If it points to completely bogus memory we're going
1556 // to crash, but there's no easy way around that.
1557 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1558 uint8_t buf[4];
1559 memcpy(buf, &magic_, 4);
1560 AbortF(function_name,
1561 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1562 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1563 return false;
1564 }
1565
1566 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1567 // told the client that we made a copy, there's no reason they can't alter the buffer.
1568 if (!mod_okay) {
1569 uLong computed_adler =
1570 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1571 if (computed_adler != adler_) {
1572 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1573 computed_adler, adler_, this);
1574 return false;
1575 }
1576 }
1577 return true;
1578 }
1579
1580 bool CheckRedZones(const char* function_name) const {
1581 // Check the begin red zone.
1582 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1583 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1584 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1585 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1586 return false;
1587 }
1588 if (kCanary[j] == '\0') {
1589 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001590 } else {
1591 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001592 }
1593 }
1594
1595 // Check end region.
1596 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1597 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1598 size_t offset_from_buffer_start =
1599 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1600 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1601 offset_from_buffer_start);
1602 return false;
1603 }
1604 if (kCanary[j] == '\0') {
1605 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001606 } else {
1607 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001608 }
1609 }
1610 return true;
1611 }
1612
1613 // Location that canary value will be written before the guarded region.
1614 const char* StartRedZone() const {
1615 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1616 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1617 }
1618
1619 // Return the interior embedded buffer.
1620 const uint8_t* BufferWithinRedZones() const {
1621 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1622 return embedded_buf;
1623 }
1624
1625 // Location that canary value will be written after the guarded region.
1626 const char* EndRedZone() const {
1627 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1628 size_t buf_len = LengthIncludingRedZones(original_length_);
1629 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1630 }
1631
1632 static constexpr size_t kRedZoneSize = 512;
1633 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1634
1635 // Value written before and after the guarded array.
1636 static const char* const kCanary;
1637
1638 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1639
1640 const uint32_t magic_;
1641 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001642 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001643 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001644};
Ian Rogers68d8b422014-07-17 11:09:10 -07001645const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001646
1647/*
1648 * ===========================================================================
1649 * JNI functions
1650 * ===========================================================================
1651 */
1652
1653class CheckJNI {
1654 public:
1655 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001656 ScopedObjectAccess soa(env);
1657 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1658 JniValueType args[1] = {{.E = env }};
1659 if (sc.Check(soa, true, "E", args)) {
1660 JniValueType result;
1661 result.I = baseEnv(env)->GetVersion(env);
1662 if (sc.Check(soa, false, "I", &result)) {
1663 return result.I;
1664 }
1665 }
1666 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001667 }
1668
Ian Rogers68d8b422014-07-17 11:09:10 -07001669 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1670 ScopedObjectAccess soa(env);
1671 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1672 JniValueType args[2] = {{.E = env }, {.p = vm}};
1673 if (sc.Check(soa, true, "Ep", args)) {
1674 JniValueType result;
1675 result.i = baseEnv(env)->GetJavaVM(env, vm);
1676 if (sc.Check(soa, false, "i", &result)) {
1677 return result.i;
1678 }
1679 }
1680 return JNI_ERR;
1681 }
1682
1683 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1684 ScopedObjectAccess soa(env);
1685 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1686 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1687 if (sc.Check(soa, true, "EcpI", args)) {
1688 JniValueType result;
1689 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1690 if (sc.Check(soa, false, "i", &result)) {
1691 return result.i;
1692 }
1693 }
1694 return JNI_ERR;
1695 }
1696
1697 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1698 ScopedObjectAccess soa(env);
1699 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1700 JniValueType args[2] = {{.E = env }, {.c = c}};
1701 if (sc.Check(soa, true, "Ec", args)) {
1702 JniValueType result;
1703 result.i = baseEnv(env)->UnregisterNatives(env, c);
1704 if (sc.Check(soa, false, "i", &result)) {
1705 return result.i;
1706 }
1707 }
1708 return JNI_ERR;
1709 }
1710
1711 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001712 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1713 // know the object is invalid. The spec says that passing invalid objects or even ones that
1714 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001715 ScopedObjectAccess soa(env);
1716 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001717 JniValueType args[2] = {{.E = env }, {.L = obj}};
1718 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001719 JniValueType result;
1720 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1721 if (sc.Check(soa, false, "w", &result)) {
1722 return result.w;
1723 }
1724 }
1725 return JNIInvalidRefType;
1726 }
1727
1728 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1729 jsize bufLen) {
1730 ScopedObjectAccess soa(env);
1731 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1732 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1733 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1734 JniValueType result;
1735 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1736 if (sc.Check(soa, false, "c", &result)) {
1737 return result.c;
1738 }
1739 }
1740 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001741 }
1742
1743 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001744 ScopedObjectAccess soa(env);
1745 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1746 JniValueType args[2] = {{.E = env}, {.u = name}};
1747 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1748 JniValueType result;
1749 result.c = baseEnv(env)->FindClass(env, name);
1750 if (sc.Check(soa, false, "c", &result)) {
1751 return result.c;
1752 }
1753 }
1754 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001755 }
1756
Elliott Hughese84278b2012-03-22 10:06:53 -07001757 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001758 ScopedObjectAccess soa(env);
1759 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1760 JniValueType args[2] = {{.E = env}, {.c = c}};
1761 if (sc.Check(soa, true, "Ec", args)) {
1762 JniValueType result;
1763 result.c = baseEnv(env)->GetSuperclass(env, c);
1764 if (sc.Check(soa, false, "c", &result)) {
1765 return result.c;
1766 }
1767 }
1768 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001769 }
1770
Elliott Hughese84278b2012-03-22 10:06:53 -07001771 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001772 ScopedObjectAccess soa(env);
1773 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1774 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1775 if (sc.Check(soa, true, "Ecc", args)) {
1776 JniValueType result;
1777 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1778 if (sc.Check(soa, false, "b", &result)) {
1779 return result.b;
1780 }
1781 }
1782 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001783 }
1784
1785 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001786 ScopedObjectAccess soa(env);
1787 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1788 JniValueType args[2] = {{.E = env}, {.L = method}};
1789 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1790 JniValueType result;
1791 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1792 if (sc.Check(soa, false, "m", &result)) {
1793 return result.m;
1794 }
1795 }
1796 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001797 }
1798
1799 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001800 ScopedObjectAccess soa(env);
1801 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1802 JniValueType args[2] = {{.E = env}, {.L = field}};
1803 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1804 JniValueType result;
1805 result.f = baseEnv(env)->FromReflectedField(env, field);
1806 if (sc.Check(soa, false, "f", &result)) {
1807 return result.f;
1808 }
1809 }
1810 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001811 }
1812
1813 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001814 ScopedObjectAccess soa(env);
1815 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1816 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1817 if (sc.Check(soa, true, "Ecmb", args)) {
1818 JniValueType result;
1819 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1820 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1821 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1822 return result.L;
1823 }
1824 }
1825 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001826 }
1827
1828 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001829 ScopedObjectAccess soa(env);
1830 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1831 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1832 if (sc.Check(soa, true, "Ecfb", args)) {
1833 JniValueType result;
1834 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1835 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1836 DCHECK(sc.CheckReflectedField(soa, result.L));
1837 return result.L;
1838 }
1839 }
1840 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001841 }
1842
1843 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001844 ScopedObjectAccess soa(env);
1845 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1846 JniValueType args[2] = {{.E = env}, {.t = obj}};
1847 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1848 JniValueType result;
1849 result.i = baseEnv(env)->Throw(env, obj);
1850 if (sc.Check(soa, false, "i", &result)) {
1851 return result.i;
1852 }
1853 }
1854 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001855 }
1856
Elliott Hughese84278b2012-03-22 10:06:53 -07001857 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001858 ScopedObjectAccess soa(env);
1859 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001860 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001861 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1862 JniValueType result;
1863 result.i = baseEnv(env)->ThrowNew(env, c, message);
1864 if (sc.Check(soa, false, "i", &result)) {
1865 return result.i;
1866 }
1867 }
1868 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001869 }
1870
1871 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001872 ScopedObjectAccess soa(env);
1873 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1874 JniValueType args[1] = {{.E = env}};
1875 if (sc.Check(soa, true, "E", args)) {
1876 JniValueType result;
1877 result.t = baseEnv(env)->ExceptionOccurred(env);
1878 if (sc.Check(soa, false, "t", &result)) {
1879 return result.t;
1880 }
1881 }
1882 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001883 }
1884
1885 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001886 ScopedObjectAccess soa(env);
1887 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1888 JniValueType args[1] = {{.E = env}};
1889 if (sc.Check(soa, true, "E", args)) {
1890 JniValueType result;
1891 baseEnv(env)->ExceptionDescribe(env);
1892 result.V = nullptr;
1893 sc.Check(soa, false, "V", &result);
1894 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001895 }
1896
1897 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001898 ScopedObjectAccess soa(env);
1899 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1900 JniValueType args[1] = {{.E = env}};
1901 if (sc.Check(soa, true, "E", args)) {
1902 JniValueType result;
1903 baseEnv(env)->ExceptionClear(env);
1904 result.V = nullptr;
1905 sc.Check(soa, false, "V", &result);
1906 }
1907 }
1908
1909 static jboolean ExceptionCheck(JNIEnv* env) {
1910 ScopedObjectAccess soa(env);
1911 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1912 JniValueType args[1] = {{.E = env}};
1913 if (sc.Check(soa, true, "E", args)) {
1914 JniValueType result;
1915 result.b = baseEnv(env)->ExceptionCheck(env);
1916 if (sc.Check(soa, false, "b", &result)) {
1917 return result.b;
1918 }
1919 }
1920 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001921 }
1922
1923 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001924 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1925 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1926 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001927 ScopedObjectAccess soa(env);
1928 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1929 JniValueType args[2] = {{.E = env}, {.u = msg}};
1930 if (sc.Check(soa, true, "Eu", args)) {
1931 JniValueType result;
1932 baseEnv(env)->FatalError(env, msg);
1933 // Unreachable.
1934 result.V = nullptr;
1935 sc.Check(soa, false, "V", &result);
1936 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001937 }
1938
1939 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001940 ScopedObjectAccess soa(env);
1941 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1942 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1943 if (sc.Check(soa, true, "EI", args)) {
1944 JniValueType result;
1945 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1946 if (sc.Check(soa, false, "i", &result)) {
1947 return result.i;
1948 }
1949 }
1950 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001951 }
1952
1953 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001954 ScopedObjectAccess soa(env);
1955 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1956 JniValueType args[2] = {{.E = env}, {.L = res}};
1957 if (sc.Check(soa, true, "EL", args)) {
1958 JniValueType result;
1959 result.L = baseEnv(env)->PopLocalFrame(env, res);
1960 sc.Check(soa, false, "L", &result);
1961 return result.L;
1962 }
1963 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001964 }
1965
1966 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001967 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001968 }
1969
Ian Rogers68d8b422014-07-17 11:09:10 -07001970 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1971 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001972 }
1973
1974 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001975 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001976 }
1977
Ian Rogers68d8b422014-07-17 11:09:10 -07001978 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1979 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001980 }
1981
Ian Rogers68d8b422014-07-17 11:09:10 -07001982 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1983 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1984 }
1985
1986 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1987 DeleteRef(__FUNCTION__, env, obj, kLocal);
1988 }
1989
1990 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1991 ScopedObjectAccess soa(env);
1992 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1993 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1994 if (sc.Check(soa, true, "EI", args)) {
1995 JniValueType result;
1996 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1997 if (sc.Check(soa, false, "i", &result)) {
1998 return result.i;
1999 }
2000 }
2001 return JNI_ERR;
2002 }
2003
2004 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
2005 ScopedObjectAccess soa(env);
2006 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2007 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
2008 if (sc.Check(soa, true, "ELL", args)) {
2009 JniValueType result;
2010 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
2011 if (sc.Check(soa, false, "b", &result)) {
2012 return result.b;
2013 }
2014 }
2015 return JNI_FALSE;
2016 }
2017
2018 static jobject AllocObject(JNIEnv* env, jclass c) {
2019 ScopedObjectAccess soa(env);
2020 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2021 JniValueType args[2] = {{.E = env}, {.c = c}};
2022 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
2023 JniValueType result;
2024 result.L = baseEnv(env)->AllocObject(env, c);
2025 if (sc.Check(soa, false, "L", &result)) {
2026 return result.L;
2027 }
2028 }
2029 return nullptr;
2030 }
2031
2032 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2033 ScopedObjectAccess soa(env);
2034 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002035 VarArgs rest(mid, vargs);
2036 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2037 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002038 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002039 JniValueType result;
2040 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2041 if (sc.Check(soa, false, "L", &result)) {
2042 return result.L;
2043 }
2044 }
2045 return nullptr;
2046 }
2047
2048 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2049 va_list args;
2050 va_start(args, mid);
2051 jobject result = NewObjectV(env, c, mid, args);
2052 va_end(args);
2053 return result;
2054 }
2055
2056 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2057 ScopedObjectAccess soa(env);
2058 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002059 VarArgs rest(mid, vargs);
2060 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2061 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002062 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002063 JniValueType result;
2064 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2065 if (sc.Check(soa, false, "L", &result)) {
2066 return result.L;
2067 }
2068 }
2069 return nullptr;
2070 }
2071
2072 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2073 ScopedObjectAccess soa(env);
2074 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2075 JniValueType args[2] = {{.E = env}, {.L = obj}};
2076 if (sc.Check(soa, true, "EL", args)) {
2077 JniValueType result;
2078 result.c = baseEnv(env)->GetObjectClass(env, obj);
2079 if (sc.Check(soa, false, "c", &result)) {
2080 return result.c;
2081 }
2082 }
2083 return nullptr;
2084 }
2085
2086 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2087 ScopedObjectAccess soa(env);
2088 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2089 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2090 if (sc.Check(soa, true, "ELc", args)) {
2091 JniValueType result;
2092 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2093 if (sc.Check(soa, false, "b", &result)) {
2094 return result.b;
2095 }
2096 }
2097 return JNI_FALSE;
2098 }
2099
2100 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2101 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2102 }
2103
2104 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2105 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2106 }
2107
2108 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2109 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2110 }
2111
2112 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2113 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2114 }
2115
2116#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
2117 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2118 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2119 } \
2120 \
2121 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2122 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2123 } \
2124 \
2125 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2126 JniValueType value; \
2127 value.shorty = v; \
2128 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2129 } \
2130 \
2131 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2132 JniValueType value; \
2133 value.shorty = v; \
2134 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2135 }
2136
2137 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
2138 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2139 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
2140 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
2141 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
2142 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
2143 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
2144 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
2145 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
2146#undef FIELD_ACCESSORS
2147
2148 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
2149 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2150 }
2151
2152 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2153 jvalue* vargs) {
2154 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2155 }
2156
2157 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01002158 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07002159 }
2160
2161 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2162 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2163 }
2164
2165 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2166 va_list vargs) {
2167 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2168 }
2169
2170 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2171 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2172 }
2173
2174 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2175 va_list vargs;
2176 va_start(vargs, mid);
2177 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2178 va_end(vargs);
2179 }
2180
2181 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2182 va_list vargs;
2183 va_start(vargs, mid);
2184 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2185 va_end(vargs);
2186 }
2187
2188 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2189 va_list vargs;
2190 va_start(vargs, mid);
2191 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2192 va_end(vargs);
2193 }
2194
2195#define CALL(rtype, name, ptype, shorty) \
2196 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
2197 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2198 } \
2199 \
2200 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2201 jvalue* vargs) { \
2202 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2203 } \
2204 \
2205 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2206 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2207 } \
2208 \
2209 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2210 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2211 } \
2212 \
2213 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2214 va_list vargs) { \
2215 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2216 } \
2217 \
2218 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2219 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2220 } \
2221 \
2222 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2223 va_list vargs; \
2224 va_start(vargs, mid); \
2225 rtype result = \
2226 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2227 va_end(vargs); \
2228 return result; \
2229 } \
2230 \
2231 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2232 ...) { \
2233 va_list vargs; \
2234 va_start(vargs, mid); \
2235 rtype result = \
2236 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2237 va_end(vargs); \
2238 return result; \
2239 } \
2240 \
2241 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2242 va_list vargs; \
2243 va_start(vargs, mid); \
2244 rtype result = \
2245 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2246 va_end(vargs); \
2247 return result; \
2248 }
2249
2250 CALL(jobject, Object, Primitive::kPrimNot, L)
2251 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2252 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2253 CALL(jchar, Char, Primitive::kPrimChar, C)
2254 CALL(jshort, Short, Primitive::kPrimShort, S)
2255 CALL(jint, Int, Primitive::kPrimInt, I)
2256 CALL(jlong, Long, Primitive::kPrimLong, J)
2257 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2258 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2259#undef CALL
2260
2261 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2262 ScopedObjectAccess soa(env);
2263 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2264 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2265 if (sc.Check(soa, true, "Epz", args)) {
2266 JniValueType result;
2267 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2268 if (sc.Check(soa, false, "s", &result)) {
2269 return result.s;
2270 }
2271 }
2272 return nullptr;
2273 }
2274
2275 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2276 ScopedObjectAccess soa(env);
2277 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2278 JniValueType args[2] = {{.E = env}, {.u = chars}};
2279 if (sc.Check(soa, true, "Eu", args)) {
2280 JniValueType result;
2281 // TODO: stale? show pointer and truncate string.
2282 result.s = baseEnv(env)->NewStringUTF(env, chars);
2283 if (sc.Check(soa, false, "s", &result)) {
2284 return result.s;
2285 }
2286 }
2287 return nullptr;
2288 }
2289
2290 static jsize GetStringLength(JNIEnv* env, jstring string) {
2291 ScopedObjectAccess soa(env);
2292 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2293 JniValueType args[2] = {{.E = env}, {.s = string}};
2294 if (sc.Check(soa, true, "Es", args)) {
2295 JniValueType result;
2296 result.z = baseEnv(env)->GetStringLength(env, string);
2297 if (sc.Check(soa, false, "z", &result)) {
2298 return result.z;
2299 }
2300 }
2301 return JNI_ERR;
2302 }
2303
2304 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2305 ScopedObjectAccess soa(env);
2306 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2307 JniValueType args[2] = {{.E = env}, {.s = string}};
2308 if (sc.Check(soa, true, "Es", args)) {
2309 JniValueType result;
2310 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2311 if (sc.Check(soa, false, "z", &result)) {
2312 return result.z;
2313 }
2314 }
2315 return JNI_ERR;
2316 }
2317
2318 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2319 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2320 is_copy, false, false));
2321 }
2322
2323 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2324 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2325 is_copy, true, false));
2326 }
2327
2328 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2329 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2330 is_copy, false, true));
2331 }
2332
2333 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2334 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2335 }
2336
2337 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2338 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2339 }
2340
2341 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2342 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2343 }
2344
2345 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2346 ScopedObjectAccess soa(env);
2347 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2348 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2349 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2350 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2351 if (sc.Check(soa, true, "EsIIp", args)) {
2352 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2353 JniValueType result;
2354 result.V = nullptr;
2355 sc.Check(soa, false, "V", &result);
2356 }
2357 }
2358
2359 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2360 ScopedObjectAccess soa(env);
2361 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2362 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2363 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2364 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2365 if (sc.Check(soa, true, "EsIIp", args)) {
2366 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2367 JniValueType result;
2368 result.V = nullptr;
2369 sc.Check(soa, false, "V", &result);
2370 }
2371 }
2372
2373 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2374 ScopedObjectAccess soa(env);
2375 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2376 JniValueType args[2] = {{.E = env}, {.a = array}};
2377 if (sc.Check(soa, true, "Ea", args)) {
2378 JniValueType result;
2379 result.z = baseEnv(env)->GetArrayLength(env, array);
2380 if (sc.Check(soa, false, "z", &result)) {
2381 return result.z;
2382 }
2383 }
2384 return JNI_ERR;
2385 }
2386
2387 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2388 jobject initial_element) {
2389 ScopedObjectAccess soa(env);
2390 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2391 JniValueType args[4] =
2392 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2393 if (sc.Check(soa, true, "EzcL", args)) {
2394 JniValueType result;
2395 // Note: assignability tests of initial_element are done in the base implementation.
2396 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2397 if (sc.Check(soa, false, "a", &result)) {
2398 return down_cast<jobjectArray>(result.a);
2399 }
2400 }
2401 return nullptr;
2402 }
2403
2404 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2405 ScopedObjectAccess soa(env);
2406 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2407 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2408 if (sc.Check(soa, true, "Eaz", args)) {
2409 JniValueType result;
2410 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2411 if (sc.Check(soa, false, "L", &result)) {
2412 return result.L;
2413 }
2414 }
2415 return nullptr;
2416 }
2417
2418 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2419 ScopedObjectAccess soa(env);
2420 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2421 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2422 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2423 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2424 // in ArrayStoreExceptions.
2425 if (sc.Check(soa, true, "EaIL", args)) {
2426 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2427 JniValueType result;
2428 result.V = nullptr;
2429 sc.Check(soa, false, "V", &result);
2430 }
2431 }
2432
2433 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2434 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2435 Primitive::kPrimBoolean));
2436 }
2437
2438 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2439 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2440 Primitive::kPrimByte));
2441 }
2442
2443 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2444 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2445 Primitive::kPrimChar));
2446 }
2447
2448 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2449 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2450 Primitive::kPrimShort));
2451 }
2452
2453 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2454 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2455 }
2456
2457 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2458 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2459 Primitive::kPrimLong));
2460 }
2461
2462 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2463 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2464 Primitive::kPrimFloat));
2465 }
2466
2467 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2468 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2469 Primitive::kPrimDouble));
2470 }
2471
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002472// NOLINT added to avoid wrong warning/fix from clang-tidy.
Ian Rogers68d8b422014-07-17 11:09:10 -07002473#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002474 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2475 return reinterpret_cast<ctype*>( /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002476 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2477 } \
2478 \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002479 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002480 jint mode) { \
2481 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2482 } \
2483 \
2484 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002485 ctype* buf) { /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002486 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2487 } \
2488 \
2489 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2490 const ctype* buf) { \
2491 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2492 }
2493
2494 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2495 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2496 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2497 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2498 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2499 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2500 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2501 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2502#undef PRIMITIVE_ARRAY_FUNCTIONS
2503
2504 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2505 ScopedObjectAccess soa(env);
2506 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2507 JniValueType args[2] = {{.E = env}, {.L = obj}};
2508 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002509 if (obj != nullptr) {
2510 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2511 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002512 JniValueType result;
2513 result.i = baseEnv(env)->MonitorEnter(env, obj);
2514 if (sc.Check(soa, false, "i", &result)) {
2515 return result.i;
2516 }
2517 }
2518 return JNI_ERR;
2519 }
2520
2521 static jint MonitorExit(JNIEnv* env, jobject obj) {
2522 ScopedObjectAccess soa(env);
2523 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2524 JniValueType args[2] = {{.E = env}, {.L = obj}};
2525 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002526 if (obj != nullptr) {
2527 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2528 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002529 JniValueType result;
2530 result.i = baseEnv(env)->MonitorExit(env, obj);
2531 if (sc.Check(soa, false, "i", &result)) {
2532 return result.i;
2533 }
2534 }
2535 return JNI_ERR;
2536 }
2537
2538 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2539 ScopedObjectAccess soa(env);
2540 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2541 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2542 if (sc.Check(soa, true, "Eap", args)) {
2543 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002544 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2545 if (ptr != nullptr && soa.ForceCopy()) {
2546 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002547 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002548 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002549 if (sc.Check(soa, false, "p", &result)) {
2550 return const_cast<void*>(result.p);
2551 }
2552 }
2553 return nullptr;
2554 }
2555
2556 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2557 ScopedObjectAccess soa(env);
2558 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2559 sc.CheckNonNull(carray);
2560 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2561 if (sc.Check(soa, true, "Eapr", args)) {
2562 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002563 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002564 }
2565 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2566 JniValueType result;
2567 result.V = nullptr;
2568 sc.Check(soa, false, "V", &result);
2569 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002570 }
2571
2572 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002573 ScopedObjectAccess soa(env);
2574 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2575 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2576 if (sc.Check(soa, true, "EpJ", args)) {
2577 JniValueType result;
2578 // Note: the validity of address and capacity are checked in the base implementation.
2579 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2580 if (sc.Check(soa, false, "L", &result)) {
2581 return result.L;
2582 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002583 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002584 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002585 }
2586
2587 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002588 ScopedObjectAccess soa(env);
2589 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2590 JniValueType args[2] = {{.E = env}, {.L = buf}};
2591 if (sc.Check(soa, true, "EL", args)) {
2592 JniValueType result;
2593 // Note: this is implemented in the base environment by a GetLongField which will sanity
2594 // check the type of buf in GetLongField above.
2595 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2596 if (sc.Check(soa, false, "p", &result)) {
2597 return const_cast<void*>(result.p);
2598 }
2599 }
2600 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002601 }
2602
2603 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002604 ScopedObjectAccess soa(env);
2605 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2606 JniValueType args[2] = {{.E = env}, {.L = buf}};
2607 if (sc.Check(soa, true, "EL", args)) {
2608 JniValueType result;
2609 // Note: this is implemented in the base environment by a GetIntField which will sanity
2610 // check the type of buf in GetIntField above.
2611 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2612 if (sc.Check(soa, false, "J", &result)) {
2613 return result.J;
2614 }
2615 }
2616 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002617 }
2618
2619 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002620 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
Ian Rogers55256cb2017-12-21 17:07:11 -08002621 return reinterpret_cast<JNIEnvExt*>(env)->GetVm();
Ian Rogers68d8b422014-07-17 11:09:10 -07002622 }
2623
2624 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Ian Rogersac4d45a2018-02-15 11:19:01 -08002625 return reinterpret_cast<JNIEnvExt*>(env)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07002626 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002627
2628 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2629 ScopedObjectAccess soa(env);
2630 ScopedCheck sc(kFlag_Default, function_name);
2631 JniValueType args[2] = {{.E = env}, {.L = obj}};
2632 if (sc.Check(soa, true, "EL", args)) {
2633 JniValueType result;
2634 switch (kind) {
2635 case kGlobal:
2636 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2637 break;
2638 case kLocal:
2639 result.L = baseEnv(env)->NewLocalRef(env, obj);
2640 break;
2641 case kWeakGlobal:
2642 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2643 break;
2644 default:
2645 LOG(FATAL) << "Unexpected reference kind: " << kind;
2646 }
2647 if (sc.Check(soa, false, "L", &result)) {
2648 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002649 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002650 return result.L;
2651 }
2652 }
2653 return nullptr;
2654 }
2655
2656 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2657 ScopedObjectAccess soa(env);
2658 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2659 JniValueType args[2] = {{.E = env}, {.L = obj}};
2660 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002661 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002662 JniValueType result;
2663 switch (kind) {
2664 case kGlobal:
2665 baseEnv(env)->DeleteGlobalRef(env, obj);
2666 break;
2667 case kLocal:
2668 baseEnv(env)->DeleteLocalRef(env, obj);
2669 break;
2670 case kWeakGlobal:
2671 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2672 break;
2673 default:
2674 LOG(FATAL) << "Unexpected reference kind: " << kind;
2675 }
2676 result.V = nullptr;
2677 sc.Check(soa, false, "V", &result);
2678 }
2679 }
2680
2681 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2682 const char* name, const char* sig, bool is_static) {
2683 ScopedObjectAccess soa(env);
2684 ScopedCheck sc(kFlag_Default, function_name);
2685 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2686 if (sc.Check(soa, true, "Ecuu", args)) {
2687 JniValueType result;
2688 if (is_static) {
2689 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2690 } else {
2691 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2692 }
2693 if (sc.Check(soa, false, "m", &result)) {
2694 return result.m;
2695 }
2696 }
2697 return nullptr;
2698 }
2699
2700 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2701 const char* name, const char* sig, bool is_static) {
2702 ScopedObjectAccess soa(env);
2703 ScopedCheck sc(kFlag_Default, function_name);
2704 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2705 if (sc.Check(soa, true, "Ecuu", args)) {
2706 JniValueType result;
2707 if (is_static) {
2708 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2709 } else {
2710 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2711 }
2712 if (sc.Check(soa, false, "f", &result)) {
2713 return result.f;
2714 }
2715 }
2716 return nullptr;
2717 }
2718
2719 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2720 bool is_static, Primitive::Type type) {
2721 ScopedObjectAccess soa(env);
2722 ScopedCheck sc(kFlag_Default, function_name);
2723 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2724 JniValueType result;
2725 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2726 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2727 const char* result_check = nullptr;
2728 switch (type) {
2729 case Primitive::kPrimNot:
2730 if (is_static) {
2731 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2732 } else {
2733 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2734 }
2735 result_check = "L";
2736 break;
2737 case Primitive::kPrimBoolean:
2738 if (is_static) {
2739 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2740 } else {
2741 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2742 }
2743 result_check = "Z";
2744 break;
2745 case Primitive::kPrimByte:
2746 if (is_static) {
2747 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2748 } else {
2749 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2750 }
2751 result_check = "B";
2752 break;
2753 case Primitive::kPrimChar:
2754 if (is_static) {
2755 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2756 } else {
2757 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2758 }
2759 result_check = "C";
2760 break;
2761 case Primitive::kPrimShort:
2762 if (is_static) {
2763 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2764 } else {
2765 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2766 }
2767 result_check = "S";
2768 break;
2769 case Primitive::kPrimInt:
2770 if (is_static) {
2771 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2772 } else {
2773 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2774 }
2775 result_check = "I";
2776 break;
2777 case Primitive::kPrimLong:
2778 if (is_static) {
2779 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2780 } else {
2781 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2782 }
2783 result_check = "J";
2784 break;
2785 case Primitive::kPrimFloat:
2786 if (is_static) {
2787 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2788 } else {
2789 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2790 }
2791 result_check = "F";
2792 break;
2793 case Primitive::kPrimDouble:
2794 if (is_static) {
2795 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2796 } else {
2797 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2798 }
2799 result_check = "D";
2800 break;
2801 case Primitive::kPrimVoid:
2802 LOG(FATAL) << "Unexpected type: " << type;
2803 break;
2804 }
2805 if (sc.Check(soa, false, result_check, &result)) {
2806 return result;
2807 }
2808 }
2809 result.J = 0;
2810 return result;
2811 }
2812
2813 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2814 bool is_static, Primitive::Type type, JniValueType value) {
2815 ScopedObjectAccess soa(env);
2816 ScopedCheck sc(kFlag_Default, function_name);
2817 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2818 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2819 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2820 if (sc.Check(soa, true, sig, args) &&
2821 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2822 switch (type) {
2823 case Primitive::kPrimNot:
2824 if (is_static) {
2825 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2826 } else {
2827 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2828 }
2829 break;
2830 case Primitive::kPrimBoolean:
2831 if (is_static) {
2832 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2833 } else {
2834 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2835 }
2836 break;
2837 case Primitive::kPrimByte:
2838 if (is_static) {
2839 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2840 } else {
2841 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2842 }
2843 break;
2844 case Primitive::kPrimChar:
2845 if (is_static) {
2846 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2847 } else {
2848 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2849 }
2850 break;
2851 case Primitive::kPrimShort:
2852 if (is_static) {
2853 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2854 } else {
2855 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2856 }
2857 break;
2858 case Primitive::kPrimInt:
2859 if (is_static) {
2860 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2861 } else {
2862 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2863 }
2864 break;
2865 case Primitive::kPrimLong:
2866 if (is_static) {
2867 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2868 } else {
2869 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2870 }
2871 break;
2872 case Primitive::kPrimFloat:
2873 if (is_static) {
2874 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2875 } else {
2876 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2877 }
2878 break;
2879 case Primitive::kPrimDouble:
2880 if (is_static) {
2881 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2882 } else {
2883 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2884 }
2885 break;
2886 case Primitive::kPrimVoid:
2887 LOG(FATAL) << "Unexpected type: " << type;
2888 break;
2889 }
2890 JniValueType result;
2891 result.V = nullptr;
2892 sc.Check(soa, false, "V", &result);
2893 }
2894 }
2895
2896 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
Alex Light48ffe062015-08-19 15:23:23 -07002897 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07002898 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002899 bool checked;
2900 switch (invoke) {
2901 case kVirtual: {
2902 DCHECK(c == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002903 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
2904 checked = sc.Check(soa, true, "ELm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002905 break;
2906 }
2907 case kDirect: {
Alex Light48ffe062015-08-19 15:23:23 -07002908 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
2909 checked = sc.Check(soa, true, "ELcm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002910 break;
2911 }
2912 case kStatic: {
2913 DCHECK(obj == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002914 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
2915 checked = sc.Check(soa, true, "Ecm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002916 break;
2917 }
2918 default:
2919 LOG(FATAL) << "Unexpected invoke: " << invoke;
2920 checked = false;
2921 break;
2922 }
2923 return checked;
2924 }
2925
2926 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2927 jmethodID mid, jvalue* vargs, Primitive::Type type,
2928 InvokeType invoke) {
2929 ScopedObjectAccess soa(env);
2930 ScopedCheck sc(kFlag_Default, function_name);
2931 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07002932 VarArgs rest(mid, vargs);
2933 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07002934 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2935 const char* result_check;
2936 switch (type) {
2937 case Primitive::kPrimNot:
2938 result_check = "L";
2939 switch (invoke) {
2940 case kVirtual:
2941 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2942 break;
2943 case kDirect:
2944 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2945 break;
2946 case kStatic:
2947 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2948 break;
2949 default:
2950 break;
2951 }
2952 break;
2953 case Primitive::kPrimBoolean:
2954 result_check = "Z";
2955 switch (invoke) {
2956 case kVirtual:
2957 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2958 break;
2959 case kDirect:
2960 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2961 break;
2962 case kStatic:
2963 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2964 break;
2965 default:
2966 break;
2967 }
2968 break;
2969 case Primitive::kPrimByte:
2970 result_check = "B";
2971 switch (invoke) {
2972 case kVirtual:
2973 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2974 break;
2975 case kDirect:
2976 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2977 break;
2978 case kStatic:
2979 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2980 break;
2981 default:
2982 break;
2983 }
2984 break;
2985 case Primitive::kPrimChar:
2986 result_check = "C";
2987 switch (invoke) {
2988 case kVirtual:
2989 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2990 break;
2991 case kDirect:
2992 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2993 break;
2994 case kStatic:
2995 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2996 break;
2997 default:
2998 break;
2999 }
3000 break;
3001 case Primitive::kPrimShort:
3002 result_check = "S";
3003 switch (invoke) {
3004 case kVirtual:
3005 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
3006 break;
3007 case kDirect:
3008 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
3009 break;
3010 case kStatic:
3011 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
3012 break;
3013 default:
3014 break;
3015 }
3016 break;
3017 case Primitive::kPrimInt:
3018 result_check = "I";
3019 switch (invoke) {
3020 case kVirtual:
3021 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
3022 break;
3023 case kDirect:
3024 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
3025 break;
3026 case kStatic:
3027 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
3028 break;
3029 default:
3030 break;
3031 }
3032 break;
3033 case Primitive::kPrimLong:
3034 result_check = "J";
3035 switch (invoke) {
3036 case kVirtual:
3037 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
3038 break;
3039 case kDirect:
3040 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3041 break;
3042 case kStatic:
3043 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3044 break;
3045 default:
3046 break;
3047 }
3048 break;
3049 case Primitive::kPrimFloat:
3050 result_check = "F";
3051 switch (invoke) {
3052 case kVirtual:
3053 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3054 break;
3055 case kDirect:
3056 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3057 break;
3058 case kStatic:
3059 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3060 break;
3061 default:
3062 break;
3063 }
3064 break;
3065 case Primitive::kPrimDouble:
3066 result_check = "D";
3067 switch (invoke) {
3068 case kVirtual:
3069 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3070 break;
3071 case kDirect:
3072 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3073 break;
3074 case kStatic:
3075 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3076 break;
3077 default:
3078 break;
3079 }
3080 break;
3081 case Primitive::kPrimVoid:
3082 result_check = "V";
3083 result.V = nullptr;
3084 switch (invoke) {
3085 case kVirtual:
3086 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3087 break;
3088 case kDirect:
3089 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3090 break;
3091 case kStatic:
3092 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3093 break;
3094 default:
3095 LOG(FATAL) << "Unexpected invoke: " << invoke;
3096 }
3097 break;
3098 default:
3099 LOG(FATAL) << "Unexpected return type: " << type;
3100 result_check = nullptr;
3101 }
3102 if (sc.Check(soa, false, result_check, &result)) {
3103 return result;
3104 }
3105 }
3106 result.J = 0;
3107 return result;
3108 }
3109
3110 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3111 jmethodID mid, va_list vargs, Primitive::Type type,
3112 InvokeType invoke) {
3113 ScopedObjectAccess soa(env);
3114 ScopedCheck sc(kFlag_Default, function_name);
3115 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003116 VarArgs rest(mid, vargs);
3117 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003118 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3119 const char* result_check;
3120 switch (type) {
3121 case Primitive::kPrimNot:
3122 result_check = "L";
3123 switch (invoke) {
3124 case kVirtual:
3125 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3126 break;
3127 case kDirect:
3128 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3129 break;
3130 case kStatic:
3131 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3132 break;
3133 default:
3134 LOG(FATAL) << "Unexpected invoke: " << invoke;
3135 }
3136 break;
3137 case Primitive::kPrimBoolean:
3138 result_check = "Z";
3139 switch (invoke) {
3140 case kVirtual:
3141 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3142 break;
3143 case kDirect:
3144 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3145 break;
3146 case kStatic:
3147 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3148 break;
3149 default:
3150 LOG(FATAL) << "Unexpected invoke: " << invoke;
3151 }
3152 break;
3153 case Primitive::kPrimByte:
3154 result_check = "B";
3155 switch (invoke) {
3156 case kVirtual:
3157 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3158 break;
3159 case kDirect:
3160 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3161 break;
3162 case kStatic:
3163 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3164 break;
3165 default:
3166 LOG(FATAL) << "Unexpected invoke: " << invoke;
3167 }
3168 break;
3169 case Primitive::kPrimChar:
3170 result_check = "C";
3171 switch (invoke) {
3172 case kVirtual:
3173 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3174 break;
3175 case kDirect:
3176 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3177 break;
3178 case kStatic:
3179 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3180 break;
3181 default:
3182 LOG(FATAL) << "Unexpected invoke: " << invoke;
3183 }
3184 break;
3185 case Primitive::kPrimShort:
3186 result_check = "S";
3187 switch (invoke) {
3188 case kVirtual:
3189 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3190 break;
3191 case kDirect:
3192 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3193 break;
3194 case kStatic:
3195 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3196 break;
3197 default:
3198 LOG(FATAL) << "Unexpected invoke: " << invoke;
3199 }
3200 break;
3201 case Primitive::kPrimInt:
3202 result_check = "I";
3203 switch (invoke) {
3204 case kVirtual:
3205 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3206 break;
3207 case kDirect:
3208 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3209 break;
3210 case kStatic:
3211 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3212 break;
3213 default:
3214 LOG(FATAL) << "Unexpected invoke: " << invoke;
3215 }
3216 break;
3217 case Primitive::kPrimLong:
3218 result_check = "J";
3219 switch (invoke) {
3220 case kVirtual:
3221 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3222 break;
3223 case kDirect:
3224 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3225 break;
3226 case kStatic:
3227 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3228 break;
3229 default:
3230 LOG(FATAL) << "Unexpected invoke: " << invoke;
3231 }
3232 break;
3233 case Primitive::kPrimFloat:
3234 result_check = "F";
3235 switch (invoke) {
3236 case kVirtual:
3237 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3238 break;
3239 case kDirect:
3240 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3241 break;
3242 case kStatic:
3243 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3244 break;
3245 default:
3246 LOG(FATAL) << "Unexpected invoke: " << invoke;
3247 }
3248 break;
3249 case Primitive::kPrimDouble:
3250 result_check = "D";
3251 switch (invoke) {
3252 case kVirtual:
3253 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3254 break;
3255 case kDirect:
3256 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3257 break;
3258 case kStatic:
3259 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3260 break;
3261 default:
3262 LOG(FATAL) << "Unexpected invoke: " << invoke;
3263 }
3264 break;
3265 case Primitive::kPrimVoid:
3266 result_check = "V";
3267 result.V = nullptr;
3268 switch (invoke) {
3269 case kVirtual:
3270 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3271 break;
3272 case kDirect:
3273 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3274 break;
3275 case kStatic:
3276 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3277 break;
3278 default:
3279 LOG(FATAL) << "Unexpected invoke: " << invoke;
3280 }
3281 break;
3282 default:
3283 LOG(FATAL) << "Unexpected return type: " << type;
3284 result_check = nullptr;
3285 }
3286 if (sc.Check(soa, false, result_check, &result)) {
3287 return result;
3288 }
3289 }
3290 result.J = 0;
3291 return result;
3292 }
3293
3294 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3295 jboolean* is_copy, bool utf, bool critical) {
3296 ScopedObjectAccess soa(env);
3297 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3298 ScopedCheck sc(flags, function_name);
3299 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3300 if (sc.Check(soa, true, "Esp", args)) {
3301 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003302 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003303 if (utf) {
3304 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003305 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3306 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003307 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003308 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3309 baseEnv(env)->GetStringChars(env, string, is_copy));
3310 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003311 }
3312 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003313 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003314 if (utf) {
3315 size_t length_in_bytes = strlen(result.u) + 1;
3316 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003317 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003318 } else {
3319 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3320 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003321 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003322 }
3323 if (is_copy != nullptr) {
3324 *is_copy = JNI_TRUE;
3325 }
3326 }
3327 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3328 return utf ? result.u : result.p;
3329 }
3330 }
3331 return nullptr;
3332 }
3333
3334 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3335 const void* chars, bool utf, bool critical) {
3336 ScopedObjectAccess soa(env);
3337 int flags = kFlag_ExcepOkay | kFlag_Release;
3338 if (critical) {
3339 flags |= kFlag_CritRelease;
3340 }
3341 ScopedCheck sc(flags, function_name);
3342 sc.CheckNonNull(chars);
3343 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3344 if (force_copy_ok && soa.ForceCopy()) {
3345 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3346 }
3347 if (force_copy_ok) {
3348 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3349 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3350 if (utf) {
3351 CHECK(!critical);
3352 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3353 } else {
3354 if (critical) {
3355 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3356 } else {
3357 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3358 }
3359 }
3360 JniValueType result;
3361 sc.Check(soa, false, "V", &result);
3362 }
3363 }
3364 }
3365
3366 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3367 Primitive::Type type) {
3368 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003369 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003370 JniValueType args[2] = {{.E = env}, {.z = length}};
3371 if (sc.Check(soa, true, "Ez", args)) {
3372 JniValueType result;
3373 switch (type) {
3374 case Primitive::kPrimBoolean:
3375 result.a = baseEnv(env)->NewBooleanArray(env, length);
3376 break;
3377 case Primitive::kPrimByte:
3378 result.a = baseEnv(env)->NewByteArray(env, length);
3379 break;
3380 case Primitive::kPrimChar:
3381 result.a = baseEnv(env)->NewCharArray(env, length);
3382 break;
3383 case Primitive::kPrimShort:
3384 result.a = baseEnv(env)->NewShortArray(env, length);
3385 break;
3386 case Primitive::kPrimInt:
3387 result.a = baseEnv(env)->NewIntArray(env, length);
3388 break;
3389 case Primitive::kPrimLong:
3390 result.a = baseEnv(env)->NewLongArray(env, length);
3391 break;
3392 case Primitive::kPrimFloat:
3393 result.a = baseEnv(env)->NewFloatArray(env, length);
3394 break;
3395 case Primitive::kPrimDouble:
3396 result.a = baseEnv(env)->NewDoubleArray(env, length);
3397 break;
3398 default:
3399 LOG(FATAL) << "Unexpected primitive type: " << type;
3400 }
3401 if (sc.Check(soa, false, "a", &result)) {
3402 return result.a;
3403 }
3404 }
3405 return nullptr;
3406 }
3407
3408 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3409 JNIEnv* env, jarray array, jboolean* is_copy) {
3410 ScopedObjectAccess soa(env);
3411 ScopedCheck sc(kFlag_Default, function_name);
3412 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3413 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3414 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003415 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003416 switch (type) {
3417 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003418 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3419 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003420 break;
3421 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003422 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003423 break;
3424 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003425 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003426 break;
3427 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003428 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003429 break;
3430 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003431 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003432 break;
3433 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003434 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003435 break;
3436 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003437 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003438 break;
3439 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003440 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003441 break;
3442 default:
3443 LOG(FATAL) << "Unexpected primitive type: " << type;
3444 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003445 if (ptr != nullptr && soa.ForceCopy()) {
3446 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003447 if (is_copy != nullptr) {
3448 *is_copy = JNI_TRUE;
3449 }
3450 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003451 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003452 if (sc.Check(soa, false, "p", &result)) {
3453 return const_cast<void*>(result.p);
3454 }
3455 }
3456 return nullptr;
3457 }
3458
3459 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3460 JNIEnv* env, jarray array, void* elems, jint mode) {
3461 ScopedObjectAccess soa(env);
3462 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3463 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3464 if (soa.ForceCopy()) {
3465 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3466 }
3467 if (!soa.ForceCopy() || elems != nullptr) {
3468 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3469 if (sc.Check(soa, true, "Eapr", args)) {
3470 switch (type) {
3471 case Primitive::kPrimBoolean:
3472 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3473 reinterpret_cast<jboolean*>(elems), mode);
3474 break;
3475 case Primitive::kPrimByte:
3476 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3477 reinterpret_cast<jbyte*>(elems), mode);
3478 break;
3479 case Primitive::kPrimChar:
3480 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3481 reinterpret_cast<jchar*>(elems), mode);
3482 break;
3483 case Primitive::kPrimShort:
3484 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3485 reinterpret_cast<jshort*>(elems), mode);
3486 break;
3487 case Primitive::kPrimInt:
3488 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3489 reinterpret_cast<jint*>(elems), mode);
3490 break;
3491 case Primitive::kPrimLong:
3492 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3493 reinterpret_cast<jlong*>(elems), mode);
3494 break;
3495 case Primitive::kPrimFloat:
3496 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3497 reinterpret_cast<jfloat*>(elems), mode);
3498 break;
3499 case Primitive::kPrimDouble:
3500 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3501 reinterpret_cast<jdouble*>(elems), mode);
3502 break;
3503 default:
3504 LOG(FATAL) << "Unexpected primitive type: " << type;
3505 }
3506 JniValueType result;
3507 result.V = nullptr;
3508 sc.Check(soa, false, "V", &result);
3509 }
3510 }
3511 }
3512 }
3513
3514 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3515 jarray array, jsize start, jsize len, void* buf) {
3516 ScopedObjectAccess soa(env);
3517 ScopedCheck sc(kFlag_Default, function_name);
3518 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3519 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3520 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3521 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3522 switch (type) {
3523 case Primitive::kPrimBoolean:
3524 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3525 reinterpret_cast<jboolean*>(buf));
3526 break;
3527 case Primitive::kPrimByte:
3528 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3529 reinterpret_cast<jbyte*>(buf));
3530 break;
3531 case Primitive::kPrimChar:
3532 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3533 reinterpret_cast<jchar*>(buf));
3534 break;
3535 case Primitive::kPrimShort:
3536 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3537 reinterpret_cast<jshort*>(buf));
3538 break;
3539 case Primitive::kPrimInt:
3540 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3541 reinterpret_cast<jint*>(buf));
3542 break;
3543 case Primitive::kPrimLong:
3544 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3545 reinterpret_cast<jlong*>(buf));
3546 break;
3547 case Primitive::kPrimFloat:
3548 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3549 reinterpret_cast<jfloat*>(buf));
3550 break;
3551 case Primitive::kPrimDouble:
3552 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3553 reinterpret_cast<jdouble*>(buf));
3554 break;
3555 default:
3556 LOG(FATAL) << "Unexpected primitive type: " << type;
3557 }
3558 JniValueType result;
3559 result.V = nullptr;
3560 sc.Check(soa, false, "V", &result);
3561 }
3562 }
3563
3564 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3565 jarray array, jsize start, jsize len, const void* buf) {
3566 ScopedObjectAccess soa(env);
3567 ScopedCheck sc(kFlag_Default, function_name);
3568 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3569 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3570 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3571 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3572 switch (type) {
3573 case Primitive::kPrimBoolean:
3574 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3575 reinterpret_cast<const jboolean*>(buf));
3576 break;
3577 case Primitive::kPrimByte:
3578 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3579 reinterpret_cast<const jbyte*>(buf));
3580 break;
3581 case Primitive::kPrimChar:
3582 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3583 reinterpret_cast<const jchar*>(buf));
3584 break;
3585 case Primitive::kPrimShort:
3586 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3587 reinterpret_cast<const jshort*>(buf));
3588 break;
3589 case Primitive::kPrimInt:
3590 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3591 reinterpret_cast<const jint*>(buf));
3592 break;
3593 case Primitive::kPrimLong:
3594 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3595 reinterpret_cast<const jlong*>(buf));
3596 break;
3597 case Primitive::kPrimFloat:
3598 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3599 reinterpret_cast<const jfloat*>(buf));
3600 break;
3601 case Primitive::kPrimDouble:
3602 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3603 reinterpret_cast<const jdouble*>(buf));
3604 break;
3605 default:
3606 LOG(FATAL) << "Unexpected primitive type: " << type;
3607 }
3608 JniValueType result;
3609 result.V = nullptr;
3610 sc.Check(soa, false, "V", &result);
3611 }
3612 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003613};
3614
3615const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003616 nullptr, // reserved0.
3617 nullptr, // reserved1.
3618 nullptr, // reserved2.
3619 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003620 CheckJNI::GetVersion,
3621 CheckJNI::DefineClass,
3622 CheckJNI::FindClass,
3623 CheckJNI::FromReflectedMethod,
3624 CheckJNI::FromReflectedField,
3625 CheckJNI::ToReflectedMethod,
3626 CheckJNI::GetSuperclass,
3627 CheckJNI::IsAssignableFrom,
3628 CheckJNI::ToReflectedField,
3629 CheckJNI::Throw,
3630 CheckJNI::ThrowNew,
3631 CheckJNI::ExceptionOccurred,
3632 CheckJNI::ExceptionDescribe,
3633 CheckJNI::ExceptionClear,
3634 CheckJNI::FatalError,
3635 CheckJNI::PushLocalFrame,
3636 CheckJNI::PopLocalFrame,
3637 CheckJNI::NewGlobalRef,
3638 CheckJNI::DeleteGlobalRef,
3639 CheckJNI::DeleteLocalRef,
3640 CheckJNI::IsSameObject,
3641 CheckJNI::NewLocalRef,
3642 CheckJNI::EnsureLocalCapacity,
3643 CheckJNI::AllocObject,
3644 CheckJNI::NewObject,
3645 CheckJNI::NewObjectV,
3646 CheckJNI::NewObjectA,
3647 CheckJNI::GetObjectClass,
3648 CheckJNI::IsInstanceOf,
3649 CheckJNI::GetMethodID,
3650 CheckJNI::CallObjectMethod,
3651 CheckJNI::CallObjectMethodV,
3652 CheckJNI::CallObjectMethodA,
3653 CheckJNI::CallBooleanMethod,
3654 CheckJNI::CallBooleanMethodV,
3655 CheckJNI::CallBooleanMethodA,
3656 CheckJNI::CallByteMethod,
3657 CheckJNI::CallByteMethodV,
3658 CheckJNI::CallByteMethodA,
3659 CheckJNI::CallCharMethod,
3660 CheckJNI::CallCharMethodV,
3661 CheckJNI::CallCharMethodA,
3662 CheckJNI::CallShortMethod,
3663 CheckJNI::CallShortMethodV,
3664 CheckJNI::CallShortMethodA,
3665 CheckJNI::CallIntMethod,
3666 CheckJNI::CallIntMethodV,
3667 CheckJNI::CallIntMethodA,
3668 CheckJNI::CallLongMethod,
3669 CheckJNI::CallLongMethodV,
3670 CheckJNI::CallLongMethodA,
3671 CheckJNI::CallFloatMethod,
3672 CheckJNI::CallFloatMethodV,
3673 CheckJNI::CallFloatMethodA,
3674 CheckJNI::CallDoubleMethod,
3675 CheckJNI::CallDoubleMethodV,
3676 CheckJNI::CallDoubleMethodA,
3677 CheckJNI::CallVoidMethod,
3678 CheckJNI::CallVoidMethodV,
3679 CheckJNI::CallVoidMethodA,
3680 CheckJNI::CallNonvirtualObjectMethod,
3681 CheckJNI::CallNonvirtualObjectMethodV,
3682 CheckJNI::CallNonvirtualObjectMethodA,
3683 CheckJNI::CallNonvirtualBooleanMethod,
3684 CheckJNI::CallNonvirtualBooleanMethodV,
3685 CheckJNI::CallNonvirtualBooleanMethodA,
3686 CheckJNI::CallNonvirtualByteMethod,
3687 CheckJNI::CallNonvirtualByteMethodV,
3688 CheckJNI::CallNonvirtualByteMethodA,
3689 CheckJNI::CallNonvirtualCharMethod,
3690 CheckJNI::CallNonvirtualCharMethodV,
3691 CheckJNI::CallNonvirtualCharMethodA,
3692 CheckJNI::CallNonvirtualShortMethod,
3693 CheckJNI::CallNonvirtualShortMethodV,
3694 CheckJNI::CallNonvirtualShortMethodA,
3695 CheckJNI::CallNonvirtualIntMethod,
3696 CheckJNI::CallNonvirtualIntMethodV,
3697 CheckJNI::CallNonvirtualIntMethodA,
3698 CheckJNI::CallNonvirtualLongMethod,
3699 CheckJNI::CallNonvirtualLongMethodV,
3700 CheckJNI::CallNonvirtualLongMethodA,
3701 CheckJNI::CallNonvirtualFloatMethod,
3702 CheckJNI::CallNonvirtualFloatMethodV,
3703 CheckJNI::CallNonvirtualFloatMethodA,
3704 CheckJNI::CallNonvirtualDoubleMethod,
3705 CheckJNI::CallNonvirtualDoubleMethodV,
3706 CheckJNI::CallNonvirtualDoubleMethodA,
3707 CheckJNI::CallNonvirtualVoidMethod,
3708 CheckJNI::CallNonvirtualVoidMethodV,
3709 CheckJNI::CallNonvirtualVoidMethodA,
3710 CheckJNI::GetFieldID,
3711 CheckJNI::GetObjectField,
3712 CheckJNI::GetBooleanField,
3713 CheckJNI::GetByteField,
3714 CheckJNI::GetCharField,
3715 CheckJNI::GetShortField,
3716 CheckJNI::GetIntField,
3717 CheckJNI::GetLongField,
3718 CheckJNI::GetFloatField,
3719 CheckJNI::GetDoubleField,
3720 CheckJNI::SetObjectField,
3721 CheckJNI::SetBooleanField,
3722 CheckJNI::SetByteField,
3723 CheckJNI::SetCharField,
3724 CheckJNI::SetShortField,
3725 CheckJNI::SetIntField,
3726 CheckJNI::SetLongField,
3727 CheckJNI::SetFloatField,
3728 CheckJNI::SetDoubleField,
3729 CheckJNI::GetStaticMethodID,
3730 CheckJNI::CallStaticObjectMethod,
3731 CheckJNI::CallStaticObjectMethodV,
3732 CheckJNI::CallStaticObjectMethodA,
3733 CheckJNI::CallStaticBooleanMethod,
3734 CheckJNI::CallStaticBooleanMethodV,
3735 CheckJNI::CallStaticBooleanMethodA,
3736 CheckJNI::CallStaticByteMethod,
3737 CheckJNI::CallStaticByteMethodV,
3738 CheckJNI::CallStaticByteMethodA,
3739 CheckJNI::CallStaticCharMethod,
3740 CheckJNI::CallStaticCharMethodV,
3741 CheckJNI::CallStaticCharMethodA,
3742 CheckJNI::CallStaticShortMethod,
3743 CheckJNI::CallStaticShortMethodV,
3744 CheckJNI::CallStaticShortMethodA,
3745 CheckJNI::CallStaticIntMethod,
3746 CheckJNI::CallStaticIntMethodV,
3747 CheckJNI::CallStaticIntMethodA,
3748 CheckJNI::CallStaticLongMethod,
3749 CheckJNI::CallStaticLongMethodV,
3750 CheckJNI::CallStaticLongMethodA,
3751 CheckJNI::CallStaticFloatMethod,
3752 CheckJNI::CallStaticFloatMethodV,
3753 CheckJNI::CallStaticFloatMethodA,
3754 CheckJNI::CallStaticDoubleMethod,
3755 CheckJNI::CallStaticDoubleMethodV,
3756 CheckJNI::CallStaticDoubleMethodA,
3757 CheckJNI::CallStaticVoidMethod,
3758 CheckJNI::CallStaticVoidMethodV,
3759 CheckJNI::CallStaticVoidMethodA,
3760 CheckJNI::GetStaticFieldID,
3761 CheckJNI::GetStaticObjectField,
3762 CheckJNI::GetStaticBooleanField,
3763 CheckJNI::GetStaticByteField,
3764 CheckJNI::GetStaticCharField,
3765 CheckJNI::GetStaticShortField,
3766 CheckJNI::GetStaticIntField,
3767 CheckJNI::GetStaticLongField,
3768 CheckJNI::GetStaticFloatField,
3769 CheckJNI::GetStaticDoubleField,
3770 CheckJNI::SetStaticObjectField,
3771 CheckJNI::SetStaticBooleanField,
3772 CheckJNI::SetStaticByteField,
3773 CheckJNI::SetStaticCharField,
3774 CheckJNI::SetStaticShortField,
3775 CheckJNI::SetStaticIntField,
3776 CheckJNI::SetStaticLongField,
3777 CheckJNI::SetStaticFloatField,
3778 CheckJNI::SetStaticDoubleField,
3779 CheckJNI::NewString,
3780 CheckJNI::GetStringLength,
3781 CheckJNI::GetStringChars,
3782 CheckJNI::ReleaseStringChars,
3783 CheckJNI::NewStringUTF,
3784 CheckJNI::GetStringUTFLength,
3785 CheckJNI::GetStringUTFChars,
3786 CheckJNI::ReleaseStringUTFChars,
3787 CheckJNI::GetArrayLength,
3788 CheckJNI::NewObjectArray,
3789 CheckJNI::GetObjectArrayElement,
3790 CheckJNI::SetObjectArrayElement,
3791 CheckJNI::NewBooleanArray,
3792 CheckJNI::NewByteArray,
3793 CheckJNI::NewCharArray,
3794 CheckJNI::NewShortArray,
3795 CheckJNI::NewIntArray,
3796 CheckJNI::NewLongArray,
3797 CheckJNI::NewFloatArray,
3798 CheckJNI::NewDoubleArray,
3799 CheckJNI::GetBooleanArrayElements,
3800 CheckJNI::GetByteArrayElements,
3801 CheckJNI::GetCharArrayElements,
3802 CheckJNI::GetShortArrayElements,
3803 CheckJNI::GetIntArrayElements,
3804 CheckJNI::GetLongArrayElements,
3805 CheckJNI::GetFloatArrayElements,
3806 CheckJNI::GetDoubleArrayElements,
3807 CheckJNI::ReleaseBooleanArrayElements,
3808 CheckJNI::ReleaseByteArrayElements,
3809 CheckJNI::ReleaseCharArrayElements,
3810 CheckJNI::ReleaseShortArrayElements,
3811 CheckJNI::ReleaseIntArrayElements,
3812 CheckJNI::ReleaseLongArrayElements,
3813 CheckJNI::ReleaseFloatArrayElements,
3814 CheckJNI::ReleaseDoubleArrayElements,
3815 CheckJNI::GetBooleanArrayRegion,
3816 CheckJNI::GetByteArrayRegion,
3817 CheckJNI::GetCharArrayRegion,
3818 CheckJNI::GetShortArrayRegion,
3819 CheckJNI::GetIntArrayRegion,
3820 CheckJNI::GetLongArrayRegion,
3821 CheckJNI::GetFloatArrayRegion,
3822 CheckJNI::GetDoubleArrayRegion,
3823 CheckJNI::SetBooleanArrayRegion,
3824 CheckJNI::SetByteArrayRegion,
3825 CheckJNI::SetCharArrayRegion,
3826 CheckJNI::SetShortArrayRegion,
3827 CheckJNI::SetIntArrayRegion,
3828 CheckJNI::SetLongArrayRegion,
3829 CheckJNI::SetFloatArrayRegion,
3830 CheckJNI::SetDoubleArrayRegion,
3831 CheckJNI::RegisterNatives,
3832 CheckJNI::UnregisterNatives,
3833 CheckJNI::MonitorEnter,
3834 CheckJNI::MonitorExit,
3835 CheckJNI::GetJavaVM,
3836 CheckJNI::GetStringRegion,
3837 CheckJNI::GetStringUTFRegion,
3838 CheckJNI::GetPrimitiveArrayCritical,
3839 CheckJNI::ReleasePrimitiveArrayCritical,
3840 CheckJNI::GetStringCritical,
3841 CheckJNI::ReleaseStringCritical,
3842 CheckJNI::NewWeakGlobalRef,
3843 CheckJNI::DeleteWeakGlobalRef,
3844 CheckJNI::ExceptionCheck,
3845 CheckJNI::NewDirectByteBuffer,
3846 CheckJNI::GetDirectBufferAddress,
3847 CheckJNI::GetDirectBufferCapacity,
3848 CheckJNI::GetObjectRefType,
3849};
3850
Elliott Hughesa2501992011-08-26 19:39:54 -07003851class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003852 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003853 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003854 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3855 JniValueType args[1] = {{.v = vm}};
3856 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3857 JniValueType result;
3858 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08003859 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3860 // which will delete the JavaVMExt.
3861 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07003862 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003863 }
3864
3865 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003866 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3867 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3868 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3869 JniValueType result;
3870 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3871 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3872 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003873 }
3874
3875 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003876 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3877 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3878 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3879 JniValueType result;
3880 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3881 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3882 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003883 }
3884
3885 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003886 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3887 JniValueType args[1] = {{.v = vm}};
3888 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3889 JniValueType result;
3890 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3891 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3892 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003893 }
3894
Ian Rogers68d8b422014-07-17 11:09:10 -07003895 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3896 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3897 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3898 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3899 JniValueType result;
3900 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3901 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3902 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003903 }
3904
3905 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003906 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3907 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003908 }
3909};
3910
3911const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003912 nullptr, // reserved0
3913 nullptr, // reserved1
3914 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003915 CheckJII::DestroyJavaVM,
3916 CheckJII::AttachCurrentThread,
3917 CheckJII::DetachCurrentThread,
3918 CheckJII::GetEnv,
3919 CheckJII::AttachCurrentThreadAsDaemon
3920};
3921
Ian Rogersac4d45a2018-02-15 11:19:01 -08003922} // anonymous namespace
3923
3924const JNINativeInterface* GetCheckJniNativeInterface() {
3925 return &gCheckNativeInterface;
3926}
3927
Elliott Hughesa2501992011-08-26 19:39:54 -07003928const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3929 return &gCheckInvokeInterface;
3930}
3931
3932} // namespace art