blob: 4a8453a721b2bf0caf28e70cbf58ce26aeb508cb [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"
Vladimir Marko679730e2018-05-25 15:06:48 +010034#include "class_root.h"
David Sehrb2ec9f52018-02-21 13:20:31 -080035#include "dex/descriptors_names.h"
David Sehr9e734c72018-01-04 17:56:19 -080036#include "dex/dex_file-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070037#include "gc/space/space.h"
Andreas Gampec0ed43e2018-06-18 10:47:15 -070038#include "java_vm_ext.h"
39#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080040#include "mirror/class-inl.h"
Vladimir Marko60976722018-04-06 15:29:38 +010041#include "mirror/field.h"
42#include "mirror/method.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080043#include "mirror/object-inl.h"
44#include "mirror/object_array-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070045#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080046#include "mirror/throwable.h"
Jeff Hao58df3272013-04-22 15:28:53 -070047#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070048#include "scoped_thread_state_change-inl.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070049#include "thread.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070050#include "well_known_classes.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070051
52namespace art {
Ian Rogersac4d45a2018-02-15 11:19:01 -080053namespace {
Elliott Hughesa2501992011-08-26 19:39:54 -070054
Andreas Gampe46ee31b2016-12-14 10:11:49 -080055using android::base::StringAppendF;
56using android::base::StringPrintf;
57
Elliott Hughesa2501992011-08-26 19:39:54 -070058/*
59 * ===========================================================================
60 * JNI function helpers
61 * ===========================================================================
62 */
63
Ian Rogers55256cb2017-12-21 17:07:11 -080064// Warn if a JNI critical is held for longer than 16ms.
65static constexpr uint64_t kCriticalWarnTimeUs = MsToUs(16);
66static_assert(kCriticalWarnTimeUs > 0, "No JNI critical warn time set");
67
Ian Rogers9e937be2018-02-15 17:06:58 -080068// True if primitives within specific ranges cause a fatal error,
69// otherwise just warn.
70static constexpr bool kBrokenPrimitivesAreFatal = kIsDebugBuild;
71
Elliott Hughes3f6635a2012-06-19 13:37:49 -070072// Flags passed into ScopedCheck.
Ian Rogers55256cb2017-12-21 17:07:11 -080073static constexpr uint16_t kFlag_Default = 0x0000;
Elliott Hughesa2501992011-08-26 19:39:54 -070074
Ian Rogers55256cb2017-12-21 17:07:11 -080075// Calling while in critical is not allowed.
76static constexpr uint16_t kFlag_CritBad = 0x0000;
77// Calling while in critical is allowed.
78static constexpr uint16_t kFlag_CritOkay = 0x0001;
79// This is a critical "get".
80static constexpr uint16_t kFlag_CritGet = 0x0002;
81// This is a critical "release".
82static constexpr uint16_t kFlag_CritRelease = 0x0003;
83// Bit mask to get "crit" value.
84static constexpr uint16_t kFlag_CritMask = 0x0003;
Elliott Hughesa2501992011-08-26 19:39:54 -070085
Ian Rogers55256cb2017-12-21 17:07:11 -080086// Raised exceptions are allowed.
87static constexpr uint16_t kFlag_ExcepOkay = 0x0004;
Elliott Hughesa2501992011-08-26 19:39:54 -070088
Ian Rogers55256cb2017-12-21 17:07:11 -080089// Are we in a non-critical release function?
90static constexpr uint16_t kFlag_Release = 0x0010;
91// Are our UTF parameters nullable?
92static constexpr uint16_t kFlag_NullableUtf = 0x0020;
Elliott Hughesa2501992011-08-26 19:39:54 -070093
Ian Rogers55256cb2017-12-21 17:07:11 -080094// Part of the invocation interface (JavaVM*).
95static constexpr uint16_t kFlag_Invocation = 0x0100;
Elliott Hughesa2501992011-08-26 19:39:54 -070096
Ian Rogers55256cb2017-12-21 17:07:11 -080097// Add this to a JNI function's flags if you want to trace every call.
98static constexpr uint16_t kFlag_ForceTrace = 0x8000;
Alex Light48ffe062015-08-19 15:23:23 -070099
100class VarArgs;
Ian Rogers68d8b422014-07-17 11:09:10 -0700101/*
102 * Java primitive types:
103 * B - jbyte
104 * C - jchar
105 * D - jdouble
106 * F - jfloat
107 * I - jint
108 * J - jlong
109 * S - jshort
110 * Z - jboolean (shown as true and false)
111 * V - void
112 *
113 * Java reference types:
114 * L - jobject
115 * a - jarray
116 * c - jclass
117 * s - jstring
118 * t - jthrowable
119 *
120 * JNI types:
121 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
122 * f - jfieldID
123 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
124 * m - jmethodID
125 * p - void*
126 * r - jint (for release mode arguments)
127 * u - const char* (Modified UTF-8)
128 * z - jsize (for lengths; use i if negative values are okay)
129 * v - JavaVM*
130 * w - jobjectRefType
131 * E - JNIEnv*
132 * . - no argument; just print "..." (used for varargs JNI calls)
133 *
134 */
135union JniValueType {
136 jarray a;
137 jboolean b;
138 jclass c;
139 jfieldID f;
140 jint i;
141 jmethodID m;
142 const void* p; // Pointer.
143 jint r; // Release mode.
144 jstring s;
145 jthrowable t;
146 const char* u; // Modified UTF-8.
147 JavaVM* v;
148 jobjectRefType w;
149 jsize z;
150 jbyte B;
151 jchar C;
152 jdouble D;
153 JNIEnv* E;
154 jfloat F;
155 jint I;
156 jlong J;
157 jobject L;
158 jshort S;
159 const void* V; // void
160 jboolean Z;
Alex Light48ffe062015-08-19 15:23:23 -0700161 const VarArgs* va;
162};
163
164/*
165 * A structure containing all the information needed to validate varargs arguments.
166 *
167 * Note that actually getting the arguments from this structure mutates it so should only be done on
168 * owned copies.
169 */
170class VarArgs {
171 public:
172 VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
173 va_copy(vargs_, var);
174 }
175
176 VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
177
178 ~VarArgs() {
179 if (type_ == kTypeVaList) {
180 va_end(vargs_);
181 }
182 }
183
Andreas Gampe44b31742018-10-01 19:30:57 -0700184 VarArgs(VarArgs&& other) noexcept {
Alex Light48ffe062015-08-19 15:23:23 -0700185 m_ = other.m_;
186 cnt_ = other.cnt_;
187 type_ = other.type_;
188 if (other.type_ == kTypeVaList) {
189 va_copy(vargs_, other.vargs_);
190 } else {
191 ptr_ = other.ptr_;
192 }
193 }
194
195 // This method is const because we need to ensure that one only uses the GetValue method on an
196 // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
197 // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
198 // we want to use one we need to Clone() it.
199 VarArgs Clone() const {
200 if (type_ == kTypeVaList) {
201 // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
202 // messed up if the source argument is not the exact type 'va_list'.
203 return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
204 } else {
205 return VarArgs(m_, cnt_, ptr_);
206 }
207 }
208
209 jmethodID GetMethodID() const {
210 return m_;
211 }
212
213 JniValueType GetValue(char fmt) {
214 JniValueType o;
215 if (type_ == kTypeVaList) {
216 switch (fmt) {
Ian Rogers9e937be2018-02-15 17:06:58 -0800217 // Assign a full int for va_list values as this is what is done in reflection.cc.
218 // TODO(b/73656264): avoid undefined behavior.
219 case 'Z': FALLTHROUGH_INTENDED;
220 case 'B': FALLTHROUGH_INTENDED;
221 case 'C': FALLTHROUGH_INTENDED;
222 case 'S': FALLTHROUGH_INTENDED;
Alex Light48ffe062015-08-19 15:23:23 -0700223 case 'I': o.I = va_arg(vargs_, jint); break;
224 case 'J': o.J = va_arg(vargs_, jlong); break;
225 case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
226 case 'D': o.D = va_arg(vargs_, jdouble); break;
227 case 'L': o.L = va_arg(vargs_, jobject); break;
228 default:
229 LOG(FATAL) << "Illegal type format char " << fmt;
230 UNREACHABLE();
231 }
232 } else {
233 CHECK(type_ == kTypePtr);
234 jvalue v = ptr_[cnt_];
235 cnt_++;
236 switch (fmt) {
Ian Rogers9e937be2018-02-15 17:06:58 -0800237 // Copy just the amount of the jvalue necessary, as done in
238 // reflection.cc, but extend to an int to be consistent with
239 // var args in CheckNonHeapValue.
240 // TODO(b/73656264): avoid undefined behavior.
241 case 'Z': o.I = v.z; break;
242 case 'B': o.I = v.b; break;
243 case 'C': o.I = v.c; break;
244 case 'S': o.I = v.s; break;
Alex Light48ffe062015-08-19 15:23:23 -0700245 case 'I': o.I = v.i; break;
246 case 'J': o.J = v.j; break;
247 case 'F': o.F = v.f; break;
248 case 'D': o.D = v.d; break;
249 case 'L': o.L = v.l; break;
250 default:
251 LOG(FATAL) << "Illegal type format char " << fmt;
252 UNREACHABLE();
253 }
254 }
255 return o;
256 }
257
258 private:
259 VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
260 va_copy(vargs_, var);
261 }
262
263 VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
264
265 enum VarArgsType {
266 kTypeVaList,
267 kTypePtr,
268 };
269
270 jmethodID m_;
271 VarArgsType type_;
272 uint32_t cnt_;
273 union {
274 va_list vargs_;
275 const jvalue* ptr_;
276 };
Elliott Hughesa0957642011-09-02 14:27:33 -0700277};
278
Andreas Gampefb8f75c2018-04-17 11:08:23 -0700279// Check whether the current thread is attached. This is usually required
280// to be the first check, as ScopedCheck needs a ScopedObjectAccess for
281// checking heap values (and that will fail with unattached threads).
282bool CheckAttachedThread(const char* function_name) {
283 Thread* self = Thread::Current();
284 if (UNLIKELY(self == nullptr)) {
285 // Need to attach this thread for a proper abort to work. We prefer this
286 // to get reasonable stacks and environment, rather than relying on
287 // tombstoned.
288 JNIEnv* env;
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700289 Runtime::Current()->GetJavaVM()->AttachCurrentThread(&env, /* thr_args= */ nullptr);
Andreas Gampefb8f75c2018-04-17 11:08:23 -0700290
291 std::string tmp = android::base::StringPrintf(
292 "a thread (tid %" PRId64 " is making JNI calls without being attached",
293 static_cast<int64_t>(GetTid()));
294 Runtime::Current()->GetJavaVM()->JniAbort(function_name, tmp.c_str());
295
296 CHECK_NE(Runtime::Current()->GetJavaVM()->DetachCurrentThread(), JNI_ERR);
297 return false;
298 }
299 return true;
300}
301
302// Macro helpers for the above.
303#define CHECK_ATTACHED_THREAD(function_name, fail_val) \
304 do { \
305 if (!CheckAttachedThread((function_name))) { \
306 return fail_val; \
307 } \
308 } while (false)
309#define CHECK_ATTACHED_THREAD_VOID(function_name) \
310 do { \
311 if (!CheckAttachedThread((function_name))) { \
312 return; \
313 } \
314 } while (false)
315
Elliott Hughesa2501992011-08-26 19:39:54 -0700316class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800317 public:
Ian Rogers55256cb2017-12-21 17:07:11 -0800318 ScopedCheck(uint16_t flags, const char* functionName, bool has_method = true)
319 : function_name_(functionName), indent_(0), flags_(flags), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700320 }
321
Ian Rogers68d8b422014-07-17 11:09:10 -0700322 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700323
Elliott Hughes81ff3182012-03-23 20:35:56 -0700324 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
325 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
326 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
327 // circumstances, but this is incorrect.
Ian Rogers68d8b422014-07-17 11:09:10 -0700328 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700329 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700330 AbortF("illegal class name '%s'\n"
331 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
332 class_name);
333 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700334 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700335 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700336 }
337
338 /*
339 * Verify that this instance field ID is valid for this object.
340 *
341 * Assumes "jobj" has already been validated.
342 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700343 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700344 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700345 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Ian Rogers68d8b422014-07-17 11:09:10 -0700346 if (o == nullptr) {
347 AbortF("field operation on NULL object: %p", java_object);
348 return false;
349 }
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700350 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700351 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700352 AbortF("field operation on invalid %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700353 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700354 java_object);
355 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700356 }
357
Andreas Gampe08883de2016-11-08 13:20:52 -0800358 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800359 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700360 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700361 }
Vladimir Markodfc0de72019-04-01 10:57:55 +0100362 ObjPtr<mirror::Class> c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700363 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700364 AbortF("jfieldID %s not valid for an object of class %s",
David Sehr709b0702016-10-13 09:12:37 -0700365 f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700366 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700367 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700368 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700369 }
370
371 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700372 * Verify that the pointer value is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -0700373 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700374 bool CheckNonNull(const void* ptr) {
375 if (UNLIKELY(ptr == nullptr)) {
376 AbortF("non-nullable argument was NULL");
377 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700378 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700379 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700380 }
381
382 /*
383 * Verify that the method's return type matches the type of call.
384 * 'expectedType' will be "L" for all objects, including arrays.
385 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700386 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
387 jmethodID mid, Primitive::Type type, InvokeType invoke)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700388 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800389 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800390 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700391 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700392 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700393 if (type != Primitive::GetType(m->GetShorty()[0])) {
David Sehr709b0702016-10-13 09:12:37 -0700394 AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700395 return false;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700396 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700397 bool is_static = (invoke == kStatic);
398 if (is_static != m->IsStatic()) {
399 if (is_static) {
400 AbortF("calling non-static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700401 m->PrettyMethod().c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700402 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700403 AbortF("calling static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700404 m->PrettyMethod().c_str(), function_name_);
Ian Rogers68d8b422014-07-17 11:09:10 -0700405 }
406 return false;
407 }
408 if (invoke != kVirtual) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700409 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700410 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700411 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
David Sehr709b0702016-10-13 09:12:37 -0700412 m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700413 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700414 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700415 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700416 if (invoke != kStatic) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700417 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700418 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700419 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700420 return false;
421 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700422 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
423 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700424 return false;
425 }
426 }
427 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700428 }
429
430 /*
431 * Verify that this static field ID is valid for this class.
432 *
433 * Assumes "java_class" has already been validated.
434 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700435 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700436 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700437 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Andreas Gampe08883de2016-11-08 13:20:52 -0800438 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800439 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700440 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700441 }
Alex Lighte4033fa2017-12-13 10:32:59 -0800442 if (!f->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700443 AbortF("static jfieldID %p not valid for class %s", fid,
444 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700445 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700446 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700447 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700448 }
449
450 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700451 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700452 *
453 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700454 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700455 * allow bad code in the system though.
456 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700457 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700458 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700459 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700460 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800461 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800462 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700463 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700464 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700465 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700466 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700467 AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
468 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700469 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700470 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700471 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700472 }
473
474 /*
475 * Verify that "mid" is appropriate for "jobj".
476 *
477 * Make sure the object is an instance of the method's declaring class.
478 * (Note the mid might point to a declaration in an interface; this
479 * will be handled automatically by the instanceof check.)
480 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700481 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700482 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800483 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800484 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700485 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700486 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700487 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700488 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700489 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700490 return false;
491 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700492 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
493 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700494 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700495 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700496 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700497 }
498
499 /**
500 * The format string is a sequence of the following characters,
501 * and must be followed by arguments of the corresponding types
502 * in the same order.
503 *
504 * Java primitive types:
505 * B - jbyte
506 * C - jchar
507 * D - jdouble
508 * F - jfloat
509 * I - jint
510 * J - jlong
511 * S - jshort
512 * Z - jboolean (shown as true and false)
513 * V - void
514 *
515 * Java reference types:
516 * L - jobject
517 * a - jarray
518 * c - jclass
519 * s - jstring
520 *
521 * JNI types:
522 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
523 * f - jfieldID
524 * m - jmethodID
525 * p - void*
526 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700527 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700528 * z - jsize (for lengths; use i if negative values are okay)
529 * v - JavaVM*
530 * E - JNIEnv*
Alex Light48ffe062015-08-19 15:23:23 -0700531 * . - VarArgs* for Jni calls with variable length arguments
Elliott Hughesa2501992011-08-26 19:39:54 -0700532 *
533 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
534 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700535 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700536 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700537 ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700538 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700539 // We need to guard some of the invocation interface's calls: a bad caller might
540 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700541 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800542 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
543 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700544 }
545 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700546
Ian Rogersef7d42f2014-01-06 12:55:46 -0800547 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700548 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700549 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700550 for (size_t i = 0; fmt[i] != '\0'; ++i) {
551 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
552 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700553 StringAppendF(&msg, ", ");
554 }
555 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700556
Elliott Hughes485cac42011-12-09 17:49:35 -0800557 if ((flags_ & kFlag_ForceTrace) != 0) {
558 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
559 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700560 if (has_method_) {
David Sehr709b0702016-10-13 09:12:37 -0700561 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700562 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
563 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700564 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700565 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
566 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700567 }
568 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700569 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700570 }
571 }
572
573 // We always do the thorough checks on entry, and never on exit...
574 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700575 for (size_t i = 0; fmt[i] != '\0'; ++i) {
576 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
577 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700578 }
579 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700580 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700581 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700582 }
583
Ian Rogers68d8b422014-07-17 11:09:10 -0700584 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
585 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800586 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700587 // We need to guard some of the invocation interface's calls: a bad caller might
588 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
589 Thread* self = Thread::Current();
590 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
591 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700592 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700593 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
594 }
595 }
596 if (should_trace) {
597 std::string msg;
598 for (size_t i = 0; fmt[i] != '\0'; ++i) {
599 TraceNonHeapValue(fmt[i], args[i], &msg);
600 if (fmt[i + 1] != '\0') {
601 StringAppendF(&msg, ", ");
602 }
603 }
604
605 if ((flags_ & kFlag_ForceTrace) != 0) {
606 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
607 } else if (entry) {
608 if (has_method_) {
609 Thread* self = Thread::Current();
610 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700611 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
David Sehr709b0702016-10-13 09:12:37 -0700612 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Ian Rogers68d8b422014-07-17 11:09:10 -0700613 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
614 indent_ = methodName.size() + 1;
615 } else {
616 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
617 indent_ = 0;
618 }
619 } else {
620 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
621 }
622 }
623
624 // We always do the thorough checks on entry, and never on exit...
625 if (entry) {
626 for (size_t i = 0; fmt[i] != '\0'; ++i) {
627 if (!CheckNonHeapValue(fmt[i], args[i])) {
628 return false;
629 }
630 }
631 }
632 return true;
633 }
634
635 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700636 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700637 ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700638 if (method == nullptr) {
639 AbortF("expected non-null method");
640 return false;
641 }
Vladimir Marko679730e2018-05-25 15:06:48 +0100642 ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
643 Runtime::Current()->GetClassLinker()->GetClassRoots();
Vladimir Marko60976722018-04-06 15:29:38 +0100644 ObjPtr<mirror::Class> c = method->GetClass();
Vladimir Marko679730e2018-05-25 15:06:48 +0100645 if (c != GetClassRoot<mirror::Method>(class_roots) &&
646 c != GetClassRoot<mirror::Constructor>(class_roots)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700647 AbortF("expected java.lang.reflect.Method or "
648 "java.lang.reflect.Constructor but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700649 method->PrettyTypeOf().c_str(), jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700650 return false;
651 }
652 return true;
653 }
654
Andreas Gampe13b27842016-11-07 16:48:23 -0800655 bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
656 ArtMethod* method = jni::DecodeArtMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700657 if (method == nullptr) {
658 AbortF("expected non-null constructor");
659 return false;
660 }
661 if (!method->IsConstructor() || method->IsStatic()) {
David Sehr709b0702016-10-13 09:12:37 -0700662 AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700663 return false;
664 }
665 return true;
666 }
667
668 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700669 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700670 ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700671 if (field == nullptr) {
672 AbortF("expected non-null java.lang.reflect.Field");
673 return false;
674 }
Vladimir Marko60976722018-04-06 15:29:38 +0100675 ObjPtr<mirror::Class> c = field->GetClass();
Vladimir Marko679730e2018-05-25 15:06:48 +0100676 if (GetClassRoot<mirror::Field>() != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700677 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700678 field->PrettyTypeOf().c_str(), jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700679 return false;
680 }
681 return true;
682 }
683
684 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700685 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700686 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700687 if (!obj->GetClass()->IsThrowableClass()) {
688 AbortF("expected java.lang.Throwable but got object of type "
David Sehr709b0702016-10-13 09:12:37 -0700689 "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700690 return false;
691 }
692 return true;
693 }
694
695 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700696 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700697 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700698 if (!c->IsThrowableClass()) {
699 AbortF("expected java.lang.Throwable class but got object of "
David Sehr709b0702016-10-13 09:12:37 -0700700 "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700701 return false;
702 }
703 return true;
704 }
705
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700706 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700707 IndirectRefKind found_kind;
708 if (expected_kind == kLocal) {
Andreas Gampedc061d02016-10-24 13:19:37 -0700709 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700710 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
711 found_kind = kLocal;
712 }
713 } else {
Andreas Gampedc061d02016-10-24 13:19:37 -0700714 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700715 }
716 if (obj != nullptr && found_kind != expected_kind) {
717 AbortF("expected reference of kind %s but found %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700718 GetIndirectRefKindString(expected_kind),
719 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700720 obj);
721 return false;
722 }
723 return true;
724 }
725
726 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700727 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700728 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700729 if (!c->IsInstantiableNonArray()) {
David Sehr709b0702016-10-13 09:12:37 -0700730 AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700731 return false;
732 }
733 return true;
734 }
735
736 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700737 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700738 if (!CheckArray(soa, array)) {
739 return false;
740 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700741 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700742 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
743 AbortF("incompatible array type %s expected %s[]: %p",
David Sehr709b0702016-10-13 09:12:37 -0700744 a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700745 return false;
746 }
747 return true;
748 }
749
750 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
751 Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700752 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700753 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
754 return false;
755 }
756 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
757 return false;
758 }
Andreas Gampe08883de2016-11-08 13:20:52 -0800759 ArtField* field = jni::DecodeArtField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700760 DCHECK(field != nullptr); // Already checked by Check.
761 if (is_static != field->IsStatic()) {
762 AbortF("attempt to access %s field %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700763 field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700764 return false;
765 }
766 if (type != field->GetTypeAsPrimitiveType()) {
767 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700768 field->PrettyField().c_str(),
769 PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
Ian Rogers68d8b422014-07-17 11:09:10 -0700770 PrettyDescriptor(type).c_str(), fid);
771 return false;
772 }
773 if (is_static) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700774 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700775 if (o == nullptr || !o->IsClass()) {
776 AbortF("attempt to access static field %s with a class argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700777 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700778 return false;
779 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700780 ObjPtr<mirror::Class> c = o->AsClass();
Alex Lighte4033fa2017-12-13 10:32:59 -0800781 if (!field->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700782 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700783 field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700784 return false;
785 }
786 } else {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700787 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700788 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
789 AbortF("attempt to access field %s from an object argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700790 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700791 return false;
792 }
793 }
794 return true;
795 }
796
797 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800798 enum InstanceKind {
799 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700800 kDirectByteBuffer,
801 kObject,
802 kString,
803 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800804 };
805
806 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700807 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800808 * an instance of expectedClass.
809 *
810 * Because we're looking at an object on the GC heap, we have to switch
811 * to "running" mode before doing the checks.
812 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700813 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700814 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800815 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800816 switch (kind) {
817 case kClass:
818 what = "jclass";
819 break;
820 case kDirectByteBuffer:
821 what = "direct ByteBuffer";
822 break;
823 case kObject:
824 what = "jobject";
825 break;
826 case kString:
827 what = "jstring";
828 break;
829 case kThrowable:
830 what = "jthrowable";
831 break;
832 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700833 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800834 }
835
Ian Rogersef7d42f2014-01-06 12:55:46 -0800836 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700837 if (null_ok) {
838 return true;
839 } else {
840 AbortF("%s received NULL %s", function_name_, what);
841 return false;
842 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800843 }
844
Mathieu Chartier0795f232016-09-27 18:43:30 -0700845 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700846 if (obj == nullptr) {
847 // Either java_object is invalid or is a cleared weak.
848 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
849 bool okay;
Andreas Gampedc061d02016-10-24 13:19:37 -0700850 if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) {
Ian Rogersc0542af2014-09-03 16:16:56 -0700851 okay = false;
852 } else {
853 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
Mathieu Chartierc4f39252016-10-05 18:32:08 -0700854 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
Ian Rogersc0542af2014-09-03 16:16:56 -0700855 }
856 if (!okay) {
857 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700858 what,
859 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
860 java_object,
861 obj.Ptr());
Ian Rogersc0542af2014-09-03 16:16:56 -0700862 return false;
863 }
864 }
865
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700866 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700867 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700868 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700869 what,
870 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
871 java_object,
872 obj.Ptr());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800873 return false;
874 }
875
876 bool okay = true;
877 switch (kind) {
878 case kClass:
879 okay = obj->IsClass();
880 break;
881 case kDirectByteBuffer:
882 UNIMPLEMENTED(FATAL);
Elliott Hughesc1896c92018-11-29 11:33:18 -0800883 UNREACHABLE();
Elliott Hughesa92853e2012-02-07 16:09:27 -0800884 case kString:
885 okay = obj->GetClass()->IsStringClass();
886 break;
887 case kThrowable:
888 okay = obj->GetClass()->IsThrowableClass();
889 break;
890 case kObject:
891 break;
892 }
893 if (!okay) {
David Sehr709b0702016-10-13 09:12:37 -0700894 AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800895 return false;
896 }
897
898 return true;
899 }
900
Ian Rogers68d8b422014-07-17 11:09:10 -0700901 /*
902 * Verify that the "mode" argument passed to a primitive array Release
903 * function is one of the valid values.
904 */
905 bool CheckReleaseMode(jint mode) {
906 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
907 AbortF("unknown value for release mode: %d", mode);
908 return false;
909 }
910 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700911 }
912
Ian Rogers68d8b422014-07-17 11:09:10 -0700913 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700914 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700915 switch (fmt) {
916 case 'a': // jarray
917 return CheckArray(soa, arg.a);
918 case 'c': // jclass
919 return CheckInstance(soa, kClass, arg.c, false);
920 case 'f': // jfieldID
Andreas Gampe08883de2016-11-08 13:20:52 -0800921 return CheckFieldID(arg.f) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700922 case 'm': // jmethodID
Andreas Gampe13b27842016-11-07 16:48:23 -0800923 return CheckMethodID(arg.m) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700924 case 'r': // release int
925 return CheckReleaseMode(arg.r);
926 case 's': // jstring
927 return CheckInstance(soa, kString, arg.s, false);
928 case 't': // jthrowable
929 return CheckInstance(soa, kThrowable, arg.t, false);
930 case 'E': // JNIEnv*
931 return CheckThread(arg.E);
932 case 'L': // jobject
933 return CheckInstance(soa, kObject, arg.L, true);
Alex Light48ffe062015-08-19 15:23:23 -0700934 case '.': // A VarArgs list
935 return CheckVarArgs(soa, arg.va);
Ian Rogers68d8b422014-07-17 11:09:10 -0700936 default:
937 return CheckNonHeapValue(fmt, arg);
938 }
939 }
940
Alex Light48ffe062015-08-19 15:23:23 -0700941 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700942 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Light48ffe062015-08-19 15:23:23 -0700943 CHECK(args_p != nullptr);
944 VarArgs args(args_p->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800945 ArtMethod* m = CheckMethodID(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700946 if (m == nullptr) {
947 return false;
948 }
949 uint32_t len = 0;
950 const char* shorty = m->GetShorty(&len);
951 // Skip the return type
952 CHECK_GE(len, 1u);
953 len--;
954 shorty++;
955 for (uint32_t i = 0; i < len; i++) {
956 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
957 return false;
958 }
959 }
960 return true;
961 }
962
Ian Rogers68d8b422014-07-17 11:09:10 -0700963 bool CheckNonHeapValue(char fmt, JniValueType arg) {
964 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700965 case 'p': // TODO: pointer - null or readable?
966 case 'v': // JavaVM*
Ian Rogers68d8b422014-07-17 11:09:10 -0700967 case 'D': // jdouble
968 case 'F': // jfloat
Ian Rogers68d8b422014-07-17 11:09:10 -0700969 case 'J': // jlong
Ian Rogers9e937be2018-02-15 17:06:58 -0800970 case 'I': // jint
Ian Rogers68d8b422014-07-17 11:09:10 -0700971 break; // Ignored.
972 case 'b': // jboolean, why two? Fall-through.
973 case 'Z':
Ian Rogers9e937be2018-02-15 17:06:58 -0800974 return CheckBoolean(arg.I);
975 case 'B': // jbyte
976 return CheckByte(arg.I);
977 case 'C': // jchar
978 return CheckChar(arg.I);
979 case 'S': // jshort
980 return CheckShort(arg.I);
Ian Rogers68d8b422014-07-17 11:09:10 -0700981 case 'u': // utf8
982 if ((flags_ & kFlag_Release) != 0) {
983 return CheckNonNull(arg.u);
984 } else {
985 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
986 return CheckUtfString(arg.u, nullable);
987 }
988 case 'w': // jobjectRefType
989 switch (arg.w) {
990 case JNIInvalidRefType:
991 case JNILocalRefType:
992 case JNIGlobalRefType:
993 case JNIWeakGlobalRefType:
994 break;
995 default:
996 AbortF("Unknown reference type");
997 return false;
998 }
999 break;
1000 case 'z': // jsize
1001 return CheckLengthPositive(arg.z);
1002 default:
1003 AbortF("unknown format specifier: '%c'", fmt);
1004 return false;
1005 }
1006 return true;
1007 }
1008
1009 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
1010 std::string* msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001011 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001012 switch (fmt) {
1013 case 'L': // jobject fall-through.
1014 case 'a': // jarray fall-through.
1015 case 's': // jstring fall-through.
1016 case 't': // jthrowable fall-through.
1017 if (arg.L == nullptr) {
1018 *msg += "NULL";
1019 } else {
1020 StringAppendF(msg, "%p", arg.L);
1021 }
1022 break;
1023 case 'c': { // jclass
1024 jclass jc = arg.c;
Mathieu Chartier0795f232016-09-27 18:43:30 -07001025 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -07001026 if (c == nullptr) {
1027 *msg += "NULL";
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001028 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001029 StringAppendF(msg, "INVALID POINTER:%p", jc);
1030 } else if (!c->IsClass()) {
David Sehr709b0702016-10-13 09:12:37 -07001031 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
Ian Rogers68d8b422014-07-17 11:09:10 -07001032 } else {
David Sehr709b0702016-10-13 09:12:37 -07001033 *msg += c->PrettyClass();
Ian Rogers68d8b422014-07-17 11:09:10 -07001034 if (!entry) {
1035 StringAppendF(msg, " (%p)", jc);
1036 }
1037 }
1038 break;
1039 }
1040 case 'f': { // jfieldID
1041 jfieldID fid = arg.f;
Andreas Gampe08883de2016-11-08 13:20:52 -08001042 ArtField* f = jni::DecodeArtField(fid);
David Sehr709b0702016-10-13 09:12:37 -07001043 *msg += ArtField::PrettyField(f);
Ian Rogers68d8b422014-07-17 11:09:10 -07001044 if (!entry) {
1045 StringAppendF(msg, " (%p)", fid);
1046 }
1047 break;
1048 }
1049 case 'm': { // jmethodID
1050 jmethodID mid = arg.m;
Andreas Gampe13b27842016-11-07 16:48:23 -08001051 ArtMethod* m = jni::DecodeArtMethod(mid);
David Sehr709b0702016-10-13 09:12:37 -07001052 *msg += ArtMethod::PrettyMethod(m);
Ian Rogers68d8b422014-07-17 11:09:10 -07001053 if (!entry) {
1054 StringAppendF(msg, " (%p)", mid);
1055 }
1056 break;
1057 }
Alex Light48ffe062015-08-19 15:23:23 -07001058 case '.': {
1059 const VarArgs* va = arg.va;
1060 VarArgs args(va->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -08001061 ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -07001062 uint32_t len;
1063 const char* shorty = m->GetShorty(&len);
1064 CHECK_GE(len, 1u);
1065 // Skip past return value.
1066 len--;
1067 shorty++;
1068 // Remove the previous ', ' from the message.
1069 msg->erase(msg->length() - 2);
1070 for (uint32_t i = 0; i < len; i++) {
1071 *msg += ", ";
1072 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
1073 }
1074 break;
1075 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001076 default:
1077 TraceNonHeapValue(fmt, arg, msg);
1078 break;
1079 }
1080 }
1081
1082 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
1083 switch (fmt) {
1084 case 'B': // jbyte
1085 if (arg.B >= 0 && arg.B < 10) {
1086 StringAppendF(msg, "%d", arg.B);
1087 } else {
1088 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1089 }
1090 break;
1091 case 'C': // jchar
1092 if (arg.C < 0x7f && arg.C >= ' ') {
1093 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1094 } else {
1095 StringAppendF(msg, "U+%x", arg.C);
1096 }
1097 break;
1098 case 'F': // jfloat
1099 StringAppendF(msg, "%g", arg.F);
1100 break;
1101 case 'D': // jdouble
1102 StringAppendF(msg, "%g", arg.D);
1103 break;
1104 case 'S': // jshort
1105 StringAppendF(msg, "%d", arg.S);
1106 break;
1107 case 'i': // jint - fall-through.
1108 case 'I': // jint
1109 StringAppendF(msg, "%d", arg.I);
1110 break;
1111 case 'J': // jlong
1112 StringAppendF(msg, "%" PRId64, arg.J);
1113 break;
1114 case 'Z': // jboolean
1115 case 'b': // jboolean (JNI-style)
1116 *msg += arg.b == JNI_TRUE ? "true" : "false";
1117 break;
1118 case 'V': // void
1119 DCHECK(arg.V == nullptr);
1120 *msg += "void";
1121 break;
1122 case 'v': // JavaVM*
1123 StringAppendF(msg, "(JavaVM*)%p", arg.v);
1124 break;
1125 case 'E':
1126 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1127 break;
1128 case 'z': // non-negative jsize
1129 // You might expect jsize to be size_t, but it's not; it's the same as jint.
1130 // We only treat this specially so we can do the non-negative check.
1131 // TODO: maybe this wasn't worth it?
1132 StringAppendF(msg, "%d", arg.z);
1133 break;
1134 case 'p': // void* ("pointer")
1135 if (arg.p == nullptr) {
1136 *msg += "NULL";
1137 } else {
1138 StringAppendF(msg, "(void*) %p", arg.p);
1139 }
1140 break;
1141 case 'r': { // jint (release mode)
1142 jint releaseMode = arg.r;
1143 if (releaseMode == 0) {
1144 *msg += "0";
1145 } else if (releaseMode == JNI_ABORT) {
1146 *msg += "JNI_ABORT";
1147 } else if (releaseMode == JNI_COMMIT) {
1148 *msg += "JNI_COMMIT";
1149 } else {
1150 StringAppendF(msg, "invalid release mode %d", releaseMode);
1151 }
1152 break;
1153 }
1154 case 'u': // const char* (Modified UTF-8)
1155 if (arg.u == nullptr) {
1156 *msg += "NULL";
1157 } else {
1158 StringAppendF(msg, "\"%s\"", arg.u);
1159 }
1160 break;
1161 case 'w': // jobjectRefType
1162 switch (arg.w) {
1163 case JNIInvalidRefType:
1164 *msg += "invalid reference type";
1165 break;
1166 case JNILocalRefType:
1167 *msg += "local ref type";
1168 break;
1169 case JNIGlobalRefType:
1170 *msg += "global ref type";
1171 break;
1172 case JNIWeakGlobalRefType:
1173 *msg += "weak global ref type";
1174 break;
1175 default:
1176 *msg += "unknown ref type";
1177 break;
1178 }
1179 break;
Ian Rogers68d8b422014-07-17 11:09:10 -07001180 default:
1181 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1182 }
1183 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001184 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001185 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -07001186 *
1187 * Since we're dealing with objects, switch to "running" mode.
1188 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001189 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001190 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001191 if (UNLIKELY(java_array == nullptr)) {
1192 AbortF("jarray was NULL");
1193 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001194 }
1195
Mathieu Chartier0795f232016-09-27 18:43:30 -07001196 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001197 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001198 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001199 AbortF("jarray is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -07001200 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)),
1201 java_array,
1202 a.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -07001203 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001204 } else if (!a->IsArrayInstance()) {
David Sehr709b0702016-10-13 09:12:37 -07001205 AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001206 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001207 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001208 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001209 }
1210
Ian Rogers9e937be2018-02-15 17:06:58 -08001211 bool CheckBoolean(jint z) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001212 if (z != JNI_TRUE && z != JNI_FALSE) {
Ian Rogers9e937be2018-02-15 17:06:58 -08001213 // Note, broken booleans are always fatal.
Ian Rogers68d8b422014-07-17 11:09:10 -07001214 AbortF("unexpected jboolean value: %d", z);
1215 return false;
1216 }
1217 return true;
1218 }
1219
Ian Rogers9e937be2018-02-15 17:06:58 -08001220 bool CheckByte(jint b) {
1221 if (b < std::numeric_limits<jbyte>::min() ||
1222 b > std::numeric_limits<jbyte>::max()) {
1223 if (kBrokenPrimitivesAreFatal) {
1224 AbortF("unexpected jbyte value: %d", b);
1225 return false;
1226 } else {
1227 LOG(WARNING) << "Unexpected jbyte value: " << b;
1228 }
1229 }
1230 return true;
1231 }
1232
1233 bool CheckShort(jint s) {
1234 if (s < std::numeric_limits<jshort>::min() ||
1235 s > std::numeric_limits<jshort>::max()) {
1236 if (kBrokenPrimitivesAreFatal) {
1237 AbortF("unexpected jshort value: %d", s);
1238 return false;
1239 } else {
1240 LOG(WARNING) << "Unexpected jshort value: " << s;
1241 }
1242 }
1243 return true;
1244 }
1245
1246 bool CheckChar(jint c) {
1247 if (c < std::numeric_limits<jchar>::min() ||
1248 c > std::numeric_limits<jchar>::max()) {
1249 if (kBrokenPrimitivesAreFatal) {
1250 AbortF("unexpected jchar value: %d", c);
1251 return false;
1252 } else {
1253 LOG(WARNING) << "Unexpected jchar value: " << c;
1254 }
1255 }
1256 return true;
1257 }
1258
Ian Rogers68d8b422014-07-17 11:09:10 -07001259 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001260 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001261 AbortF("negative jsize: %d", length);
1262 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001263 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001264 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001265 }
1266
Andreas Gampe08883de2016-11-08 13:20:52 -08001267 ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001268 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001269 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001270 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001271 }
Andreas Gampe08883de2016-11-08 13:20:52 -08001272 ArtField* f = jni::DecodeArtField(fid);
Mathieu Chartierc7853442015-03-27 14:35:38 -07001273 // TODO: Better check here.
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001274 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001275 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001276 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001277 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001278 }
1279 return f;
1280 }
1281
Andreas Gampe13b27842016-11-07 16:48:23 -08001282 ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001283 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001284 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001285 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001286 }
Andreas Gampe13b27842016-11-07 16:48:23 -08001287 ArtMethod* m = jni::DecodeArtMethod(mid);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001288 // TODO: Better check here.
Vladimir Markod93e3742018-07-18 10:58:13 +01001289 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass().Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001290 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001291 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001292 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001293 }
1294 return m;
1295 }
1296
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001297 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001298 Thread* self = Thread::Current();
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001299 CHECK(self != nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -07001300
Daniel Erat35e827a2016-05-10 18:07:18 -06001301 // Get the current thread's JNIEnv by going through our TLS pointer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001302 JNIEnvExt* threadEnv = self->GetJniEnv();
1303
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001304 // Verify that the current thread is (a) attached and (b) associated with
1305 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001306 if (env != threadEnv) {
Daniel Erat35e827a2016-05-10 18:07:18 -06001307 // Get the thread owning the JNIEnv that's being used.
Ian Rogersac4d45a2018-02-15 11:19:01 -08001308 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->GetSelf();
Ian Rogers68d8b422014-07-17 11:09:10 -07001309 AbortF("thread %s using JNIEnv* from thread %s",
Daniel Erat35e827a2016-05-10 18:07:18 -06001310 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001311 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001312 }
1313
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001314 // Verify that, if this thread previously made a critical "get" call, we
1315 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001316 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001317 case kFlag_CritOkay: // okay to call this method
1318 break;
1319 case kFlag_CritBad: // not okay to call
Ian Rogersac4d45a2018-02-15 11:19:01 -08001320 if (threadEnv->GetCritical() > 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001321 AbortF("thread %s using JNI after critical get",
1322 ToStr<Thread>(*self).c_str());
1323 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001324 }
1325 break;
1326 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001327 // Don't check here; we allow nested gets.
Ian Rogersac4d45a2018-02-15 11:19:01 -08001328 if (threadEnv->GetCritical() == 0) {
1329 threadEnv->SetCriticalStartUs(self->GetCpuMicroTime());
Ian Rogers55256cb2017-12-21 17:07:11 -08001330 }
Ian Rogersac4d45a2018-02-15 11:19:01 -08001331 threadEnv->SetCritical(threadEnv->GetCritical() + 1);
Elliott Hughesa2501992011-08-26 19:39:54 -07001332 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001333 case kFlag_CritRelease: // this is a "release" call
Ian Rogersac4d45a2018-02-15 11:19:01 -08001334 if (threadEnv->GetCritical() == 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001335 AbortF("thread %s called too many critical releases",
1336 ToStr<Thread>(*self).c_str());
1337 return false;
Ian Rogersac4d45a2018-02-15 11:19:01 -08001338 } else if (threadEnv->GetCritical() == 1) {
Ian Rogers55256cb2017-12-21 17:07:11 -08001339 // Leaving the critical region, possibly warn about long critical regions.
Ian Rogersac4d45a2018-02-15 11:19:01 -08001340 uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->GetCriticalStartUs();
Ian Rogers55256cb2017-12-21 17:07:11 -08001341 if (critical_duration_us > kCriticalWarnTimeUs) {
1342 LOG(WARNING) << "JNI critical lock held for "
1343 << PrettyDuration(UsToNs(critical_duration_us)) << " on " << *self;
1344 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001345 }
Ian Rogersac4d45a2018-02-15 11:19:01 -08001346 threadEnv->SetCritical(threadEnv->GetCritical() - 1);
Elliott Hughesa2501992011-08-26 19:39:54 -07001347 break;
1348 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001349 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001350 }
1351
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001352 // Verify that, if an exception has been raised, the native code doesn't
1353 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001354 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001355 mirror::Throwable* exception = self->GetException();
1356 AbortF("JNI %s called with pending exception %s",
1357 function_name_,
1358 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001359 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001360 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001361 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001362 }
1363
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001364 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001365 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001366 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001367 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001368 AbortF("non-nullable const char* was NULL");
1369 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001370 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001371 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001372 }
1373
Ian Rogersef7d42f2014-01-06 12:55:46 -08001374 const char* errorKind = nullptr;
Andreas Gampeef4afe92015-07-27 21:03:25 -07001375 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001376 if (errorKind != nullptr) {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001377 // This is an expensive loop that will resize often, but this isn't supposed to hit in
1378 // practice anyways.
1379 std::ostringstream oss;
1380 oss << std::hex;
1381 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1382 while (*tmp != 0) {
1383 if (tmp == utf8) {
1384 oss << "<";
1385 }
1386 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1387 if (tmp == utf8) {
1388 oss << '>';
1389 }
1390 tmp++;
1391 if (*tmp != 0) {
1392 oss << ' ';
1393 }
1394 }
1395
Ian Rogers68d8b422014-07-17 11:09:10 -07001396 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
Andreas Gampeef4afe92015-07-27 21:03:25 -07001397 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001398 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001399 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001400 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001401 }
1402
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001403 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1404 // sequences in place of encoded surrogate pairs.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001405 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001406 while (*bytes != '\0') {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001407 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
Elliott Hughesa2501992011-08-26 19:39:54 -07001408 // Switch on the high four bits.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001409 switch (*utf8 >> 4) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001410 case 0x00:
1411 case 0x01:
1412 case 0x02:
1413 case 0x03:
1414 case 0x04:
1415 case 0x05:
1416 case 0x06:
1417 case 0x07:
1418 // Bit pattern 0xxx. No need for any extra bytes.
1419 break;
1420 case 0x08:
1421 case 0x09:
1422 case 0x0a:
1423 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001424 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001425 *errorKind = "start";
1426 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001427 case 0x0f:
1428 // Bit pattern 1111, which might be the start of a 4 byte sequence.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001429 if ((*utf8 & 0x08) == 0) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001430 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1431 // We consume one continuation byte here, and fall through to consume two more.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001432 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1433 if ((*utf8 & 0xc0) != 0x80) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001434 *errorKind = "continuation";
1435 return utf8;
1436 }
1437 } else {
1438 *errorKind = "start";
1439 return utf8;
1440 }
1441
1442 // Fall through to the cases below to consume two more continuation bytes.
1443 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001444 case 0x0e:
1445 // Bit pattern 1110, so there are two additional bytes.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001446 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1447 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001448 *errorKind = "continuation";
1449 return utf8;
1450 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001451
1452 // Fall through to consume one more continuation byte.
1453 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001454 case 0x0c:
1455 case 0x0d:
1456 // Bit pattern 110x, so there is one additional byte.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001457 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1458 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001459 *errorKind = "continuation";
1460 return utf8;
1461 }
1462 break;
1463 }
1464 }
Yi Kong4b22b342018-08-02 14:43:21 -07001465 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001466 }
1467
Ian Rogers68d8b422014-07-17 11:09:10 -07001468 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1469 va_list args;
1470 va_start(args, fmt);
1471 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1472 va_end(args);
1473 }
1474
1475 // The name of the JNI function being checked.
1476 const char* const function_name_;
1477
Elliott Hughes92cb4982011-12-16 16:57:28 -08001478 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001479
Ian Rogers55256cb2017-12-21 17:07:11 -08001480 const uint16_t flags_;
1481
Ian Rogers68d8b422014-07-17 11:09:10 -07001482 const bool has_method_;
1483
Elliott Hughesa2501992011-08-26 19:39:54 -07001484 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1485};
1486
Elliott Hughesa2501992011-08-26 19:39:54 -07001487/*
1488 * ===========================================================================
1489 * Guarded arrays
1490 * ===========================================================================
1491 */
1492
Elliott Hughesa2501992011-08-26 19:39:54 -07001493/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001494class GuardedCopy {
1495 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001496 /*
1497 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1498 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001499 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001500 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001501 const size_t new_len = LengthIncludingRedZones(len);
1502 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001503
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001504 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001505 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001506 if (!mod_okay) {
1507 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001508 }
1509
Ian Rogers68d8b422014-07-17 11:09:10 -07001510 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001511
Ian Rogers68d8b422014-07-17 11:09:10 -07001512 // Fill begin region with canary pattern.
1513 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1514 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1515 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1516 if (kCanary[j] == '\0') {
1517 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001518 } else {
1519 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001520 }
1521 }
1522
1523 // Copy the data in; note "len" could be zero.
1524 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1525
1526 // Fill end region with canary pattern.
1527 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1528 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1529 if (kCanary[j] == '\0') {
1530 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001531 } else {
1532 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001533 }
1534 }
1535
1536 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001537 }
1538
1539 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001540 * Create a guarded copy of a primitive array. Modifications to the copied
1541 * data are allowed. Returns a pointer to the copied data.
1542 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001543 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1544 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001545 ScopedObjectAccess soa(env);
1546
Mathieu Chartier0795f232016-09-27 18:43:30 -07001547 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Ian Rogers68d8b422014-07-17 11:09:10 -07001548 size_t component_size = a->GetClass()->GetComponentSize();
1549 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001550 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001551 if (is_copy != nullptr) {
1552 *is_copy = JNI_TRUE;
1553 }
1554 return result;
1555 }
1556
1557 /*
1558 * Perform the array "release" operation, which may or may not copy data
1559 * back into the managed heap, and may or may not release the underlying storage.
1560 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001561 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1562 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1563 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001564 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001565 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1566 return nullptr;
1567 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001568 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1569 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001570 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001571 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001572 }
1573 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001574 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001575 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001576 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001577 }
1578
1579
1580 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001581 * Free up the guard buffer, scrub it, and return the original pointer.
1582 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001583 static void* Destroy(void* embedded_buf) {
1584 GuardedCopy* copy = FromEmbedded(embedded_buf);
1585 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1586 size_t len = LengthIncludingRedZones(copy->original_length_);
1587 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001588 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001589 }
1590
1591 /*
1592 * Verify the guard area and, if "modOkay" is false, that the data itself
1593 * has not been altered.
1594 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001595 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001596 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001597 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1598 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1599 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001600 }
1601
1602 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001603 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001604 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1605 }
1606
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001607 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001608 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001609 if (result == MAP_FAILED) {
1610 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1611 }
1612 return reinterpret_cast<uint8_t*>(result);
1613 }
1614
Ian Rogers68d8b422014-07-17 11:09:10 -07001615 static void DebugFree(void* buf, size_t len) {
1616 if (munmap(buf, len) != 0) {
1617 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001618 }
1619 }
1620
Ian Rogers68d8b422014-07-17 11:09:10 -07001621 static size_t LengthIncludingRedZones(size_t len) {
1622 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001623 }
1624
Ian Rogers68d8b422014-07-17 11:09:10 -07001625 // Get the GuardedCopy from the interior pointer.
1626 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1627 return reinterpret_cast<GuardedCopy*>(
1628 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001629 }
1630
Ian Rogers68d8b422014-07-17 11:09:10 -07001631 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1632 return reinterpret_cast<const GuardedCopy*>(
1633 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001634 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001635
1636 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1637 va_list args;
1638 va_start(args, fmt);
1639 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1640 va_end(args);
1641 }
1642
1643 bool CheckHeader(const char* function_name, bool mod_okay) const {
1644 static const uint32_t kMagicCmp = kGuardMagic;
1645
1646 // Before we do anything with "pExtra", check the magic number. We
1647 // do the check with memcmp rather than "==" in case the pointer is
1648 // unaligned. If it points to completely bogus memory we're going
1649 // to crash, but there's no easy way around that.
1650 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1651 uint8_t buf[4];
1652 memcpy(buf, &magic_, 4);
1653 AbortF(function_name,
1654 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1655 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1656 return false;
1657 }
1658
1659 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1660 // told the client that we made a copy, there's no reason they can't alter the buffer.
1661 if (!mod_okay) {
1662 uLong computed_adler =
1663 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1664 if (computed_adler != adler_) {
1665 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1666 computed_adler, adler_, this);
1667 return false;
1668 }
1669 }
1670 return true;
1671 }
1672
1673 bool CheckRedZones(const char* function_name) const {
1674 // Check the begin red zone.
1675 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1676 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1677 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1678 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1679 return false;
1680 }
1681 if (kCanary[j] == '\0') {
1682 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001683 } else {
1684 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001685 }
1686 }
1687
1688 // Check end region.
1689 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1690 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1691 size_t offset_from_buffer_start =
1692 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1693 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1694 offset_from_buffer_start);
1695 return false;
1696 }
1697 if (kCanary[j] == '\0') {
1698 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001699 } else {
1700 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001701 }
1702 }
1703 return true;
1704 }
1705
1706 // Location that canary value will be written before the guarded region.
1707 const char* StartRedZone() const {
1708 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1709 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1710 }
1711
1712 // Return the interior embedded buffer.
1713 const uint8_t* BufferWithinRedZones() const {
1714 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1715 return embedded_buf;
1716 }
1717
1718 // Location that canary value will be written after the guarded region.
1719 const char* EndRedZone() const {
1720 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1721 size_t buf_len = LengthIncludingRedZones(original_length_);
1722 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1723 }
1724
1725 static constexpr size_t kRedZoneSize = 512;
1726 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1727
1728 // Value written before and after the guarded array.
1729 static const char* const kCanary;
1730
1731 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1732
1733 const uint32_t magic_;
1734 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001735 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001736 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001737};
Ian Rogers68d8b422014-07-17 11:09:10 -07001738const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001739
1740/*
1741 * ===========================================================================
1742 * JNI functions
1743 * ===========================================================================
1744 */
1745
1746class CheckJNI {
1747 public:
1748 static jint GetVersion(JNIEnv* env) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001749 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07001750 ScopedObjectAccess soa(env);
1751 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1752 JniValueType args[1] = {{.E = env }};
1753 if (sc.Check(soa, true, "E", args)) {
1754 JniValueType result;
1755 result.I = baseEnv(env)->GetVersion(env);
1756 if (sc.Check(soa, false, "I", &result)) {
1757 return result.I;
1758 }
1759 }
1760 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001761 }
1762
Ian Rogers68d8b422014-07-17 11:09:10 -07001763 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001764 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07001765 ScopedObjectAccess soa(env);
1766 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1767 JniValueType args[2] = {{.E = env }, {.p = vm}};
1768 if (sc.Check(soa, true, "Ep", args)) {
1769 JniValueType result;
1770 result.i = baseEnv(env)->GetJavaVM(env, vm);
1771 if (sc.Check(soa, false, "i", &result)) {
1772 return result.i;
1773 }
1774 }
1775 return JNI_ERR;
1776 }
1777
1778 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001779 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07001780 ScopedObjectAccess soa(env);
1781 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1782 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1783 if (sc.Check(soa, true, "EcpI", args)) {
1784 JniValueType result;
1785 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1786 if (sc.Check(soa, false, "i", &result)) {
1787 return result.i;
1788 }
1789 }
1790 return JNI_ERR;
1791 }
1792
1793 static jint UnregisterNatives(JNIEnv* env, jclass c) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001794 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07001795 ScopedObjectAccess soa(env);
1796 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1797 JniValueType args[2] = {{.E = env }, {.c = c}};
1798 if (sc.Check(soa, true, "Ec", args)) {
1799 JniValueType result;
1800 result.i = baseEnv(env)->UnregisterNatives(env, c);
1801 if (sc.Check(soa, false, "i", &result)) {
1802 return result.i;
1803 }
1804 }
1805 return JNI_ERR;
1806 }
1807
1808 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001809 CHECK_ATTACHED_THREAD(__FUNCTION__, JNIInvalidRefType);
Ian Rogersc0542af2014-09-03 16:16:56 -07001810 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1811 // know the object is invalid. The spec says that passing invalid objects or even ones that
1812 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001813 ScopedObjectAccess soa(env);
1814 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001815 JniValueType args[2] = {{.E = env }, {.L = obj}};
1816 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001817 JniValueType result;
1818 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1819 if (sc.Check(soa, false, "w", &result)) {
1820 return result.w;
1821 }
1822 }
1823 return JNIInvalidRefType;
1824 }
1825
1826 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1827 jsize bufLen) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001828 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001829 ScopedObjectAccess soa(env);
1830 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1831 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1832 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1833 JniValueType result;
1834 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1835 if (sc.Check(soa, false, "c", &result)) {
1836 return result.c;
1837 }
1838 }
1839 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001840 }
1841
1842 static jclass FindClass(JNIEnv* env, const char* name) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001843 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001844 ScopedObjectAccess soa(env);
1845 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1846 JniValueType args[2] = {{.E = env}, {.u = name}};
1847 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1848 JniValueType result;
1849 result.c = baseEnv(env)->FindClass(env, name);
1850 if (sc.Check(soa, false, "c", &result)) {
1851 return result.c;
1852 }
1853 }
1854 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001855 }
1856
Elliott Hughese84278b2012-03-22 10:06:53 -07001857 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001858 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001859 ScopedObjectAccess soa(env);
1860 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1861 JniValueType args[2] = {{.E = env}, {.c = c}};
1862 if (sc.Check(soa, true, "Ec", args)) {
1863 JniValueType result;
1864 result.c = baseEnv(env)->GetSuperclass(env, c);
1865 if (sc.Check(soa, false, "c", &result)) {
1866 return result.c;
1867 }
1868 }
1869 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001870 }
1871
Elliott Hughese84278b2012-03-22 10:06:53 -07001872 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001873 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
Ian Rogers68d8b422014-07-17 11:09:10 -07001874 ScopedObjectAccess soa(env);
1875 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1876 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1877 if (sc.Check(soa, true, "Ecc", args)) {
1878 JniValueType result;
1879 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1880 if (sc.Check(soa, false, "b", &result)) {
1881 return result.b;
1882 }
1883 }
1884 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001885 }
1886
1887 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001888 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001889 ScopedObjectAccess soa(env);
1890 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1891 JniValueType args[2] = {{.E = env}, {.L = method}};
1892 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1893 JniValueType result;
1894 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1895 if (sc.Check(soa, false, "m", &result)) {
1896 return result.m;
1897 }
1898 }
1899 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001900 }
1901
1902 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001903 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001904 ScopedObjectAccess soa(env);
1905 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1906 JniValueType args[2] = {{.E = env}, {.L = field}};
1907 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1908 JniValueType result;
1909 result.f = baseEnv(env)->FromReflectedField(env, field);
1910 if (sc.Check(soa, false, "f", &result)) {
1911 return result.f;
1912 }
1913 }
1914 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001915 }
1916
1917 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001918 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001919 ScopedObjectAccess soa(env);
1920 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogers9e937be2018-02-15 17:06:58 -08001921 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.I = isStatic}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001922 if (sc.Check(soa, true, "Ecmb", args)) {
1923 JniValueType result;
1924 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1925 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1926 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1927 return result.L;
1928 }
1929 }
1930 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001931 }
1932
1933 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001934 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001935 ScopedObjectAccess soa(env);
1936 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogers9e937be2018-02-15 17:06:58 -08001937 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.I = isStatic}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001938 if (sc.Check(soa, true, "Ecfb", args)) {
1939 JniValueType result;
1940 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1941 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1942 DCHECK(sc.CheckReflectedField(soa, result.L));
1943 return result.L;
1944 }
1945 }
1946 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001947 }
1948
1949 static jint Throw(JNIEnv* env, jthrowable obj) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001950 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07001951 ScopedObjectAccess soa(env);
1952 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1953 JniValueType args[2] = {{.E = env}, {.t = obj}};
1954 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1955 JniValueType result;
1956 result.i = baseEnv(env)->Throw(env, obj);
1957 if (sc.Check(soa, false, "i", &result)) {
1958 return result.i;
1959 }
1960 }
1961 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001962 }
1963
Elliott Hughese84278b2012-03-22 10:06:53 -07001964 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001965 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07001966 ScopedObjectAccess soa(env);
1967 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001968 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001969 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1970 JniValueType result;
1971 result.i = baseEnv(env)->ThrowNew(env, c, message);
1972 if (sc.Check(soa, false, "i", &result)) {
1973 return result.i;
1974 }
1975 }
1976 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001977 }
1978
1979 static jthrowable ExceptionOccurred(JNIEnv* env) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001980 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001981 ScopedObjectAccess soa(env);
1982 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1983 JniValueType args[1] = {{.E = env}};
1984 if (sc.Check(soa, true, "E", args)) {
1985 JniValueType result;
1986 result.t = baseEnv(env)->ExceptionOccurred(env);
1987 if (sc.Check(soa, false, "t", &result)) {
1988 return result.t;
1989 }
1990 }
1991 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001992 }
1993
1994 static void ExceptionDescribe(JNIEnv* env) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07001995 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Ian Rogers68d8b422014-07-17 11:09:10 -07001996 ScopedObjectAccess soa(env);
1997 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1998 JniValueType args[1] = {{.E = env}};
1999 if (sc.Check(soa, true, "E", args)) {
2000 JniValueType result;
2001 baseEnv(env)->ExceptionDescribe(env);
2002 result.V = nullptr;
2003 sc.Check(soa, false, "V", &result);
2004 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002005 }
2006
2007 static void ExceptionClear(JNIEnv* env) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002008 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Ian Rogers68d8b422014-07-17 11:09:10 -07002009 ScopedObjectAccess soa(env);
2010 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2011 JniValueType args[1] = {{.E = env}};
2012 if (sc.Check(soa, true, "E", args)) {
2013 JniValueType result;
2014 baseEnv(env)->ExceptionClear(env);
2015 result.V = nullptr;
2016 sc.Check(soa, false, "V", &result);
2017 }
2018 }
2019
2020 static jboolean ExceptionCheck(JNIEnv* env) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002021 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
Ian Rogers68d8b422014-07-17 11:09:10 -07002022 ScopedObjectAccess soa(env);
2023 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
2024 JniValueType args[1] = {{.E = env}};
2025 if (sc.Check(soa, true, "E", args)) {
2026 JniValueType result;
2027 result.b = baseEnv(env)->ExceptionCheck(env);
2028 if (sc.Check(soa, false, "b", &result)) {
2029 return result.b;
2030 }
2031 }
2032 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07002033 }
2034
2035 static void FatalError(JNIEnv* env, const char* msg) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002036 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Elliott Hughesc4378df2013-06-14 17:05:13 -07002037 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
2038 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
2039 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07002040 ScopedObjectAccess soa(env);
2041 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
2042 JniValueType args[2] = {{.E = env}, {.u = msg}};
2043 if (sc.Check(soa, true, "Eu", args)) {
2044 JniValueType result;
2045 baseEnv(env)->FatalError(env, msg);
2046 // Unreachable.
2047 result.V = nullptr;
2048 sc.Check(soa, false, "V", &result);
2049 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002050 }
2051
2052 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002053 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002054 ScopedObjectAccess soa(env);
2055 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2056 JniValueType args[2] = {{.E = env}, {.I = capacity}};
2057 if (sc.Check(soa, true, "EI", args)) {
2058 JniValueType result;
2059 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
2060 if (sc.Check(soa, false, "i", &result)) {
2061 return result.i;
2062 }
2063 }
2064 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002065 }
2066
2067 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002068 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002069 ScopedObjectAccess soa(env);
2070 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2071 JniValueType args[2] = {{.E = env}, {.L = res}};
2072 if (sc.Check(soa, true, "EL", args)) {
2073 JniValueType result;
2074 result.L = baseEnv(env)->PopLocalFrame(env, res);
2075 sc.Check(soa, false, "L", &result);
2076 return result.L;
2077 }
2078 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002079 }
2080
2081 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002082 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07002083 }
2084
Ian Rogers68d8b422014-07-17 11:09:10 -07002085 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
2086 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07002087 }
2088
2089 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002090 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07002091 }
2092
Ian Rogers68d8b422014-07-17 11:09:10 -07002093 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
2094 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07002095 }
2096
Ian Rogers68d8b422014-07-17 11:09:10 -07002097 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
2098 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
2099 }
2100
2101 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
2102 DeleteRef(__FUNCTION__, env, obj, kLocal);
2103 }
2104
2105 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002106 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002107 ScopedObjectAccess soa(env);
2108 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2109 JniValueType args[2] = {{.E = env}, {.I = capacity}};
2110 if (sc.Check(soa, true, "EI", args)) {
2111 JniValueType result;
2112 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
2113 if (sc.Check(soa, false, "i", &result)) {
2114 return result.i;
2115 }
2116 }
2117 return JNI_ERR;
2118 }
2119
2120 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002121 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
Ian Rogers68d8b422014-07-17 11:09:10 -07002122 ScopedObjectAccess soa(env);
2123 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2124 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
2125 if (sc.Check(soa, true, "ELL", args)) {
2126 JniValueType result;
2127 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
2128 if (sc.Check(soa, false, "b", &result)) {
2129 return result.b;
2130 }
2131 }
2132 return JNI_FALSE;
2133 }
2134
2135 static jobject AllocObject(JNIEnv* env, jclass c) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002136 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002137 ScopedObjectAccess soa(env);
2138 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2139 JniValueType args[2] = {{.E = env}, {.c = c}};
2140 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
2141 JniValueType result;
2142 result.L = baseEnv(env)->AllocObject(env, c);
2143 if (sc.Check(soa, false, "L", &result)) {
2144 return result.L;
2145 }
2146 }
2147 return nullptr;
2148 }
2149
2150 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002151 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002152 ScopedObjectAccess soa(env);
2153 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002154 VarArgs rest(mid, vargs);
2155 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2156 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002157 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002158 JniValueType result;
2159 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2160 if (sc.Check(soa, false, "L", &result)) {
2161 return result.L;
2162 }
2163 }
2164 return nullptr;
2165 }
2166
2167 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002168 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002169 va_list args;
2170 va_start(args, mid);
2171 jobject result = NewObjectV(env, c, mid, args);
2172 va_end(args);
2173 return result;
2174 }
2175
Elliott Hughes22352f32018-06-15 17:33:58 -07002176 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, const jvalue* vargs) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002177 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002178 ScopedObjectAccess soa(env);
2179 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002180 VarArgs rest(mid, vargs);
2181 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2182 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002183 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002184 JniValueType result;
2185 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2186 if (sc.Check(soa, false, "L", &result)) {
2187 return result.L;
2188 }
2189 }
2190 return nullptr;
2191 }
2192
2193 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002194 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002195 ScopedObjectAccess soa(env);
2196 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2197 JniValueType args[2] = {{.E = env}, {.L = obj}};
2198 if (sc.Check(soa, true, "EL", args)) {
2199 JniValueType result;
2200 result.c = baseEnv(env)->GetObjectClass(env, obj);
2201 if (sc.Check(soa, false, "c", &result)) {
2202 return result.c;
2203 }
2204 }
2205 return nullptr;
2206 }
2207
2208 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002209 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
Ian Rogers68d8b422014-07-17 11:09:10 -07002210 ScopedObjectAccess soa(env);
2211 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2212 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2213 if (sc.Check(soa, true, "ELc", args)) {
2214 JniValueType result;
2215 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2216 if (sc.Check(soa, false, "b", &result)) {
2217 return result.b;
2218 }
2219 }
2220 return JNI_FALSE;
2221 }
2222
2223 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2224 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2225 }
2226
2227 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2228 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2229 }
2230
2231 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2232 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2233 }
2234
2235 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2236 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2237 }
2238
Ian Rogers9e937be2018-02-15 17:06:58 -08002239#define FIELD_ACCESSORS(jtype, name, ptype, shorty, slot_sized_shorty) \
Ian Rogers68d8b422014-07-17 11:09:10 -07002240 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2241 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2242 } \
2243 \
2244 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2245 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2246 } \
2247 \
2248 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2249 JniValueType value; \
Ian Rogers9e937be2018-02-15 17:06:58 -08002250 value.slot_sized_shorty = v; \
Ian Rogers68d8b422014-07-17 11:09:10 -07002251 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2252 } \
2253 \
2254 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2255 JniValueType value; \
Ian Rogers9e937be2018-02-15 17:06:58 -08002256 value.slot_sized_shorty = v; \
Ian Rogers68d8b422014-07-17 11:09:10 -07002257 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2258 }
2259
Ian Rogers9e937be2018-02-15 17:06:58 -08002260 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L, L)
2261 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z, I)
2262 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B, I)
2263 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C, I)
2264 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S, I)
2265 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I, I)
2266 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J, J)
2267 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F, F)
2268 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D, D)
Ian Rogers68d8b422014-07-17 11:09:10 -07002269#undef FIELD_ACCESSORS
2270
Elliott Hughes22352f32018-06-15 17:33:58 -07002271 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, const jvalue* vargs) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002272 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2273 }
2274
2275 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
Elliott Hughes22352f32018-06-15 17:33:58 -07002276 const jvalue* vargs) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002277 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2278 }
2279
Elliott Hughes22352f32018-06-15 17:33:58 -07002280 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, const jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01002281 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07002282 }
2283
2284 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2285 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2286 }
2287
2288 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2289 va_list vargs) {
2290 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2291 }
2292
2293 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2294 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2295 }
2296
2297 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2298 va_list vargs;
2299 va_start(vargs, mid);
2300 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2301 va_end(vargs);
2302 }
2303
2304 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2305 va_list vargs;
2306 va_start(vargs, mid);
2307 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2308 va_end(vargs);
2309 }
2310
2311 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2312 va_list vargs;
2313 va_start(vargs, mid);
2314 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2315 va_end(vargs);
2316 }
2317
2318#define CALL(rtype, name, ptype, shorty) \
Elliott Hughes22352f32018-06-15 17:33:58 -07002319 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, const jvalue* vargs) { \
Ian Rogers68d8b422014-07-17 11:09:10 -07002320 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2321 } \
2322 \
2323 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
Elliott Hughes22352f32018-06-15 17:33:58 -07002324 const jvalue* vargs) { \
Ian Rogers68d8b422014-07-17 11:09:10 -07002325 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2326 } \
2327 \
Elliott Hughes22352f32018-06-15 17:33:58 -07002328 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, const jvalue* vargs) { \
Ian Rogers68d8b422014-07-17 11:09:10 -07002329 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2330 } \
2331 \
2332 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2333 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2334 } \
2335 \
2336 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2337 va_list vargs) { \
2338 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2339 } \
2340 \
2341 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2342 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2343 } \
2344 \
2345 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2346 va_list vargs; \
2347 va_start(vargs, mid); \
2348 rtype result = \
2349 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2350 va_end(vargs); \
2351 return result; \
2352 } \
2353 \
2354 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2355 ...) { \
2356 va_list vargs; \
2357 va_start(vargs, mid); \
2358 rtype result = \
2359 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2360 va_end(vargs); \
2361 return result; \
2362 } \
2363 \
2364 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2365 va_list vargs; \
2366 va_start(vargs, mid); \
2367 rtype result = \
2368 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2369 va_end(vargs); \
2370 return result; \
2371 }
2372
2373 CALL(jobject, Object, Primitive::kPrimNot, L)
2374 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2375 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2376 CALL(jchar, Char, Primitive::kPrimChar, C)
2377 CALL(jshort, Short, Primitive::kPrimShort, S)
2378 CALL(jint, Int, Primitive::kPrimInt, I)
2379 CALL(jlong, Long, Primitive::kPrimLong, J)
2380 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2381 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2382#undef CALL
2383
2384 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002385 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002386 ScopedObjectAccess soa(env);
2387 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2388 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2389 if (sc.Check(soa, true, "Epz", args)) {
2390 JniValueType result;
2391 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2392 if (sc.Check(soa, false, "s", &result)) {
2393 return result.s;
2394 }
2395 }
2396 return nullptr;
2397 }
2398
2399 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002400 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002401 ScopedObjectAccess soa(env);
2402 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2403 JniValueType args[2] = {{.E = env}, {.u = chars}};
2404 if (sc.Check(soa, true, "Eu", args)) {
2405 JniValueType result;
2406 // TODO: stale? show pointer and truncate string.
2407 result.s = baseEnv(env)->NewStringUTF(env, chars);
2408 if (sc.Check(soa, false, "s", &result)) {
2409 return result.s;
2410 }
2411 }
2412 return nullptr;
2413 }
2414
2415 static jsize GetStringLength(JNIEnv* env, jstring string) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002416 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002417 ScopedObjectAccess soa(env);
2418 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2419 JniValueType args[2] = {{.E = env}, {.s = string}};
2420 if (sc.Check(soa, true, "Es", args)) {
2421 JniValueType result;
2422 result.z = baseEnv(env)->GetStringLength(env, string);
2423 if (sc.Check(soa, false, "z", &result)) {
2424 return result.z;
2425 }
2426 }
2427 return JNI_ERR;
2428 }
2429
2430 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002431 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002432 ScopedObjectAccess soa(env);
2433 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2434 JniValueType args[2] = {{.E = env}, {.s = string}};
2435 if (sc.Check(soa, true, "Es", args)) {
2436 JniValueType result;
2437 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2438 if (sc.Check(soa, false, "z", &result)) {
2439 return result.z;
2440 }
2441 }
2442 return JNI_ERR;
2443 }
2444
2445 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2446 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2447 is_copy, false, false));
2448 }
2449
2450 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2451 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2452 is_copy, true, false));
2453 }
2454
2455 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2456 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2457 is_copy, false, true));
2458 }
2459
2460 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2461 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2462 }
2463
2464 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2465 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2466 }
2467
2468 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2469 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2470 }
2471
2472 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002473 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Ian Rogers68d8b422014-07-17 11:09:10 -07002474 ScopedObjectAccess soa(env);
2475 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2476 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2477 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2478 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2479 if (sc.Check(soa, true, "EsIIp", args)) {
2480 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2481 JniValueType result;
2482 result.V = nullptr;
2483 sc.Check(soa, false, "V", &result);
2484 }
2485 }
2486
2487 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002488 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Ian Rogers68d8b422014-07-17 11:09:10 -07002489 ScopedObjectAccess soa(env);
2490 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2491 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2492 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2493 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2494 if (sc.Check(soa, true, "EsIIp", args)) {
2495 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2496 JniValueType result;
2497 result.V = nullptr;
2498 sc.Check(soa, false, "V", &result);
2499 }
2500 }
2501
2502 static jsize GetArrayLength(JNIEnv* env, jarray array) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002503 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002504 ScopedObjectAccess soa(env);
2505 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2506 JniValueType args[2] = {{.E = env}, {.a = array}};
2507 if (sc.Check(soa, true, "Ea", args)) {
2508 JniValueType result;
2509 result.z = baseEnv(env)->GetArrayLength(env, array);
2510 if (sc.Check(soa, false, "z", &result)) {
2511 return result.z;
2512 }
2513 }
2514 return JNI_ERR;
2515 }
2516
2517 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2518 jobject initial_element) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002519 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002520 ScopedObjectAccess soa(env);
2521 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2522 JniValueType args[4] =
2523 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2524 if (sc.Check(soa, true, "EzcL", args)) {
2525 JniValueType result;
2526 // Note: assignability tests of initial_element are done in the base implementation.
2527 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2528 if (sc.Check(soa, false, "a", &result)) {
2529 return down_cast<jobjectArray>(result.a);
2530 }
2531 }
2532 return nullptr;
2533 }
2534
2535 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002536 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002537 ScopedObjectAccess soa(env);
2538 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2539 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2540 if (sc.Check(soa, true, "Eaz", args)) {
2541 JniValueType result;
2542 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2543 if (sc.Check(soa, false, "L", &result)) {
2544 return result.L;
2545 }
2546 }
2547 return nullptr;
2548 }
2549
2550 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002551 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Ian Rogers68d8b422014-07-17 11:09:10 -07002552 ScopedObjectAccess soa(env);
2553 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2554 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2555 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2556 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2557 // in ArrayStoreExceptions.
2558 if (sc.Check(soa, true, "EaIL", args)) {
2559 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2560 JniValueType result;
2561 result.V = nullptr;
2562 sc.Check(soa, false, "V", &result);
2563 }
2564 }
2565
2566 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2567 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2568 Primitive::kPrimBoolean));
2569 }
2570
2571 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2572 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2573 Primitive::kPrimByte));
2574 }
2575
2576 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2577 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2578 Primitive::kPrimChar));
2579 }
2580
2581 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2582 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2583 Primitive::kPrimShort));
2584 }
2585
2586 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2587 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2588 }
2589
2590 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2591 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2592 Primitive::kPrimLong));
2593 }
2594
2595 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2596 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2597 Primitive::kPrimFloat));
2598 }
2599
2600 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2601 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2602 Primitive::kPrimDouble));
2603 }
2604
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002605// NOLINT added to avoid wrong warning/fix from clang-tidy.
Ian Rogers68d8b422014-07-17 11:09:10 -07002606#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002607 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2608 return reinterpret_cast<ctype*>( /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002609 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2610 } \
2611 \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002612 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002613 jint mode) { \
2614 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2615 } \
2616 \
2617 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002618 ctype* buf) { /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002619 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2620 } \
2621 \
2622 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2623 const ctype* buf) { \
2624 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2625 }
2626
2627 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2628 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2629 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2630 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2631 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2632 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2633 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2634 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2635#undef PRIMITIVE_ARRAY_FUNCTIONS
2636
2637 static jint MonitorEnter(JNIEnv* env, jobject obj) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002638 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002639 ScopedObjectAccess soa(env);
2640 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2641 JniValueType args[2] = {{.E = env}, {.L = obj}};
2642 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002643 if (obj != nullptr) {
2644 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2645 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002646 JniValueType result;
2647 result.i = baseEnv(env)->MonitorEnter(env, obj);
2648 if (sc.Check(soa, false, "i", &result)) {
2649 return result.i;
2650 }
2651 }
2652 return JNI_ERR;
2653 }
2654
2655 static jint MonitorExit(JNIEnv* env, jobject obj) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002656 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002657 ScopedObjectAccess soa(env);
2658 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2659 JniValueType args[2] = {{.E = env}, {.L = obj}};
2660 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002661 if (obj != nullptr) {
2662 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2663 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002664 JniValueType result;
2665 result.i = baseEnv(env)->MonitorExit(env, obj);
2666 if (sc.Check(soa, false, "i", &result)) {
2667 return result.i;
2668 }
2669 }
2670 return JNI_ERR;
2671 }
2672
2673 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002674 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002675 ScopedObjectAccess soa(env);
2676 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2677 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2678 if (sc.Check(soa, true, "Eap", args)) {
2679 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002680 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2681 if (ptr != nullptr && soa.ForceCopy()) {
2682 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002683 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002684 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002685 if (sc.Check(soa, false, "p", &result)) {
2686 return const_cast<void*>(result.p);
2687 }
2688 }
2689 return nullptr;
2690 }
2691
2692 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002693 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Ian Rogers68d8b422014-07-17 11:09:10 -07002694 ScopedObjectAccess soa(env);
2695 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2696 sc.CheckNonNull(carray);
2697 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2698 if (sc.Check(soa, true, "Eapr", args)) {
2699 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002700 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002701 }
2702 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2703 JniValueType result;
2704 result.V = nullptr;
2705 sc.Check(soa, false, "V", &result);
2706 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002707 }
2708
2709 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002710 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002711 ScopedObjectAccess soa(env);
2712 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2713 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2714 if (sc.Check(soa, true, "EpJ", args)) {
2715 JniValueType result;
2716 // Note: the validity of address and capacity are checked in the base implementation.
2717 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2718 if (sc.Check(soa, false, "L", &result)) {
2719 return result.L;
2720 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002721 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002722 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002723 }
2724
2725 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002726 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002727 ScopedObjectAccess soa(env);
2728 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2729 JniValueType args[2] = {{.E = env}, {.L = buf}};
2730 if (sc.Check(soa, true, "EL", args)) {
2731 JniValueType result;
2732 // Note: this is implemented in the base environment by a GetLongField which will sanity
2733 // check the type of buf in GetLongField above.
2734 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2735 if (sc.Check(soa, false, "p", &result)) {
2736 return const_cast<void*>(result.p);
2737 }
2738 }
2739 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002740 }
2741
2742 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002743 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002744 ScopedObjectAccess soa(env);
2745 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2746 JniValueType args[2] = {{.E = env}, {.L = buf}};
2747 if (sc.Check(soa, true, "EL", args)) {
2748 JniValueType result;
2749 // Note: this is implemented in the base environment by a GetIntField which will sanity
2750 // check the type of buf in GetIntField above.
2751 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2752 if (sc.Check(soa, false, "J", &result)) {
2753 return result.J;
2754 }
2755 }
2756 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002757 }
2758
2759 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002760 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
Ian Rogers55256cb2017-12-21 17:07:11 -08002761 return reinterpret_cast<JNIEnvExt*>(env)->GetVm();
Ian Rogers68d8b422014-07-17 11:09:10 -07002762 }
2763
2764 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Ian Rogersac4d45a2018-02-15 11:19:01 -08002765 return reinterpret_cast<JNIEnvExt*>(env)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07002766 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002767
2768 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002769 CHECK_ATTACHED_THREAD(function_name, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002770 ScopedObjectAccess soa(env);
2771 ScopedCheck sc(kFlag_Default, function_name);
2772 JniValueType args[2] = {{.E = env}, {.L = obj}};
2773 if (sc.Check(soa, true, "EL", args)) {
2774 JniValueType result;
2775 switch (kind) {
2776 case kGlobal:
2777 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2778 break;
2779 case kLocal:
2780 result.L = baseEnv(env)->NewLocalRef(env, obj);
2781 break;
2782 case kWeakGlobal:
2783 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2784 break;
2785 default:
2786 LOG(FATAL) << "Unexpected reference kind: " << kind;
2787 }
2788 if (sc.Check(soa, false, "L", &result)) {
2789 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002790 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002791 return result.L;
2792 }
2793 }
2794 return nullptr;
2795 }
2796
2797 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002798 CHECK_ATTACHED_THREAD_VOID(function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07002799 ScopedObjectAccess soa(env);
2800 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2801 JniValueType args[2] = {{.E = env}, {.L = obj}};
2802 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002803 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002804 JniValueType result;
2805 switch (kind) {
2806 case kGlobal:
2807 baseEnv(env)->DeleteGlobalRef(env, obj);
2808 break;
2809 case kLocal:
2810 baseEnv(env)->DeleteLocalRef(env, obj);
2811 break;
2812 case kWeakGlobal:
2813 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2814 break;
2815 default:
2816 LOG(FATAL) << "Unexpected reference kind: " << kind;
2817 }
2818 result.V = nullptr;
2819 sc.Check(soa, false, "V", &result);
2820 }
2821 }
2822
2823 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2824 const char* name, const char* sig, bool is_static) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002825 CHECK_ATTACHED_THREAD(function_name, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002826 ScopedObjectAccess soa(env);
2827 ScopedCheck sc(kFlag_Default, function_name);
2828 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2829 if (sc.Check(soa, true, "Ecuu", args)) {
2830 JniValueType result;
2831 if (is_static) {
2832 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2833 } else {
2834 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2835 }
2836 if (sc.Check(soa, false, "m", &result)) {
2837 return result.m;
2838 }
2839 }
2840 return nullptr;
2841 }
2842
2843 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2844 const char* name, const char* sig, bool is_static) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002845 CHECK_ATTACHED_THREAD(function_name, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002846 ScopedObjectAccess soa(env);
2847 ScopedCheck sc(kFlag_Default, function_name);
2848 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2849 if (sc.Check(soa, true, "Ecuu", args)) {
2850 JniValueType result;
2851 if (is_static) {
2852 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2853 } else {
2854 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2855 }
2856 if (sc.Check(soa, false, "f", &result)) {
2857 return result.f;
2858 }
2859 }
2860 return nullptr;
2861 }
2862
2863 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2864 bool is_static, Primitive::Type type) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002865 CHECK_ATTACHED_THREAD(function_name, JniValueType());
Ian Rogers68d8b422014-07-17 11:09:10 -07002866 ScopedObjectAccess soa(env);
2867 ScopedCheck sc(kFlag_Default, function_name);
2868 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2869 JniValueType result;
2870 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2871 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2872 const char* result_check = nullptr;
2873 switch (type) {
2874 case Primitive::kPrimNot:
2875 if (is_static) {
2876 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2877 } else {
2878 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2879 }
2880 result_check = "L";
2881 break;
2882 case Primitive::kPrimBoolean:
2883 if (is_static) {
2884 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2885 } else {
2886 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2887 }
2888 result_check = "Z";
2889 break;
2890 case Primitive::kPrimByte:
2891 if (is_static) {
2892 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2893 } else {
2894 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2895 }
2896 result_check = "B";
2897 break;
2898 case Primitive::kPrimChar:
2899 if (is_static) {
2900 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2901 } else {
2902 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2903 }
2904 result_check = "C";
2905 break;
2906 case Primitive::kPrimShort:
2907 if (is_static) {
2908 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2909 } else {
2910 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2911 }
2912 result_check = "S";
2913 break;
2914 case Primitive::kPrimInt:
2915 if (is_static) {
2916 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2917 } else {
2918 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2919 }
2920 result_check = "I";
2921 break;
2922 case Primitive::kPrimLong:
2923 if (is_static) {
2924 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2925 } else {
2926 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2927 }
2928 result_check = "J";
2929 break;
2930 case Primitive::kPrimFloat:
2931 if (is_static) {
2932 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2933 } else {
2934 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2935 }
2936 result_check = "F";
2937 break;
2938 case Primitive::kPrimDouble:
2939 if (is_static) {
2940 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2941 } else {
2942 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2943 }
2944 result_check = "D";
2945 break;
2946 case Primitive::kPrimVoid:
2947 LOG(FATAL) << "Unexpected type: " << type;
Elliott Hughesc1896c92018-11-29 11:33:18 -08002948 UNREACHABLE();
Ian Rogers68d8b422014-07-17 11:09:10 -07002949 }
2950 if (sc.Check(soa, false, result_check, &result)) {
2951 return result;
2952 }
2953 }
2954 result.J = 0;
2955 return result;
2956 }
2957
2958 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2959 bool is_static, Primitive::Type type, JniValueType value) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07002960 CHECK_ATTACHED_THREAD_VOID(function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07002961 ScopedObjectAccess soa(env);
2962 ScopedCheck sc(kFlag_Default, function_name);
2963 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2964 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2965 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2966 if (sc.Check(soa, true, sig, args) &&
2967 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2968 switch (type) {
2969 case Primitive::kPrimNot:
2970 if (is_static) {
2971 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2972 } else {
2973 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2974 }
2975 break;
2976 case Primitive::kPrimBoolean:
2977 if (is_static) {
2978 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2979 } else {
2980 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2981 }
2982 break;
2983 case Primitive::kPrimByte:
2984 if (is_static) {
2985 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2986 } else {
2987 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2988 }
2989 break;
2990 case Primitive::kPrimChar:
2991 if (is_static) {
2992 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2993 } else {
2994 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2995 }
2996 break;
2997 case Primitive::kPrimShort:
2998 if (is_static) {
2999 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
3000 } else {
3001 baseEnv(env)->SetShortField(env, obj, fid, value.S);
3002 }
3003 break;
3004 case Primitive::kPrimInt:
3005 if (is_static) {
3006 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
3007 } else {
3008 baseEnv(env)->SetIntField(env, obj, fid, value.I);
3009 }
3010 break;
3011 case Primitive::kPrimLong:
3012 if (is_static) {
3013 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
3014 } else {
3015 baseEnv(env)->SetLongField(env, obj, fid, value.J);
3016 }
3017 break;
3018 case Primitive::kPrimFloat:
3019 if (is_static) {
3020 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
3021 } else {
3022 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
3023 }
3024 break;
3025 case Primitive::kPrimDouble:
3026 if (is_static) {
3027 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
3028 } else {
3029 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
3030 }
3031 break;
3032 case Primitive::kPrimVoid:
3033 LOG(FATAL) << "Unexpected type: " << type;
Elliott Hughesc1896c92018-11-29 11:33:18 -08003034 UNREACHABLE();
Ian Rogers68d8b422014-07-17 11:09:10 -07003035 }
3036 JniValueType result;
3037 result.V = nullptr;
3038 sc.Check(soa, false, "V", &result);
3039 }
3040 }
3041
3042 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
Alex Light48ffe062015-08-19 15:23:23 -07003043 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07003044 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003045 bool checked;
3046 switch (invoke) {
3047 case kVirtual: {
3048 DCHECK(c == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07003049 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
3050 checked = sc.Check(soa, true, "ELm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07003051 break;
3052 }
3053 case kDirect: {
Alex Light48ffe062015-08-19 15:23:23 -07003054 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
3055 checked = sc.Check(soa, true, "ELcm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07003056 break;
3057 }
3058 case kStatic: {
3059 DCHECK(obj == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07003060 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
3061 checked = sc.Check(soa, true, "Ecm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07003062 break;
3063 }
3064 default:
3065 LOG(FATAL) << "Unexpected invoke: " << invoke;
3066 checked = false;
3067 break;
3068 }
3069 return checked;
3070 }
3071
3072 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
Elliott Hughes22352f32018-06-15 17:33:58 -07003073 jmethodID mid, const jvalue* vargs, Primitive::Type type,
Ian Rogers68d8b422014-07-17 11:09:10 -07003074 InvokeType invoke) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07003075 CHECK_ATTACHED_THREAD(function_name, JniValueType());
Ian Rogers68d8b422014-07-17 11:09:10 -07003076 ScopedObjectAccess soa(env);
3077 ScopedCheck sc(kFlag_Default, function_name);
3078 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003079 VarArgs rest(mid, vargs);
3080 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003081 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3082 const char* result_check;
3083 switch (type) {
3084 case Primitive::kPrimNot:
3085 result_check = "L";
3086 switch (invoke) {
3087 case kVirtual:
3088 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
3089 break;
3090 case kDirect:
3091 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
3092 break;
3093 case kStatic:
3094 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
3095 break;
3096 default:
3097 break;
3098 }
3099 break;
3100 case Primitive::kPrimBoolean:
3101 result_check = "Z";
3102 switch (invoke) {
3103 case kVirtual:
3104 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
3105 break;
3106 case kDirect:
3107 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
3108 break;
3109 case kStatic:
3110 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
3111 break;
3112 default:
3113 break;
3114 }
3115 break;
3116 case Primitive::kPrimByte:
3117 result_check = "B";
3118 switch (invoke) {
3119 case kVirtual:
3120 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
3121 break;
3122 case kDirect:
3123 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
3124 break;
3125 case kStatic:
3126 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
3127 break;
3128 default:
3129 break;
3130 }
3131 break;
3132 case Primitive::kPrimChar:
3133 result_check = "C";
3134 switch (invoke) {
3135 case kVirtual:
3136 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
3137 break;
3138 case kDirect:
3139 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
3140 break;
3141 case kStatic:
3142 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
3143 break;
3144 default:
3145 break;
3146 }
3147 break;
3148 case Primitive::kPrimShort:
3149 result_check = "S";
3150 switch (invoke) {
3151 case kVirtual:
3152 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
3153 break;
3154 case kDirect:
3155 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
3156 break;
3157 case kStatic:
3158 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
3159 break;
3160 default:
3161 break;
3162 }
3163 break;
3164 case Primitive::kPrimInt:
3165 result_check = "I";
3166 switch (invoke) {
3167 case kVirtual:
3168 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
3169 break;
3170 case kDirect:
3171 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
3172 break;
3173 case kStatic:
3174 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
3175 break;
3176 default:
3177 break;
3178 }
3179 break;
3180 case Primitive::kPrimLong:
3181 result_check = "J";
3182 switch (invoke) {
3183 case kVirtual:
3184 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
3185 break;
3186 case kDirect:
3187 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3188 break;
3189 case kStatic:
3190 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3191 break;
3192 default:
3193 break;
3194 }
3195 break;
3196 case Primitive::kPrimFloat:
3197 result_check = "F";
3198 switch (invoke) {
3199 case kVirtual:
3200 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3201 break;
3202 case kDirect:
3203 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3204 break;
3205 case kStatic:
3206 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3207 break;
3208 default:
3209 break;
3210 }
3211 break;
3212 case Primitive::kPrimDouble:
3213 result_check = "D";
3214 switch (invoke) {
3215 case kVirtual:
3216 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3217 break;
3218 case kDirect:
3219 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3220 break;
3221 case kStatic:
3222 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3223 break;
3224 default:
3225 break;
3226 }
3227 break;
3228 case Primitive::kPrimVoid:
3229 result_check = "V";
3230 result.V = nullptr;
3231 switch (invoke) {
3232 case kVirtual:
3233 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3234 break;
3235 case kDirect:
3236 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3237 break;
3238 case kStatic:
3239 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3240 break;
3241 default:
3242 LOG(FATAL) << "Unexpected invoke: " << invoke;
3243 }
3244 break;
3245 default:
3246 LOG(FATAL) << "Unexpected return type: " << type;
3247 result_check = nullptr;
3248 }
3249 if (sc.Check(soa, false, result_check, &result)) {
3250 return result;
3251 }
3252 }
3253 result.J = 0;
3254 return result;
3255 }
3256
3257 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3258 jmethodID mid, va_list vargs, Primitive::Type type,
3259 InvokeType invoke) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07003260 CHECK_ATTACHED_THREAD(function_name, JniValueType());
Ian Rogers68d8b422014-07-17 11:09:10 -07003261 ScopedObjectAccess soa(env);
3262 ScopedCheck sc(kFlag_Default, function_name);
3263 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003264 VarArgs rest(mid, vargs);
3265 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003266 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3267 const char* result_check;
3268 switch (type) {
3269 case Primitive::kPrimNot:
3270 result_check = "L";
3271 switch (invoke) {
3272 case kVirtual:
3273 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3274 break;
3275 case kDirect:
3276 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3277 break;
3278 case kStatic:
3279 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3280 break;
3281 default:
3282 LOG(FATAL) << "Unexpected invoke: " << invoke;
3283 }
3284 break;
3285 case Primitive::kPrimBoolean:
3286 result_check = "Z";
3287 switch (invoke) {
3288 case kVirtual:
3289 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3290 break;
3291 case kDirect:
3292 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3293 break;
3294 case kStatic:
3295 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3296 break;
3297 default:
3298 LOG(FATAL) << "Unexpected invoke: " << invoke;
3299 }
3300 break;
3301 case Primitive::kPrimByte:
3302 result_check = "B";
3303 switch (invoke) {
3304 case kVirtual:
3305 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3306 break;
3307 case kDirect:
3308 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3309 break;
3310 case kStatic:
3311 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3312 break;
3313 default:
3314 LOG(FATAL) << "Unexpected invoke: " << invoke;
3315 }
3316 break;
3317 case Primitive::kPrimChar:
3318 result_check = "C";
3319 switch (invoke) {
3320 case kVirtual:
3321 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3322 break;
3323 case kDirect:
3324 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3325 break;
3326 case kStatic:
3327 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3328 break;
3329 default:
3330 LOG(FATAL) << "Unexpected invoke: " << invoke;
3331 }
3332 break;
3333 case Primitive::kPrimShort:
3334 result_check = "S";
3335 switch (invoke) {
3336 case kVirtual:
3337 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3338 break;
3339 case kDirect:
3340 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3341 break;
3342 case kStatic:
3343 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3344 break;
3345 default:
3346 LOG(FATAL) << "Unexpected invoke: " << invoke;
3347 }
3348 break;
3349 case Primitive::kPrimInt:
3350 result_check = "I";
3351 switch (invoke) {
3352 case kVirtual:
3353 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3354 break;
3355 case kDirect:
3356 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3357 break;
3358 case kStatic:
3359 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3360 break;
3361 default:
3362 LOG(FATAL) << "Unexpected invoke: " << invoke;
3363 }
3364 break;
3365 case Primitive::kPrimLong:
3366 result_check = "J";
3367 switch (invoke) {
3368 case kVirtual:
3369 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3370 break;
3371 case kDirect:
3372 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3373 break;
3374 case kStatic:
3375 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3376 break;
3377 default:
3378 LOG(FATAL) << "Unexpected invoke: " << invoke;
3379 }
3380 break;
3381 case Primitive::kPrimFloat:
3382 result_check = "F";
3383 switch (invoke) {
3384 case kVirtual:
3385 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3386 break;
3387 case kDirect:
3388 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3389 break;
3390 case kStatic:
3391 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3392 break;
3393 default:
3394 LOG(FATAL) << "Unexpected invoke: " << invoke;
3395 }
3396 break;
3397 case Primitive::kPrimDouble:
3398 result_check = "D";
3399 switch (invoke) {
3400 case kVirtual:
3401 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3402 break;
3403 case kDirect:
3404 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3405 break;
3406 case kStatic:
3407 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3408 break;
3409 default:
3410 LOG(FATAL) << "Unexpected invoke: " << invoke;
3411 }
3412 break;
3413 case Primitive::kPrimVoid:
3414 result_check = "V";
3415 result.V = nullptr;
3416 switch (invoke) {
3417 case kVirtual:
3418 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3419 break;
3420 case kDirect:
3421 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3422 break;
3423 case kStatic:
3424 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3425 break;
3426 default:
3427 LOG(FATAL) << "Unexpected invoke: " << invoke;
3428 }
3429 break;
3430 default:
3431 LOG(FATAL) << "Unexpected return type: " << type;
3432 result_check = nullptr;
3433 }
3434 if (sc.Check(soa, false, result_check, &result)) {
3435 return result;
3436 }
3437 }
3438 result.J = 0;
3439 return result;
3440 }
3441
3442 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3443 jboolean* is_copy, bool utf, bool critical) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07003444 CHECK_ATTACHED_THREAD(function_name, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003445 ScopedObjectAccess soa(env);
3446 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3447 ScopedCheck sc(flags, function_name);
3448 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3449 if (sc.Check(soa, true, "Esp", args)) {
3450 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003451 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003452 if (utf) {
3453 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003454 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3455 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003456 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003457 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3458 baseEnv(env)->GetStringChars(env, string, is_copy));
3459 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003460 }
3461 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003462 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003463 if (utf) {
3464 size_t length_in_bytes = strlen(result.u) + 1;
3465 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003466 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003467 } else {
3468 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3469 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003470 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003471 }
3472 if (is_copy != nullptr) {
3473 *is_copy = JNI_TRUE;
3474 }
3475 }
3476 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3477 return utf ? result.u : result.p;
3478 }
3479 }
3480 return nullptr;
3481 }
3482
3483 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3484 const void* chars, bool utf, bool critical) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07003485 CHECK_ATTACHED_THREAD_VOID(function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003486 ScopedObjectAccess soa(env);
3487 int flags = kFlag_ExcepOkay | kFlag_Release;
3488 if (critical) {
3489 flags |= kFlag_CritRelease;
3490 }
3491 ScopedCheck sc(flags, function_name);
3492 sc.CheckNonNull(chars);
3493 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3494 if (force_copy_ok && soa.ForceCopy()) {
3495 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3496 }
3497 if (force_copy_ok) {
3498 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3499 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3500 if (utf) {
3501 CHECK(!critical);
3502 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3503 } else {
3504 if (critical) {
3505 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3506 } else {
3507 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3508 }
3509 }
3510 JniValueType result;
3511 sc.Check(soa, false, "V", &result);
3512 }
3513 }
3514 }
3515
3516 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3517 Primitive::Type type) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07003518 CHECK_ATTACHED_THREAD(function_name, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003519 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003520 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003521 JniValueType args[2] = {{.E = env}, {.z = length}};
3522 if (sc.Check(soa, true, "Ez", args)) {
3523 JniValueType result;
3524 switch (type) {
3525 case Primitive::kPrimBoolean:
3526 result.a = baseEnv(env)->NewBooleanArray(env, length);
3527 break;
3528 case Primitive::kPrimByte:
3529 result.a = baseEnv(env)->NewByteArray(env, length);
3530 break;
3531 case Primitive::kPrimChar:
3532 result.a = baseEnv(env)->NewCharArray(env, length);
3533 break;
3534 case Primitive::kPrimShort:
3535 result.a = baseEnv(env)->NewShortArray(env, length);
3536 break;
3537 case Primitive::kPrimInt:
3538 result.a = baseEnv(env)->NewIntArray(env, length);
3539 break;
3540 case Primitive::kPrimLong:
3541 result.a = baseEnv(env)->NewLongArray(env, length);
3542 break;
3543 case Primitive::kPrimFloat:
3544 result.a = baseEnv(env)->NewFloatArray(env, length);
3545 break;
3546 case Primitive::kPrimDouble:
3547 result.a = baseEnv(env)->NewDoubleArray(env, length);
3548 break;
3549 default:
3550 LOG(FATAL) << "Unexpected primitive type: " << type;
3551 }
3552 if (sc.Check(soa, false, "a", &result)) {
3553 return result.a;
3554 }
3555 }
3556 return nullptr;
3557 }
3558
3559 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3560 JNIEnv* env, jarray array, jboolean* is_copy) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07003561 CHECK_ATTACHED_THREAD(function_name, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003562 ScopedObjectAccess soa(env);
3563 ScopedCheck sc(kFlag_Default, function_name);
3564 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3565 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3566 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003567 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003568 switch (type) {
3569 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003570 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3571 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003572 break;
3573 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003574 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003575 break;
3576 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003577 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003578 break;
3579 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003580 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003581 break;
3582 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003583 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003584 break;
3585 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003586 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003587 break;
3588 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003589 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003590 break;
3591 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003592 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003593 break;
3594 default:
3595 LOG(FATAL) << "Unexpected primitive type: " << type;
3596 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003597 if (ptr != nullptr && soa.ForceCopy()) {
3598 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003599 if (is_copy != nullptr) {
3600 *is_copy = JNI_TRUE;
3601 }
3602 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003603 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003604 if (sc.Check(soa, false, "p", &result)) {
3605 return const_cast<void*>(result.p);
3606 }
3607 }
3608 return nullptr;
3609 }
3610
3611 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3612 JNIEnv* env, jarray array, void* elems, jint mode) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07003613 CHECK_ATTACHED_THREAD_VOID(function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003614 ScopedObjectAccess soa(env);
3615 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3616 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3617 if (soa.ForceCopy()) {
3618 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3619 }
3620 if (!soa.ForceCopy() || elems != nullptr) {
3621 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3622 if (sc.Check(soa, true, "Eapr", args)) {
3623 switch (type) {
3624 case Primitive::kPrimBoolean:
3625 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3626 reinterpret_cast<jboolean*>(elems), mode);
3627 break;
3628 case Primitive::kPrimByte:
3629 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3630 reinterpret_cast<jbyte*>(elems), mode);
3631 break;
3632 case Primitive::kPrimChar:
3633 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3634 reinterpret_cast<jchar*>(elems), mode);
3635 break;
3636 case Primitive::kPrimShort:
3637 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3638 reinterpret_cast<jshort*>(elems), mode);
3639 break;
3640 case Primitive::kPrimInt:
3641 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3642 reinterpret_cast<jint*>(elems), mode);
3643 break;
3644 case Primitive::kPrimLong:
3645 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3646 reinterpret_cast<jlong*>(elems), mode);
3647 break;
3648 case Primitive::kPrimFloat:
3649 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3650 reinterpret_cast<jfloat*>(elems), mode);
3651 break;
3652 case Primitive::kPrimDouble:
3653 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3654 reinterpret_cast<jdouble*>(elems), mode);
3655 break;
3656 default:
3657 LOG(FATAL) << "Unexpected primitive type: " << type;
3658 }
3659 JniValueType result;
3660 result.V = nullptr;
3661 sc.Check(soa, false, "V", &result);
3662 }
3663 }
3664 }
3665 }
3666
3667 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3668 jarray array, jsize start, jsize len, void* buf) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07003669 CHECK_ATTACHED_THREAD_VOID(function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003670 ScopedObjectAccess soa(env);
3671 ScopedCheck sc(kFlag_Default, function_name);
3672 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3673 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3674 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3675 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3676 switch (type) {
3677 case Primitive::kPrimBoolean:
3678 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3679 reinterpret_cast<jboolean*>(buf));
3680 break;
3681 case Primitive::kPrimByte:
3682 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3683 reinterpret_cast<jbyte*>(buf));
3684 break;
3685 case Primitive::kPrimChar:
3686 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3687 reinterpret_cast<jchar*>(buf));
3688 break;
3689 case Primitive::kPrimShort:
3690 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3691 reinterpret_cast<jshort*>(buf));
3692 break;
3693 case Primitive::kPrimInt:
3694 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3695 reinterpret_cast<jint*>(buf));
3696 break;
3697 case Primitive::kPrimLong:
3698 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3699 reinterpret_cast<jlong*>(buf));
3700 break;
3701 case Primitive::kPrimFloat:
3702 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3703 reinterpret_cast<jfloat*>(buf));
3704 break;
3705 case Primitive::kPrimDouble:
3706 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3707 reinterpret_cast<jdouble*>(buf));
3708 break;
3709 default:
3710 LOG(FATAL) << "Unexpected primitive type: " << type;
3711 }
3712 JniValueType result;
3713 result.V = nullptr;
3714 sc.Check(soa, false, "V", &result);
3715 }
3716 }
3717
3718 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3719 jarray array, jsize start, jsize len, const void* buf) {
Andreas Gampefb8f75c2018-04-17 11:08:23 -07003720 CHECK_ATTACHED_THREAD_VOID(function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003721 ScopedObjectAccess soa(env);
3722 ScopedCheck sc(kFlag_Default, function_name);
3723 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3724 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3725 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3726 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3727 switch (type) {
3728 case Primitive::kPrimBoolean:
3729 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3730 reinterpret_cast<const jboolean*>(buf));
3731 break;
3732 case Primitive::kPrimByte:
3733 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3734 reinterpret_cast<const jbyte*>(buf));
3735 break;
3736 case Primitive::kPrimChar:
3737 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3738 reinterpret_cast<const jchar*>(buf));
3739 break;
3740 case Primitive::kPrimShort:
3741 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3742 reinterpret_cast<const jshort*>(buf));
3743 break;
3744 case Primitive::kPrimInt:
3745 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3746 reinterpret_cast<const jint*>(buf));
3747 break;
3748 case Primitive::kPrimLong:
3749 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3750 reinterpret_cast<const jlong*>(buf));
3751 break;
3752 case Primitive::kPrimFloat:
3753 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3754 reinterpret_cast<const jfloat*>(buf));
3755 break;
3756 case Primitive::kPrimDouble:
3757 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3758 reinterpret_cast<const jdouble*>(buf));
3759 break;
3760 default:
3761 LOG(FATAL) << "Unexpected primitive type: " << type;
3762 }
3763 JniValueType result;
3764 result.V = nullptr;
3765 sc.Check(soa, false, "V", &result);
3766 }
3767 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003768};
3769
3770const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003771 nullptr, // reserved0.
3772 nullptr, // reserved1.
3773 nullptr, // reserved2.
3774 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003775 CheckJNI::GetVersion,
3776 CheckJNI::DefineClass,
3777 CheckJNI::FindClass,
3778 CheckJNI::FromReflectedMethod,
3779 CheckJNI::FromReflectedField,
3780 CheckJNI::ToReflectedMethod,
3781 CheckJNI::GetSuperclass,
3782 CheckJNI::IsAssignableFrom,
3783 CheckJNI::ToReflectedField,
3784 CheckJNI::Throw,
3785 CheckJNI::ThrowNew,
3786 CheckJNI::ExceptionOccurred,
3787 CheckJNI::ExceptionDescribe,
3788 CheckJNI::ExceptionClear,
3789 CheckJNI::FatalError,
3790 CheckJNI::PushLocalFrame,
3791 CheckJNI::PopLocalFrame,
3792 CheckJNI::NewGlobalRef,
3793 CheckJNI::DeleteGlobalRef,
3794 CheckJNI::DeleteLocalRef,
3795 CheckJNI::IsSameObject,
3796 CheckJNI::NewLocalRef,
3797 CheckJNI::EnsureLocalCapacity,
3798 CheckJNI::AllocObject,
3799 CheckJNI::NewObject,
3800 CheckJNI::NewObjectV,
3801 CheckJNI::NewObjectA,
3802 CheckJNI::GetObjectClass,
3803 CheckJNI::IsInstanceOf,
3804 CheckJNI::GetMethodID,
3805 CheckJNI::CallObjectMethod,
3806 CheckJNI::CallObjectMethodV,
3807 CheckJNI::CallObjectMethodA,
3808 CheckJNI::CallBooleanMethod,
3809 CheckJNI::CallBooleanMethodV,
3810 CheckJNI::CallBooleanMethodA,
3811 CheckJNI::CallByteMethod,
3812 CheckJNI::CallByteMethodV,
3813 CheckJNI::CallByteMethodA,
3814 CheckJNI::CallCharMethod,
3815 CheckJNI::CallCharMethodV,
3816 CheckJNI::CallCharMethodA,
3817 CheckJNI::CallShortMethod,
3818 CheckJNI::CallShortMethodV,
3819 CheckJNI::CallShortMethodA,
3820 CheckJNI::CallIntMethod,
3821 CheckJNI::CallIntMethodV,
3822 CheckJNI::CallIntMethodA,
3823 CheckJNI::CallLongMethod,
3824 CheckJNI::CallLongMethodV,
3825 CheckJNI::CallLongMethodA,
3826 CheckJNI::CallFloatMethod,
3827 CheckJNI::CallFloatMethodV,
3828 CheckJNI::CallFloatMethodA,
3829 CheckJNI::CallDoubleMethod,
3830 CheckJNI::CallDoubleMethodV,
3831 CheckJNI::CallDoubleMethodA,
3832 CheckJNI::CallVoidMethod,
3833 CheckJNI::CallVoidMethodV,
3834 CheckJNI::CallVoidMethodA,
3835 CheckJNI::CallNonvirtualObjectMethod,
3836 CheckJNI::CallNonvirtualObjectMethodV,
3837 CheckJNI::CallNonvirtualObjectMethodA,
3838 CheckJNI::CallNonvirtualBooleanMethod,
3839 CheckJNI::CallNonvirtualBooleanMethodV,
3840 CheckJNI::CallNonvirtualBooleanMethodA,
3841 CheckJNI::CallNonvirtualByteMethod,
3842 CheckJNI::CallNonvirtualByteMethodV,
3843 CheckJNI::CallNonvirtualByteMethodA,
3844 CheckJNI::CallNonvirtualCharMethod,
3845 CheckJNI::CallNonvirtualCharMethodV,
3846 CheckJNI::CallNonvirtualCharMethodA,
3847 CheckJNI::CallNonvirtualShortMethod,
3848 CheckJNI::CallNonvirtualShortMethodV,
3849 CheckJNI::CallNonvirtualShortMethodA,
3850 CheckJNI::CallNonvirtualIntMethod,
3851 CheckJNI::CallNonvirtualIntMethodV,
3852 CheckJNI::CallNonvirtualIntMethodA,
3853 CheckJNI::CallNonvirtualLongMethod,
3854 CheckJNI::CallNonvirtualLongMethodV,
3855 CheckJNI::CallNonvirtualLongMethodA,
3856 CheckJNI::CallNonvirtualFloatMethod,
3857 CheckJNI::CallNonvirtualFloatMethodV,
3858 CheckJNI::CallNonvirtualFloatMethodA,
3859 CheckJNI::CallNonvirtualDoubleMethod,
3860 CheckJNI::CallNonvirtualDoubleMethodV,
3861 CheckJNI::CallNonvirtualDoubleMethodA,
3862 CheckJNI::CallNonvirtualVoidMethod,
3863 CheckJNI::CallNonvirtualVoidMethodV,
3864 CheckJNI::CallNonvirtualVoidMethodA,
3865 CheckJNI::GetFieldID,
3866 CheckJNI::GetObjectField,
3867 CheckJNI::GetBooleanField,
3868 CheckJNI::GetByteField,
3869 CheckJNI::GetCharField,
3870 CheckJNI::GetShortField,
3871 CheckJNI::GetIntField,
3872 CheckJNI::GetLongField,
3873 CheckJNI::GetFloatField,
3874 CheckJNI::GetDoubleField,
3875 CheckJNI::SetObjectField,
3876 CheckJNI::SetBooleanField,
3877 CheckJNI::SetByteField,
3878 CheckJNI::SetCharField,
3879 CheckJNI::SetShortField,
3880 CheckJNI::SetIntField,
3881 CheckJNI::SetLongField,
3882 CheckJNI::SetFloatField,
3883 CheckJNI::SetDoubleField,
3884 CheckJNI::GetStaticMethodID,
3885 CheckJNI::CallStaticObjectMethod,
3886 CheckJNI::CallStaticObjectMethodV,
3887 CheckJNI::CallStaticObjectMethodA,
3888 CheckJNI::CallStaticBooleanMethod,
3889 CheckJNI::CallStaticBooleanMethodV,
3890 CheckJNI::CallStaticBooleanMethodA,
3891 CheckJNI::CallStaticByteMethod,
3892 CheckJNI::CallStaticByteMethodV,
3893 CheckJNI::CallStaticByteMethodA,
3894 CheckJNI::CallStaticCharMethod,
3895 CheckJNI::CallStaticCharMethodV,
3896 CheckJNI::CallStaticCharMethodA,
3897 CheckJNI::CallStaticShortMethod,
3898 CheckJNI::CallStaticShortMethodV,
3899 CheckJNI::CallStaticShortMethodA,
3900 CheckJNI::CallStaticIntMethod,
3901 CheckJNI::CallStaticIntMethodV,
3902 CheckJNI::CallStaticIntMethodA,
3903 CheckJNI::CallStaticLongMethod,
3904 CheckJNI::CallStaticLongMethodV,
3905 CheckJNI::CallStaticLongMethodA,
3906 CheckJNI::CallStaticFloatMethod,
3907 CheckJNI::CallStaticFloatMethodV,
3908 CheckJNI::CallStaticFloatMethodA,
3909 CheckJNI::CallStaticDoubleMethod,
3910 CheckJNI::CallStaticDoubleMethodV,
3911 CheckJNI::CallStaticDoubleMethodA,
3912 CheckJNI::CallStaticVoidMethod,
3913 CheckJNI::CallStaticVoidMethodV,
3914 CheckJNI::CallStaticVoidMethodA,
3915 CheckJNI::GetStaticFieldID,
3916 CheckJNI::GetStaticObjectField,
3917 CheckJNI::GetStaticBooleanField,
3918 CheckJNI::GetStaticByteField,
3919 CheckJNI::GetStaticCharField,
3920 CheckJNI::GetStaticShortField,
3921 CheckJNI::GetStaticIntField,
3922 CheckJNI::GetStaticLongField,
3923 CheckJNI::GetStaticFloatField,
3924 CheckJNI::GetStaticDoubleField,
3925 CheckJNI::SetStaticObjectField,
3926 CheckJNI::SetStaticBooleanField,
3927 CheckJNI::SetStaticByteField,
3928 CheckJNI::SetStaticCharField,
3929 CheckJNI::SetStaticShortField,
3930 CheckJNI::SetStaticIntField,
3931 CheckJNI::SetStaticLongField,
3932 CheckJNI::SetStaticFloatField,
3933 CheckJNI::SetStaticDoubleField,
3934 CheckJNI::NewString,
3935 CheckJNI::GetStringLength,
3936 CheckJNI::GetStringChars,
3937 CheckJNI::ReleaseStringChars,
3938 CheckJNI::NewStringUTF,
3939 CheckJNI::GetStringUTFLength,
3940 CheckJNI::GetStringUTFChars,
3941 CheckJNI::ReleaseStringUTFChars,
3942 CheckJNI::GetArrayLength,
3943 CheckJNI::NewObjectArray,
3944 CheckJNI::GetObjectArrayElement,
3945 CheckJNI::SetObjectArrayElement,
3946 CheckJNI::NewBooleanArray,
3947 CheckJNI::NewByteArray,
3948 CheckJNI::NewCharArray,
3949 CheckJNI::NewShortArray,
3950 CheckJNI::NewIntArray,
3951 CheckJNI::NewLongArray,
3952 CheckJNI::NewFloatArray,
3953 CheckJNI::NewDoubleArray,
3954 CheckJNI::GetBooleanArrayElements,
3955 CheckJNI::GetByteArrayElements,
3956 CheckJNI::GetCharArrayElements,
3957 CheckJNI::GetShortArrayElements,
3958 CheckJNI::GetIntArrayElements,
3959 CheckJNI::GetLongArrayElements,
3960 CheckJNI::GetFloatArrayElements,
3961 CheckJNI::GetDoubleArrayElements,
3962 CheckJNI::ReleaseBooleanArrayElements,
3963 CheckJNI::ReleaseByteArrayElements,
3964 CheckJNI::ReleaseCharArrayElements,
3965 CheckJNI::ReleaseShortArrayElements,
3966 CheckJNI::ReleaseIntArrayElements,
3967 CheckJNI::ReleaseLongArrayElements,
3968 CheckJNI::ReleaseFloatArrayElements,
3969 CheckJNI::ReleaseDoubleArrayElements,
3970 CheckJNI::GetBooleanArrayRegion,
3971 CheckJNI::GetByteArrayRegion,
3972 CheckJNI::GetCharArrayRegion,
3973 CheckJNI::GetShortArrayRegion,
3974 CheckJNI::GetIntArrayRegion,
3975 CheckJNI::GetLongArrayRegion,
3976 CheckJNI::GetFloatArrayRegion,
3977 CheckJNI::GetDoubleArrayRegion,
3978 CheckJNI::SetBooleanArrayRegion,
3979 CheckJNI::SetByteArrayRegion,
3980 CheckJNI::SetCharArrayRegion,
3981 CheckJNI::SetShortArrayRegion,
3982 CheckJNI::SetIntArrayRegion,
3983 CheckJNI::SetLongArrayRegion,
3984 CheckJNI::SetFloatArrayRegion,
3985 CheckJNI::SetDoubleArrayRegion,
3986 CheckJNI::RegisterNatives,
3987 CheckJNI::UnregisterNatives,
3988 CheckJNI::MonitorEnter,
3989 CheckJNI::MonitorExit,
3990 CheckJNI::GetJavaVM,
3991 CheckJNI::GetStringRegion,
3992 CheckJNI::GetStringUTFRegion,
3993 CheckJNI::GetPrimitiveArrayCritical,
3994 CheckJNI::ReleasePrimitiveArrayCritical,
3995 CheckJNI::GetStringCritical,
3996 CheckJNI::ReleaseStringCritical,
3997 CheckJNI::NewWeakGlobalRef,
3998 CheckJNI::DeleteWeakGlobalRef,
3999 CheckJNI::ExceptionCheck,
4000 CheckJNI::NewDirectByteBuffer,
4001 CheckJNI::GetDirectBufferAddress,
4002 CheckJNI::GetDirectBufferCapacity,
4003 CheckJNI::GetObjectRefType,
4004};
4005
Elliott Hughesa2501992011-08-26 19:39:54 -07004006class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08004007 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07004008 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07004009 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
4010 JniValueType args[1] = {{.v = vm}};
4011 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
4012 JniValueType result;
4013 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08004014 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
4015 // which will delete the JavaVMExt.
4016 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07004017 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07004018 }
4019
4020 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07004021 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4022 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
4023 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
4024 JniValueType result;
4025 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
4026 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4027 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07004028 }
4029
4030 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07004031 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4032 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
4033 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
4034 JniValueType result;
4035 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
4036 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4037 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07004038 }
4039
4040 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07004041 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4042 JniValueType args[1] = {{.v = vm}};
4043 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
4044 JniValueType result;
4045 result.i = BaseVm(vm)->DetachCurrentThread(vm);
4046 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4047 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07004048 }
4049
Ian Rogers68d8b422014-07-17 11:09:10 -07004050 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
4051 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4052 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
4053 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
4054 JniValueType result;
4055 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
4056 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4057 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07004058 }
4059
4060 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07004061 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
4062 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07004063 }
4064};
4065
4066const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08004067 nullptr, // reserved0
4068 nullptr, // reserved1
4069 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07004070 CheckJII::DestroyJavaVM,
4071 CheckJII::AttachCurrentThread,
4072 CheckJII::DetachCurrentThread,
4073 CheckJII::GetEnv,
4074 CheckJII::AttachCurrentThreadAsDaemon
4075};
4076
Ian Rogersac4d45a2018-02-15 11:19:01 -08004077} // anonymous namespace
4078
4079const JNINativeInterface* GetCheckJniNativeInterface() {
4080 return &gCheckNativeInterface;
4081}
4082
Elliott Hughesa2501992011-08-26 19:39:54 -07004083const JNIInvokeInterface* GetCheckJniInvokeInterface() {
4084 return &gCheckInvokeInterface;
4085}
4086
4087} // namespace art