blob: c4350914414ea735dce5802017b229b8f6a68bb2 [file] [log] [blame]
Elliott Hughesa2501992011-08-26 19:39:54 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Gampe277ccbd2014-11-03 21:36:10 -080017#include "check_jni.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070018
19#include <sys/mman.h>
20#include <zlib.h>
21
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070022#include <iomanip>
23
Andreas Gampe57943812017-12-06 21:39:13 -080024#include <android-base/logging.h>
25#include <android-base/stringprintf.h>
Andreas Gampe46ee31b2016-12-14 10:11:49 -080026
Mathieu Chartierc7853442015-03-27 14:35:38 -070027#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070028#include "art_method-inl.h"
Andreas Gampe57943812017-12-06 21:39:13 -080029#include "base/macros.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070030#include "base/to_str.h"
Ian Rogers55256cb2017-12-21 17:07:11 -080031#include "base/time_utils.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080032#include "class_linker-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070033#include "class_linker.h"
David Sehrb2ec9f52018-02-21 13:20:31 -080034#include "dex/descriptors_names.h"
David Sehr9e734c72018-01-04 17:56:19 -080035#include "dex/dex_file-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070036#include "gc/space/space.h"
Vladimir Marko3e61dc02018-05-04 10:06:38 +010037#include "jni/java_vm_ext.h"
38#include "jni/jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080039#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080040#include "mirror/object-inl.h"
41#include "mirror/object_array-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070042#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080043#include "mirror/throwable.h"
Jeff Hao58df3272013-04-22 15:28:53 -070044#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070045#include "scoped_thread_state_change-inl.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070046#include "thread.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070047#include "well_known_classes.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070048
49namespace art {
Ian Rogersac4d45a2018-02-15 11:19:01 -080050namespace {
Elliott Hughesa2501992011-08-26 19:39:54 -070051
Andreas Gampe46ee31b2016-12-14 10:11:49 -080052using android::base::StringAppendF;
53using android::base::StringPrintf;
54
Elliott Hughesa2501992011-08-26 19:39:54 -070055/*
56 * ===========================================================================
57 * JNI function helpers
58 * ===========================================================================
59 */
60
Ian Rogers55256cb2017-12-21 17:07:11 -080061// Warn if a JNI critical is held for longer than 16ms.
62static constexpr uint64_t kCriticalWarnTimeUs = MsToUs(16);
63static_assert(kCriticalWarnTimeUs > 0, "No JNI critical warn time set");
64
Ian Rogers9e937be2018-02-15 17:06:58 -080065// True if primitives within specific ranges cause a fatal error,
66// otherwise just warn.
67static constexpr bool kBrokenPrimitivesAreFatal = kIsDebugBuild;
68
Elliott Hughes3f6635a2012-06-19 13:37:49 -070069// Flags passed into ScopedCheck.
Ian Rogers55256cb2017-12-21 17:07:11 -080070static constexpr uint16_t kFlag_Default = 0x0000;
Elliott Hughesa2501992011-08-26 19:39:54 -070071
Ian Rogers55256cb2017-12-21 17:07:11 -080072// Calling while in critical is not allowed.
73static constexpr uint16_t kFlag_CritBad = 0x0000;
74// Calling while in critical is allowed.
75static constexpr uint16_t kFlag_CritOkay = 0x0001;
76// This is a critical "get".
77static constexpr uint16_t kFlag_CritGet = 0x0002;
78// This is a critical "release".
79static constexpr uint16_t kFlag_CritRelease = 0x0003;
80// Bit mask to get "crit" value.
81static constexpr uint16_t kFlag_CritMask = 0x0003;
Elliott Hughesa2501992011-08-26 19:39:54 -070082
Ian Rogers55256cb2017-12-21 17:07:11 -080083// Raised exceptions are allowed.
84static constexpr uint16_t kFlag_ExcepOkay = 0x0004;
Elliott Hughesa2501992011-08-26 19:39:54 -070085
Ian Rogers55256cb2017-12-21 17:07:11 -080086// Are we in a non-critical release function?
87static constexpr uint16_t kFlag_Release = 0x0010;
88// Are our UTF parameters nullable?
89static constexpr uint16_t kFlag_NullableUtf = 0x0020;
Elliott Hughesa2501992011-08-26 19:39:54 -070090
Ian Rogers55256cb2017-12-21 17:07:11 -080091// Part of the invocation interface (JavaVM*).
92static constexpr uint16_t kFlag_Invocation = 0x0100;
Elliott Hughesa2501992011-08-26 19:39:54 -070093
Ian Rogers55256cb2017-12-21 17:07:11 -080094// Add this to a JNI function's flags if you want to trace every call.
95static constexpr uint16_t kFlag_ForceTrace = 0x8000;
Alex Light48ffe062015-08-19 15:23:23 -070096
97class VarArgs;
Ian Rogers68d8b422014-07-17 11:09:10 -070098/*
99 * Java primitive types:
100 * B - jbyte
101 * C - jchar
102 * D - jdouble
103 * F - jfloat
104 * I - jint
105 * J - jlong
106 * S - jshort
107 * Z - jboolean (shown as true and false)
108 * V - void
109 *
110 * Java reference types:
111 * L - jobject
112 * a - jarray
113 * c - jclass
114 * s - jstring
115 * t - jthrowable
116 *
117 * JNI types:
118 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
119 * f - jfieldID
120 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
121 * m - jmethodID
122 * p - void*
123 * r - jint (for release mode arguments)
124 * u - const char* (Modified UTF-8)
125 * z - jsize (for lengths; use i if negative values are okay)
126 * v - JavaVM*
127 * w - jobjectRefType
128 * E - JNIEnv*
129 * . - no argument; just print "..." (used for varargs JNI calls)
130 *
131 */
132union JniValueType {
133 jarray a;
134 jboolean b;
135 jclass c;
136 jfieldID f;
137 jint i;
138 jmethodID m;
139 const void* p; // Pointer.
140 jint r; // Release mode.
141 jstring s;
142 jthrowable t;
143 const char* u; // Modified UTF-8.
144 JavaVM* v;
145 jobjectRefType w;
146 jsize z;
147 jbyte B;
148 jchar C;
149 jdouble D;
150 JNIEnv* E;
151 jfloat F;
152 jint I;
153 jlong J;
154 jobject L;
155 jshort S;
156 const void* V; // void
157 jboolean Z;
Alex Light48ffe062015-08-19 15:23:23 -0700158 const VarArgs* va;
159};
160
161/*
162 * A structure containing all the information needed to validate varargs arguments.
163 *
164 * Note that actually getting the arguments from this structure mutates it so should only be done on
165 * owned copies.
166 */
167class VarArgs {
168 public:
169 VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
170 va_copy(vargs_, var);
171 }
172
173 VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
174
175 ~VarArgs() {
176 if (type_ == kTypeVaList) {
177 va_end(vargs_);
178 }
179 }
180
181 VarArgs(VarArgs&& other) {
182 m_ = other.m_;
183 cnt_ = other.cnt_;
184 type_ = other.type_;
185 if (other.type_ == kTypeVaList) {
186 va_copy(vargs_, other.vargs_);
187 } else {
188 ptr_ = other.ptr_;
189 }
190 }
191
192 // This method is const because we need to ensure that one only uses the GetValue method on an
193 // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
194 // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
195 // we want to use one we need to Clone() it.
196 VarArgs Clone() const {
197 if (type_ == kTypeVaList) {
198 // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
199 // messed up if the source argument is not the exact type 'va_list'.
200 return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
201 } else {
202 return VarArgs(m_, cnt_, ptr_);
203 }
204 }
205
206 jmethodID GetMethodID() const {
207 return m_;
208 }
209
210 JniValueType GetValue(char fmt) {
211 JniValueType o;
212 if (type_ == kTypeVaList) {
213 switch (fmt) {
Ian Rogers9e937be2018-02-15 17:06:58 -0800214 // Assign a full int for va_list values as this is what is done in reflection.cc.
215 // TODO(b/73656264): avoid undefined behavior.
216 case 'Z': FALLTHROUGH_INTENDED;
217 case 'B': FALLTHROUGH_INTENDED;
218 case 'C': FALLTHROUGH_INTENDED;
219 case 'S': FALLTHROUGH_INTENDED;
Alex Light48ffe062015-08-19 15:23:23 -0700220 case 'I': o.I = va_arg(vargs_, jint); break;
221 case 'J': o.J = va_arg(vargs_, jlong); break;
222 case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
223 case 'D': o.D = va_arg(vargs_, jdouble); break;
224 case 'L': o.L = va_arg(vargs_, jobject); break;
225 default:
226 LOG(FATAL) << "Illegal type format char " << fmt;
227 UNREACHABLE();
228 }
229 } else {
230 CHECK(type_ == kTypePtr);
231 jvalue v = ptr_[cnt_];
232 cnt_++;
233 switch (fmt) {
Ian Rogers9e937be2018-02-15 17:06:58 -0800234 // Copy just the amount of the jvalue necessary, as done in
235 // reflection.cc, but extend to an int to be consistent with
236 // var args in CheckNonHeapValue.
237 // TODO(b/73656264): avoid undefined behavior.
238 case 'Z': o.I = v.z; break;
239 case 'B': o.I = v.b; break;
240 case 'C': o.I = v.c; break;
241 case 'S': o.I = v.s; break;
Alex Light48ffe062015-08-19 15:23:23 -0700242 case 'I': o.I = v.i; break;
243 case 'J': o.J = v.j; break;
244 case 'F': o.F = v.f; break;
245 case 'D': o.D = v.d; break;
246 case 'L': o.L = v.l; break;
247 default:
248 LOG(FATAL) << "Illegal type format char " << fmt;
249 UNREACHABLE();
250 }
251 }
252 return o;
253 }
254
255 private:
256 VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
257 va_copy(vargs_, var);
258 }
259
260 VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
261
262 enum VarArgsType {
263 kTypeVaList,
264 kTypePtr,
265 };
266
267 jmethodID m_;
268 VarArgsType type_;
269 uint32_t cnt_;
270 union {
271 va_list vargs_;
272 const jvalue* ptr_;
273 };
Elliott Hughesa0957642011-09-02 14:27:33 -0700274};
275
Andreas Gampe69944c92018-04-17 11:08:23 -0700276// Check whether the current thread is attached. This is usually required
277// to be the first check, as ScopedCheck needs a ScopedObjectAccess for
278// checking heap values (and that will fail with unattached threads).
279bool CheckAttachedThread(const char* function_name) {
280 Thread* self = Thread::Current();
281 if (UNLIKELY(self == nullptr)) {
282 // Need to attach this thread for a proper abort to work. We prefer this
283 // to get reasonable stacks and environment, rather than relying on
284 // tombstoned.
285 JNIEnv* env;
286 Runtime::Current()->GetJavaVM()->AttachCurrentThread(&env, /* thread_args */ nullptr);
287
288 std::string tmp = android::base::StringPrintf(
289 "a thread (tid %" PRId64 " is making JNI calls without being attached",
290 static_cast<int64_t>(GetTid()));
291 Runtime::Current()->GetJavaVM()->JniAbort(function_name, tmp.c_str());
292
293 CHECK_NE(Runtime::Current()->GetJavaVM()->DetachCurrentThread(), JNI_ERR);
294 return false;
295 }
296 return true;
297}
298
299// Macro helpers for the above.
300#define CHECK_ATTACHED_THREAD(function_name, fail_val) \
301 do { \
302 if (!CheckAttachedThread((function_name))) { \
303 return fail_val; \
304 } \
305 } while (false)
306#define CHECK_ATTACHED_THREAD_VOID(function_name) \
307 do { \
308 if (!CheckAttachedThread((function_name))) { \
309 return; \
310 } \
311 } while (false)
312
Elliott Hughesa2501992011-08-26 19:39:54 -0700313class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800314 public:
Ian Rogers55256cb2017-12-21 17:07:11 -0800315 ScopedCheck(uint16_t flags, const char* functionName, bool has_method = true)
316 : function_name_(functionName), indent_(0), flags_(flags), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700317 }
318
Ian Rogers68d8b422014-07-17 11:09:10 -0700319 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700320
Elliott Hughes81ff3182012-03-23 20:35:56 -0700321 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
322 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
323 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
324 // circumstances, but this is incorrect.
Ian Rogers68d8b422014-07-17 11:09:10 -0700325 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700326 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700327 AbortF("illegal class name '%s'\n"
328 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
329 class_name);
330 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700331 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700332 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700333 }
334
335 /*
336 * Verify that this instance field ID is valid for this object.
337 *
338 * Assumes "jobj" has already been validated.
339 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700340 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700341 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700342 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Ian Rogers68d8b422014-07-17 11:09:10 -0700343 if (o == nullptr) {
344 AbortF("field operation on NULL object: %p", java_object);
345 return false;
346 }
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700347 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700348 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700349 AbortF("field operation on invalid %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700350 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700351 java_object);
352 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700353 }
354
Andreas Gampe08883de2016-11-08 13:20:52 -0800355 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800356 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700357 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700358 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800359 mirror::Class* c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700360 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700361 AbortF("jfieldID %s not valid for an object of class %s",
David Sehr709b0702016-10-13 09:12:37 -0700362 f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700363 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700364 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700365 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700366 }
367
368 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700369 * Verify that the pointer value is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -0700370 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700371 bool CheckNonNull(const void* ptr) {
372 if (UNLIKELY(ptr == nullptr)) {
373 AbortF("non-nullable argument was NULL");
374 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700375 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700376 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700377 }
378
379 /*
380 * Verify that the method's return type matches the type of call.
381 * 'expectedType' will be "L" for all objects, including arrays.
382 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700383 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
384 jmethodID mid, Primitive::Type type, InvokeType invoke)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700385 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800386 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800387 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700388 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700389 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700390 if (type != Primitive::GetType(m->GetShorty()[0])) {
David Sehr709b0702016-10-13 09:12:37 -0700391 AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700392 return false;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700393 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700394 bool is_static = (invoke == kStatic);
395 if (is_static != m->IsStatic()) {
396 if (is_static) {
397 AbortF("calling non-static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700398 m->PrettyMethod().c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700399 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700400 AbortF("calling static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700401 m->PrettyMethod().c_str(), function_name_);
Ian Rogers68d8b422014-07-17 11:09:10 -0700402 }
403 return false;
404 }
405 if (invoke != kVirtual) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700406 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700407 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700408 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
David Sehr709b0702016-10-13 09:12:37 -0700409 m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700410 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700411 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700412 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700413 if (invoke != kStatic) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700414 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700415 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700416 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700417 return false;
418 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700419 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
420 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700421 return false;
422 }
423 }
424 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700425 }
426
427 /*
428 * Verify that this static field ID is valid for this class.
429 *
430 * Assumes "java_class" has already been validated.
431 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700432 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700433 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700434 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Andreas Gampe08883de2016-11-08 13:20:52 -0800435 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800436 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700437 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700438 }
Alex Lighte4033fa2017-12-13 10:32:59 -0800439 if (!f->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700440 AbortF("static jfieldID %p not valid for class %s", fid,
441 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700442 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700443 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700444 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700445 }
446
447 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700448 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700449 *
450 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700451 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700452 * allow bad code in the system though.
453 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700454 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700455 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700456 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700457 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800458 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800459 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700460 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700461 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700462 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700463 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700464 AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
465 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700466 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700467 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700468 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700469 }
470
471 /*
472 * Verify that "mid" is appropriate for "jobj".
473 *
474 * Make sure the object is an instance of the method's declaring class.
475 * (Note the mid might point to a declaration in an interface; this
476 * will be handled automatically by the instanceof check.)
477 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700478 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700479 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800480 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800481 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700482 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700483 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700484 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700485 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700486 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700487 return false;
488 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700489 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
490 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700491 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700492 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700493 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700494 }
495
496 /**
497 * The format string is a sequence of the following characters,
498 * and must be followed by arguments of the corresponding types
499 * in the same order.
500 *
501 * Java primitive types:
502 * B - jbyte
503 * C - jchar
504 * D - jdouble
505 * F - jfloat
506 * I - jint
507 * J - jlong
508 * S - jshort
509 * Z - jboolean (shown as true and false)
510 * V - void
511 *
512 * Java reference types:
513 * L - jobject
514 * a - jarray
515 * c - jclass
516 * s - jstring
517 *
518 * JNI types:
519 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
520 * f - jfieldID
521 * m - jmethodID
522 * p - void*
523 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700524 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700525 * z - jsize (for lengths; use i if negative values are okay)
526 * v - JavaVM*
527 * E - JNIEnv*
Alex Light48ffe062015-08-19 15:23:23 -0700528 * . - VarArgs* for Jni calls with variable length arguments
Elliott Hughesa2501992011-08-26 19:39:54 -0700529 *
530 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
531 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700532 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700533 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700534 ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700535 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700536 // We need to guard some of the invocation interface's calls: a bad caller might
537 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700538 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800539 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
540 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700541 }
542 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700543
Ian Rogersef7d42f2014-01-06 12:55:46 -0800544 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700545 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700546 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700547 for (size_t i = 0; fmt[i] != '\0'; ++i) {
548 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
549 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700550 StringAppendF(&msg, ", ");
551 }
552 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700553
Elliott Hughes485cac42011-12-09 17:49:35 -0800554 if ((flags_ & kFlag_ForceTrace) != 0) {
555 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
556 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700557 if (has_method_) {
David Sehr709b0702016-10-13 09:12:37 -0700558 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700559 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
560 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700561 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700562 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
563 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700564 }
565 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700566 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700567 }
568 }
569
570 // We always do the thorough checks on entry, and never on exit...
571 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700572 for (size_t i = 0; fmt[i] != '\0'; ++i) {
573 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
574 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700575 }
576 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700577 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700578 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700579 }
580
Ian Rogers68d8b422014-07-17 11:09:10 -0700581 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
582 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800583 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700584 // We need to guard some of the invocation interface's calls: a bad caller might
585 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
586 Thread* self = Thread::Current();
587 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
588 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700589 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700590 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
591 }
592 }
593 if (should_trace) {
594 std::string msg;
595 for (size_t i = 0; fmt[i] != '\0'; ++i) {
596 TraceNonHeapValue(fmt[i], args[i], &msg);
597 if (fmt[i + 1] != '\0') {
598 StringAppendF(&msg, ", ");
599 }
600 }
601
602 if ((flags_ & kFlag_ForceTrace) != 0) {
603 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
604 } else if (entry) {
605 if (has_method_) {
606 Thread* self = Thread::Current();
607 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700608 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
David Sehr709b0702016-10-13 09:12:37 -0700609 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Ian Rogers68d8b422014-07-17 11:09:10 -0700610 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
611 indent_ = methodName.size() + 1;
612 } else {
613 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
614 indent_ = 0;
615 }
616 } else {
617 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
618 }
619 }
620
621 // We always do the thorough checks on entry, and never on exit...
622 if (entry) {
623 for (size_t i = 0; fmt[i] != '\0'; ++i) {
624 if (!CheckNonHeapValue(fmt[i], args[i])) {
625 return false;
626 }
627 }
628 }
629 return true;
630 }
631
632 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700633 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700634 ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700635 if (method == nullptr) {
636 AbortF("expected non-null method");
637 return false;
638 }
639 mirror::Class* c = method->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700640 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c &&
641 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700642 AbortF("expected java.lang.reflect.Method or "
643 "java.lang.reflect.Constructor but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700644 method->PrettyTypeOf().c_str(), jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700645 return false;
646 }
647 return true;
648 }
649
Andreas Gampe13b27842016-11-07 16:48:23 -0800650 bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
651 ArtMethod* method = jni::DecodeArtMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700652 if (method == nullptr) {
653 AbortF("expected non-null constructor");
654 return false;
655 }
656 if (!method->IsConstructor() || method->IsStatic()) {
David Sehr709b0702016-10-13 09:12:37 -0700657 AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700658 return false;
659 }
660 return true;
661 }
662
663 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700664 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700665 ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700666 if (field == nullptr) {
667 AbortF("expected non-null java.lang.reflect.Field");
668 return false;
669 }
670 mirror::Class* c = field->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700671 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700672 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700673 field->PrettyTypeOf().c_str(), jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700674 return false;
675 }
676 return true;
677 }
678
679 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700680 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700681 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700682 if (!obj->GetClass()->IsThrowableClass()) {
683 AbortF("expected java.lang.Throwable but got object of type "
David Sehr709b0702016-10-13 09:12:37 -0700684 "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700685 return false;
686 }
687 return true;
688 }
689
690 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700691 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700692 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700693 if (!c->IsThrowableClass()) {
694 AbortF("expected java.lang.Throwable class but got object of "
David Sehr709b0702016-10-13 09:12:37 -0700695 "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700696 return false;
697 }
698 return true;
699 }
700
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700701 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700702 IndirectRefKind found_kind;
703 if (expected_kind == kLocal) {
Andreas Gampedc061d02016-10-24 13:19:37 -0700704 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700705 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
706 found_kind = kLocal;
707 }
708 } else {
Andreas Gampedc061d02016-10-24 13:19:37 -0700709 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700710 }
711 if (obj != nullptr && found_kind != expected_kind) {
712 AbortF("expected reference of kind %s but found %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700713 GetIndirectRefKindString(expected_kind),
714 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700715 obj);
716 return false;
717 }
718 return true;
719 }
720
721 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700722 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700723 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700724 if (!c->IsInstantiableNonArray()) {
David Sehr709b0702016-10-13 09:12:37 -0700725 AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700726 return false;
727 }
728 return true;
729 }
730
731 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700732 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700733 if (!CheckArray(soa, array)) {
734 return false;
735 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700736 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700737 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
738 AbortF("incompatible array type %s expected %s[]: %p",
David Sehr709b0702016-10-13 09:12:37 -0700739 a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700740 return false;
741 }
742 return true;
743 }
744
745 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
746 Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700747 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700748 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
749 return false;
750 }
751 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
752 return false;
753 }
Andreas Gampe08883de2016-11-08 13:20:52 -0800754 ArtField* field = jni::DecodeArtField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700755 DCHECK(field != nullptr); // Already checked by Check.
756 if (is_static != field->IsStatic()) {
757 AbortF("attempt to access %s field %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700758 field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700759 return false;
760 }
761 if (type != field->GetTypeAsPrimitiveType()) {
762 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700763 field->PrettyField().c_str(),
764 PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
Ian Rogers68d8b422014-07-17 11:09:10 -0700765 PrettyDescriptor(type).c_str(), fid);
766 return false;
767 }
768 if (is_static) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700769 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700770 if (o == nullptr || !o->IsClass()) {
771 AbortF("attempt to access static field %s with a class argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700772 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700773 return false;
774 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700775 ObjPtr<mirror::Class> c = o->AsClass();
Alex Lighte4033fa2017-12-13 10:32:59 -0800776 if (!field->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700777 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700778 field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700779 return false;
780 }
781 } else {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700782 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700783 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
784 AbortF("attempt to access field %s from an object argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700785 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700786 return false;
787 }
788 }
789 return true;
790 }
791
792 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800793 enum InstanceKind {
794 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700795 kDirectByteBuffer,
796 kObject,
797 kString,
798 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800799 };
800
801 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700802 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800803 * an instance of expectedClass.
804 *
805 * Because we're looking at an object on the GC heap, we have to switch
806 * to "running" mode before doing the checks.
807 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700808 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700809 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800810 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800811 switch (kind) {
812 case kClass:
813 what = "jclass";
814 break;
815 case kDirectByteBuffer:
816 what = "direct ByteBuffer";
817 break;
818 case kObject:
819 what = "jobject";
820 break;
821 case kString:
822 what = "jstring";
823 break;
824 case kThrowable:
825 what = "jthrowable";
826 break;
827 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700828 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800829 }
830
Ian Rogersef7d42f2014-01-06 12:55:46 -0800831 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700832 if (null_ok) {
833 return true;
834 } else {
835 AbortF("%s received NULL %s", function_name_, what);
836 return false;
837 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800838 }
839
Mathieu Chartier0795f232016-09-27 18:43:30 -0700840 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700841 if (obj == nullptr) {
842 // Either java_object is invalid or is a cleared weak.
843 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
844 bool okay;
Andreas Gampedc061d02016-10-24 13:19:37 -0700845 if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) {
Ian Rogersc0542af2014-09-03 16:16:56 -0700846 okay = false;
847 } else {
848 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
Mathieu Chartierc4f39252016-10-05 18:32:08 -0700849 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
Ian Rogersc0542af2014-09-03 16:16:56 -0700850 }
851 if (!okay) {
852 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700853 what,
854 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
855 java_object,
856 obj.Ptr());
Ian Rogersc0542af2014-09-03 16:16:56 -0700857 return false;
858 }
859 }
860
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700861 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700862 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700863 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700864 what,
865 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
866 java_object,
867 obj.Ptr());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800868 return false;
869 }
870
871 bool okay = true;
872 switch (kind) {
873 case kClass:
874 okay = obj->IsClass();
875 break;
876 case kDirectByteBuffer:
877 UNIMPLEMENTED(FATAL);
878 break;
879 case kString:
880 okay = obj->GetClass()->IsStringClass();
881 break;
882 case kThrowable:
883 okay = obj->GetClass()->IsThrowableClass();
884 break;
885 case kObject:
886 break;
887 }
888 if (!okay) {
David Sehr709b0702016-10-13 09:12:37 -0700889 AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800890 return false;
891 }
892
893 return true;
894 }
895
Ian Rogers68d8b422014-07-17 11:09:10 -0700896 /*
897 * Verify that the "mode" argument passed to a primitive array Release
898 * function is one of the valid values.
899 */
900 bool CheckReleaseMode(jint mode) {
901 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
902 AbortF("unknown value for release mode: %d", mode);
903 return false;
904 }
905 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700906 }
907
Ian Rogers68d8b422014-07-17 11:09:10 -0700908 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700909 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700910 switch (fmt) {
911 case 'a': // jarray
912 return CheckArray(soa, arg.a);
913 case 'c': // jclass
914 return CheckInstance(soa, kClass, arg.c, false);
915 case 'f': // jfieldID
Andreas Gampe08883de2016-11-08 13:20:52 -0800916 return CheckFieldID(arg.f) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700917 case 'm': // jmethodID
Andreas Gampe13b27842016-11-07 16:48:23 -0800918 return CheckMethodID(arg.m) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700919 case 'r': // release int
920 return CheckReleaseMode(arg.r);
921 case 's': // jstring
922 return CheckInstance(soa, kString, arg.s, false);
923 case 't': // jthrowable
924 return CheckInstance(soa, kThrowable, arg.t, false);
925 case 'E': // JNIEnv*
926 return CheckThread(arg.E);
927 case 'L': // jobject
928 return CheckInstance(soa, kObject, arg.L, true);
Alex Light48ffe062015-08-19 15:23:23 -0700929 case '.': // A VarArgs list
930 return CheckVarArgs(soa, arg.va);
Ian Rogers68d8b422014-07-17 11:09:10 -0700931 default:
932 return CheckNonHeapValue(fmt, arg);
933 }
934 }
935
Alex Light48ffe062015-08-19 15:23:23 -0700936 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700937 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Light48ffe062015-08-19 15:23:23 -0700938 CHECK(args_p != nullptr);
939 VarArgs args(args_p->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800940 ArtMethod* m = CheckMethodID(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700941 if (m == nullptr) {
942 return false;
943 }
944 uint32_t len = 0;
945 const char* shorty = m->GetShorty(&len);
946 // Skip the return type
947 CHECK_GE(len, 1u);
948 len--;
949 shorty++;
950 for (uint32_t i = 0; i < len; i++) {
951 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
952 return false;
953 }
954 }
955 return true;
956 }
957
Ian Rogers68d8b422014-07-17 11:09:10 -0700958 bool CheckNonHeapValue(char fmt, JniValueType arg) {
959 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700960 case 'p': // TODO: pointer - null or readable?
961 case 'v': // JavaVM*
Ian Rogers68d8b422014-07-17 11:09:10 -0700962 case 'D': // jdouble
963 case 'F': // jfloat
Ian Rogers68d8b422014-07-17 11:09:10 -0700964 case 'J': // jlong
Ian Rogers9e937be2018-02-15 17:06:58 -0800965 case 'I': // jint
Ian Rogers68d8b422014-07-17 11:09:10 -0700966 break; // Ignored.
967 case 'b': // jboolean, why two? Fall-through.
968 case 'Z':
Ian Rogers9e937be2018-02-15 17:06:58 -0800969 return CheckBoolean(arg.I);
970 case 'B': // jbyte
971 return CheckByte(arg.I);
972 case 'C': // jchar
973 return CheckChar(arg.I);
974 case 'S': // jshort
975 return CheckShort(arg.I);
Ian Rogers68d8b422014-07-17 11:09:10 -0700976 case 'u': // utf8
977 if ((flags_ & kFlag_Release) != 0) {
978 return CheckNonNull(arg.u);
979 } else {
980 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
981 return CheckUtfString(arg.u, nullable);
982 }
983 case 'w': // jobjectRefType
984 switch (arg.w) {
985 case JNIInvalidRefType:
986 case JNILocalRefType:
987 case JNIGlobalRefType:
988 case JNIWeakGlobalRefType:
989 break;
990 default:
991 AbortF("Unknown reference type");
992 return false;
993 }
994 break;
995 case 'z': // jsize
996 return CheckLengthPositive(arg.z);
997 default:
998 AbortF("unknown format specifier: '%c'", fmt);
999 return false;
1000 }
1001 return true;
1002 }
1003
1004 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
1005 std::string* msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001006 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001007 switch (fmt) {
1008 case 'L': // jobject fall-through.
1009 case 'a': // jarray fall-through.
1010 case 's': // jstring fall-through.
1011 case 't': // jthrowable fall-through.
1012 if (arg.L == nullptr) {
1013 *msg += "NULL";
1014 } else {
1015 StringAppendF(msg, "%p", arg.L);
1016 }
1017 break;
1018 case 'c': { // jclass
1019 jclass jc = arg.c;
Mathieu Chartier0795f232016-09-27 18:43:30 -07001020 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -07001021 if (c == nullptr) {
1022 *msg += "NULL";
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001023 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001024 StringAppendF(msg, "INVALID POINTER:%p", jc);
1025 } else if (!c->IsClass()) {
David Sehr709b0702016-10-13 09:12:37 -07001026 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
Ian Rogers68d8b422014-07-17 11:09:10 -07001027 } else {
David Sehr709b0702016-10-13 09:12:37 -07001028 *msg += c->PrettyClass();
Ian Rogers68d8b422014-07-17 11:09:10 -07001029 if (!entry) {
1030 StringAppendF(msg, " (%p)", jc);
1031 }
1032 }
1033 break;
1034 }
1035 case 'f': { // jfieldID
1036 jfieldID fid = arg.f;
Andreas Gampe08883de2016-11-08 13:20:52 -08001037 ArtField* f = jni::DecodeArtField(fid);
David Sehr709b0702016-10-13 09:12:37 -07001038 *msg += ArtField::PrettyField(f);
Ian Rogers68d8b422014-07-17 11:09:10 -07001039 if (!entry) {
1040 StringAppendF(msg, " (%p)", fid);
1041 }
1042 break;
1043 }
1044 case 'm': { // jmethodID
1045 jmethodID mid = arg.m;
Andreas Gampe13b27842016-11-07 16:48:23 -08001046 ArtMethod* m = jni::DecodeArtMethod(mid);
David Sehr709b0702016-10-13 09:12:37 -07001047 *msg += ArtMethod::PrettyMethod(m);
Ian Rogers68d8b422014-07-17 11:09:10 -07001048 if (!entry) {
1049 StringAppendF(msg, " (%p)", mid);
1050 }
1051 break;
1052 }
Alex Light48ffe062015-08-19 15:23:23 -07001053 case '.': {
1054 const VarArgs* va = arg.va;
1055 VarArgs args(va->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -08001056 ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -07001057 uint32_t len;
1058 const char* shorty = m->GetShorty(&len);
1059 CHECK_GE(len, 1u);
1060 // Skip past return value.
1061 len--;
1062 shorty++;
1063 // Remove the previous ', ' from the message.
1064 msg->erase(msg->length() - 2);
1065 for (uint32_t i = 0; i < len; i++) {
1066 *msg += ", ";
1067 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
1068 }
1069 break;
1070 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001071 default:
1072 TraceNonHeapValue(fmt, arg, msg);
1073 break;
1074 }
1075 }
1076
1077 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
1078 switch (fmt) {
1079 case 'B': // jbyte
1080 if (arg.B >= 0 && arg.B < 10) {
1081 StringAppendF(msg, "%d", arg.B);
1082 } else {
1083 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1084 }
1085 break;
1086 case 'C': // jchar
1087 if (arg.C < 0x7f && arg.C >= ' ') {
1088 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1089 } else {
1090 StringAppendF(msg, "U+%x", arg.C);
1091 }
1092 break;
1093 case 'F': // jfloat
1094 StringAppendF(msg, "%g", arg.F);
1095 break;
1096 case 'D': // jdouble
1097 StringAppendF(msg, "%g", arg.D);
1098 break;
1099 case 'S': // jshort
1100 StringAppendF(msg, "%d", arg.S);
1101 break;
1102 case 'i': // jint - fall-through.
1103 case 'I': // jint
1104 StringAppendF(msg, "%d", arg.I);
1105 break;
1106 case 'J': // jlong
1107 StringAppendF(msg, "%" PRId64, arg.J);
1108 break;
1109 case 'Z': // jboolean
1110 case 'b': // jboolean (JNI-style)
1111 *msg += arg.b == JNI_TRUE ? "true" : "false";
1112 break;
1113 case 'V': // void
1114 DCHECK(arg.V == nullptr);
1115 *msg += "void";
1116 break;
1117 case 'v': // JavaVM*
1118 StringAppendF(msg, "(JavaVM*)%p", arg.v);
1119 break;
1120 case 'E':
1121 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1122 break;
1123 case 'z': // non-negative jsize
1124 // You might expect jsize to be size_t, but it's not; it's the same as jint.
1125 // We only treat this specially so we can do the non-negative check.
1126 // TODO: maybe this wasn't worth it?
1127 StringAppendF(msg, "%d", arg.z);
1128 break;
1129 case 'p': // void* ("pointer")
1130 if (arg.p == nullptr) {
1131 *msg += "NULL";
1132 } else {
1133 StringAppendF(msg, "(void*) %p", arg.p);
1134 }
1135 break;
1136 case 'r': { // jint (release mode)
1137 jint releaseMode = arg.r;
1138 if (releaseMode == 0) {
1139 *msg += "0";
1140 } else if (releaseMode == JNI_ABORT) {
1141 *msg += "JNI_ABORT";
1142 } else if (releaseMode == JNI_COMMIT) {
1143 *msg += "JNI_COMMIT";
1144 } else {
1145 StringAppendF(msg, "invalid release mode %d", releaseMode);
1146 }
1147 break;
1148 }
1149 case 'u': // const char* (Modified UTF-8)
1150 if (arg.u == nullptr) {
1151 *msg += "NULL";
1152 } else {
1153 StringAppendF(msg, "\"%s\"", arg.u);
1154 }
1155 break;
1156 case 'w': // jobjectRefType
1157 switch (arg.w) {
1158 case JNIInvalidRefType:
1159 *msg += "invalid reference type";
1160 break;
1161 case JNILocalRefType:
1162 *msg += "local ref type";
1163 break;
1164 case JNIGlobalRefType:
1165 *msg += "global ref type";
1166 break;
1167 case JNIWeakGlobalRefType:
1168 *msg += "weak global ref type";
1169 break;
1170 default:
1171 *msg += "unknown ref type";
1172 break;
1173 }
1174 break;
Ian Rogers68d8b422014-07-17 11:09:10 -07001175 default:
1176 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1177 }
1178 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001179 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001180 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -07001181 *
1182 * Since we're dealing with objects, switch to "running" mode.
1183 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001184 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001185 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001186 if (UNLIKELY(java_array == nullptr)) {
1187 AbortF("jarray was NULL");
1188 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001189 }
1190
Mathieu Chartier0795f232016-09-27 18:43:30 -07001191 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001192 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001193 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001194 AbortF("jarray is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -07001195 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)),
1196 java_array,
1197 a.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -07001198 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001199 } else if (!a->IsArrayInstance()) {
David Sehr709b0702016-10-13 09:12:37 -07001200 AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001201 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001202 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001203 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001204 }
1205
Ian Rogers9e937be2018-02-15 17:06:58 -08001206 bool CheckBoolean(jint z) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001207 if (z != JNI_TRUE && z != JNI_FALSE) {
Ian Rogers9e937be2018-02-15 17:06:58 -08001208 // Note, broken booleans are always fatal.
Ian Rogers68d8b422014-07-17 11:09:10 -07001209 AbortF("unexpected jboolean value: %d", z);
1210 return false;
1211 }
1212 return true;
1213 }
1214
Ian Rogers9e937be2018-02-15 17:06:58 -08001215 bool CheckByte(jint b) {
1216 if (b < std::numeric_limits<jbyte>::min() ||
1217 b > std::numeric_limits<jbyte>::max()) {
1218 if (kBrokenPrimitivesAreFatal) {
1219 AbortF("unexpected jbyte value: %d", b);
1220 return false;
1221 } else {
1222 LOG(WARNING) << "Unexpected jbyte value: " << b;
1223 }
1224 }
1225 return true;
1226 }
1227
1228 bool CheckShort(jint s) {
1229 if (s < std::numeric_limits<jshort>::min() ||
1230 s > std::numeric_limits<jshort>::max()) {
1231 if (kBrokenPrimitivesAreFatal) {
1232 AbortF("unexpected jshort value: %d", s);
1233 return false;
1234 } else {
1235 LOG(WARNING) << "Unexpected jshort value: " << s;
1236 }
1237 }
1238 return true;
1239 }
1240
1241 bool CheckChar(jint c) {
1242 if (c < std::numeric_limits<jchar>::min() ||
1243 c > std::numeric_limits<jchar>::max()) {
1244 if (kBrokenPrimitivesAreFatal) {
1245 AbortF("unexpected jchar value: %d", c);
1246 return false;
1247 } else {
1248 LOG(WARNING) << "Unexpected jchar value: " << c;
1249 }
1250 }
1251 return true;
1252 }
1253
Ian Rogers68d8b422014-07-17 11:09:10 -07001254 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001255 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001256 AbortF("negative jsize: %d", length);
1257 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001258 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001259 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001260 }
1261
Andreas Gampe08883de2016-11-08 13:20:52 -08001262 ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001263 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001264 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001265 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001266 }
Andreas Gampe08883de2016-11-08 13:20:52 -08001267 ArtField* f = jni::DecodeArtField(fid);
Mathieu Chartierc7853442015-03-27 14:35:38 -07001268 // TODO: Better check here.
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001269 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001270 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001271 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001272 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001273 }
1274 return f;
1275 }
1276
Andreas Gampe13b27842016-11-07 16:48:23 -08001277 ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001278 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001279 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001280 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001281 }
Andreas Gampe13b27842016-11-07 16:48:23 -08001282 ArtMethod* m = jni::DecodeArtMethod(mid);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001283 // TODO: Better check here.
1284 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001285 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001286 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001287 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001288 }
1289 return m;
1290 }
1291
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001292 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001293 Thread* self = Thread::Current();
Andreas Gampe69944c92018-04-17 11:08:23 -07001294 CHECK(self != nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -07001295
Daniel Erat35e827a2016-05-10 18:07:18 -06001296 // Get the current thread's JNIEnv by going through our TLS pointer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001297 JNIEnvExt* threadEnv = self->GetJniEnv();
1298
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001299 // Verify that the current thread is (a) attached and (b) associated with
1300 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001301 if (env != threadEnv) {
Daniel Erat35e827a2016-05-10 18:07:18 -06001302 // Get the thread owning the JNIEnv that's being used.
Ian Rogersac4d45a2018-02-15 11:19:01 -08001303 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->GetSelf();
Ian Rogers68d8b422014-07-17 11:09:10 -07001304 AbortF("thread %s using JNIEnv* from thread %s",
Daniel Erat35e827a2016-05-10 18:07:18 -06001305 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001306 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001307 }
1308
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001309 // Verify that, if this thread previously made a critical "get" call, we
1310 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001311 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001312 case kFlag_CritOkay: // okay to call this method
1313 break;
1314 case kFlag_CritBad: // not okay to call
Ian Rogersac4d45a2018-02-15 11:19:01 -08001315 if (threadEnv->GetCritical() > 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001316 AbortF("thread %s using JNI after critical get",
1317 ToStr<Thread>(*self).c_str());
1318 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001319 }
1320 break;
1321 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001322 // Don't check here; we allow nested gets.
Ian Rogersac4d45a2018-02-15 11:19:01 -08001323 if (threadEnv->GetCritical() == 0) {
1324 threadEnv->SetCriticalStartUs(self->GetCpuMicroTime());
Ian Rogers55256cb2017-12-21 17:07:11 -08001325 }
Ian Rogersac4d45a2018-02-15 11:19:01 -08001326 threadEnv->SetCritical(threadEnv->GetCritical() + 1);
Elliott Hughesa2501992011-08-26 19:39:54 -07001327 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001328 case kFlag_CritRelease: // this is a "release" call
Ian Rogersac4d45a2018-02-15 11:19:01 -08001329 if (threadEnv->GetCritical() == 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001330 AbortF("thread %s called too many critical releases",
1331 ToStr<Thread>(*self).c_str());
1332 return false;
Ian Rogersac4d45a2018-02-15 11:19:01 -08001333 } else if (threadEnv->GetCritical() == 1) {
Ian Rogers55256cb2017-12-21 17:07:11 -08001334 // Leaving the critical region, possibly warn about long critical regions.
Ian Rogersac4d45a2018-02-15 11:19:01 -08001335 uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->GetCriticalStartUs();
Ian Rogers55256cb2017-12-21 17:07:11 -08001336 if (critical_duration_us > kCriticalWarnTimeUs) {
1337 LOG(WARNING) << "JNI critical lock held for "
1338 << PrettyDuration(UsToNs(critical_duration_us)) << " on " << *self;
1339 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001340 }
Ian Rogersac4d45a2018-02-15 11:19:01 -08001341 threadEnv->SetCritical(threadEnv->GetCritical() - 1);
Elliott Hughesa2501992011-08-26 19:39:54 -07001342 break;
1343 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001344 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001345 }
1346
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001347 // Verify that, if an exception has been raised, the native code doesn't
1348 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001349 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001350 mirror::Throwable* exception = self->GetException();
1351 AbortF("JNI %s called with pending exception %s",
1352 function_name_,
1353 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001354 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001355 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001356 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001357 }
1358
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001359 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001360 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001361 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001362 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001363 AbortF("non-nullable const char* was NULL");
1364 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001365 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001366 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001367 }
1368
Ian Rogersef7d42f2014-01-06 12:55:46 -08001369 const char* errorKind = nullptr;
Andreas Gampeef4afe92015-07-27 21:03:25 -07001370 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001371 if (errorKind != nullptr) {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001372 // This is an expensive loop that will resize often, but this isn't supposed to hit in
1373 // practice anyways.
1374 std::ostringstream oss;
1375 oss << std::hex;
1376 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1377 while (*tmp != 0) {
1378 if (tmp == utf8) {
1379 oss << "<";
1380 }
1381 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1382 if (tmp == utf8) {
1383 oss << '>';
1384 }
1385 tmp++;
1386 if (*tmp != 0) {
1387 oss << ' ';
1388 }
1389 }
1390
Ian Rogers68d8b422014-07-17 11:09:10 -07001391 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
Andreas Gampeef4afe92015-07-27 21:03:25 -07001392 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001393 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001394 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001395 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001396 }
1397
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001398 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1399 // sequences in place of encoded surrogate pairs.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001400 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001401 while (*bytes != '\0') {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001402 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
Elliott Hughesa2501992011-08-26 19:39:54 -07001403 // Switch on the high four bits.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001404 switch (*utf8 >> 4) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001405 case 0x00:
1406 case 0x01:
1407 case 0x02:
1408 case 0x03:
1409 case 0x04:
1410 case 0x05:
1411 case 0x06:
1412 case 0x07:
1413 // Bit pattern 0xxx. No need for any extra bytes.
1414 break;
1415 case 0x08:
1416 case 0x09:
1417 case 0x0a:
1418 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001419 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001420 *errorKind = "start";
1421 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001422 case 0x0f:
1423 // Bit pattern 1111, which might be the start of a 4 byte sequence.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001424 if ((*utf8 & 0x08) == 0) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001425 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1426 // We consume one continuation byte here, and fall through to consume two more.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001427 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1428 if ((*utf8 & 0xc0) != 0x80) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001429 *errorKind = "continuation";
1430 return utf8;
1431 }
1432 } else {
1433 *errorKind = "start";
1434 return utf8;
1435 }
1436
1437 // Fall through to the cases below to consume two more continuation bytes.
1438 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001439 case 0x0e:
1440 // Bit pattern 1110, so there are two additional bytes.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001441 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1442 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001443 *errorKind = "continuation";
1444 return utf8;
1445 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001446
1447 // Fall through to consume one more continuation byte.
1448 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001449 case 0x0c:
1450 case 0x0d:
1451 // Bit pattern 110x, so there is one additional byte.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001452 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1453 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001454 *errorKind = "continuation";
1455 return utf8;
1456 }
1457 break;
1458 }
1459 }
1460 return 0;
1461 }
1462
Ian Rogers68d8b422014-07-17 11:09:10 -07001463 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1464 va_list args;
1465 va_start(args, fmt);
1466 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1467 va_end(args);
1468 }
1469
1470 // The name of the JNI function being checked.
1471 const char* const function_name_;
1472
Elliott Hughes92cb4982011-12-16 16:57:28 -08001473 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001474
Ian Rogers55256cb2017-12-21 17:07:11 -08001475 const uint16_t flags_;
1476
Ian Rogers68d8b422014-07-17 11:09:10 -07001477 const bool has_method_;
1478
Elliott Hughesa2501992011-08-26 19:39:54 -07001479 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1480};
1481
Elliott Hughesa2501992011-08-26 19:39:54 -07001482/*
1483 * ===========================================================================
1484 * Guarded arrays
1485 * ===========================================================================
1486 */
1487
Elliott Hughesa2501992011-08-26 19:39:54 -07001488/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001489class GuardedCopy {
1490 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001491 /*
1492 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1493 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001494 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001495 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001496 const size_t new_len = LengthIncludingRedZones(len);
1497 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001498
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001499 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001500 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001501 if (!mod_okay) {
1502 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001503 }
1504
Ian Rogers68d8b422014-07-17 11:09:10 -07001505 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001506
Ian Rogers68d8b422014-07-17 11:09:10 -07001507 // Fill begin region with canary pattern.
1508 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1509 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1510 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1511 if (kCanary[j] == '\0') {
1512 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001513 } else {
1514 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001515 }
1516 }
1517
1518 // Copy the data in; note "len" could be zero.
1519 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1520
1521 // Fill end region with canary pattern.
1522 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1523 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1524 if (kCanary[j] == '\0') {
1525 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001526 } else {
1527 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001528 }
1529 }
1530
1531 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001532 }
1533
1534 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001535 * Create a guarded copy of a primitive array. Modifications to the copied
1536 * data are allowed. Returns a pointer to the copied data.
1537 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001538 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1539 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001540 ScopedObjectAccess soa(env);
1541
Mathieu Chartier0795f232016-09-27 18:43:30 -07001542 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Ian Rogers68d8b422014-07-17 11:09:10 -07001543 size_t component_size = a->GetClass()->GetComponentSize();
1544 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001545 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001546 if (is_copy != nullptr) {
1547 *is_copy = JNI_TRUE;
1548 }
1549 return result;
1550 }
1551
1552 /*
1553 * Perform the array "release" operation, which may or may not copy data
1554 * back into the managed heap, and may or may not release the underlying storage.
1555 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001556 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1557 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1558 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001559 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001560 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1561 return nullptr;
1562 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001563 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1564 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001565 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001566 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001567 }
1568 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001569 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001570 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001571 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001572 }
1573
1574
1575 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001576 * Free up the guard buffer, scrub it, and return the original pointer.
1577 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001578 static void* Destroy(void* embedded_buf) {
1579 GuardedCopy* copy = FromEmbedded(embedded_buf);
1580 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1581 size_t len = LengthIncludingRedZones(copy->original_length_);
1582 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001583 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001584 }
1585
1586 /*
1587 * Verify the guard area and, if "modOkay" is false, that the data itself
1588 * has not been altered.
1589 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001590 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001591 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001592 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1593 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1594 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001595 }
1596
1597 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001598 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001599 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1600 }
1601
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001602 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001603 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001604 if (result == MAP_FAILED) {
1605 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1606 }
1607 return reinterpret_cast<uint8_t*>(result);
1608 }
1609
Ian Rogers68d8b422014-07-17 11:09:10 -07001610 static void DebugFree(void* buf, size_t len) {
1611 if (munmap(buf, len) != 0) {
1612 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001613 }
1614 }
1615
Ian Rogers68d8b422014-07-17 11:09:10 -07001616 static size_t LengthIncludingRedZones(size_t len) {
1617 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001618 }
1619
Ian Rogers68d8b422014-07-17 11:09:10 -07001620 // Get the GuardedCopy from the interior pointer.
1621 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1622 return reinterpret_cast<GuardedCopy*>(
1623 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001624 }
1625
Ian Rogers68d8b422014-07-17 11:09:10 -07001626 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1627 return reinterpret_cast<const GuardedCopy*>(
1628 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001629 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001630
1631 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1632 va_list args;
1633 va_start(args, fmt);
1634 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1635 va_end(args);
1636 }
1637
1638 bool CheckHeader(const char* function_name, bool mod_okay) const {
1639 static const uint32_t kMagicCmp = kGuardMagic;
1640
1641 // Before we do anything with "pExtra", check the magic number. We
1642 // do the check with memcmp rather than "==" in case the pointer is
1643 // unaligned. If it points to completely bogus memory we're going
1644 // to crash, but there's no easy way around that.
1645 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1646 uint8_t buf[4];
1647 memcpy(buf, &magic_, 4);
1648 AbortF(function_name,
1649 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1650 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1651 return false;
1652 }
1653
1654 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1655 // told the client that we made a copy, there's no reason they can't alter the buffer.
1656 if (!mod_okay) {
1657 uLong computed_adler =
1658 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1659 if (computed_adler != adler_) {
1660 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1661 computed_adler, adler_, this);
1662 return false;
1663 }
1664 }
1665 return true;
1666 }
1667
1668 bool CheckRedZones(const char* function_name) const {
1669 // Check the begin red zone.
1670 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1671 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1672 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1673 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1674 return false;
1675 }
1676 if (kCanary[j] == '\0') {
1677 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001678 } else {
1679 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001680 }
1681 }
1682
1683 // Check end region.
1684 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1685 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1686 size_t offset_from_buffer_start =
1687 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1688 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1689 offset_from_buffer_start);
1690 return false;
1691 }
1692 if (kCanary[j] == '\0') {
1693 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001694 } else {
1695 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001696 }
1697 }
1698 return true;
1699 }
1700
1701 // Location that canary value will be written before the guarded region.
1702 const char* StartRedZone() const {
1703 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1704 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1705 }
1706
1707 // Return the interior embedded buffer.
1708 const uint8_t* BufferWithinRedZones() const {
1709 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1710 return embedded_buf;
1711 }
1712
1713 // Location that canary value will be written after the guarded region.
1714 const char* EndRedZone() const {
1715 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1716 size_t buf_len = LengthIncludingRedZones(original_length_);
1717 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1718 }
1719
1720 static constexpr size_t kRedZoneSize = 512;
1721 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1722
1723 // Value written before and after the guarded array.
1724 static const char* const kCanary;
1725
1726 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1727
1728 const uint32_t magic_;
1729 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001730 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001731 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001732};
Ian Rogers68d8b422014-07-17 11:09:10 -07001733const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001734
1735/*
1736 * ===========================================================================
1737 * JNI functions
1738 * ===========================================================================
1739 */
1740
1741class CheckJNI {
1742 public:
1743 static jint GetVersion(JNIEnv* env) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001744 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07001745 ScopedObjectAccess soa(env);
1746 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1747 JniValueType args[1] = {{.E = env }};
1748 if (sc.Check(soa, true, "E", args)) {
1749 JniValueType result;
1750 result.I = baseEnv(env)->GetVersion(env);
1751 if (sc.Check(soa, false, "I", &result)) {
1752 return result.I;
1753 }
1754 }
1755 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001756 }
1757
Ian Rogers68d8b422014-07-17 11:09:10 -07001758 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001759 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07001760 ScopedObjectAccess soa(env);
1761 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1762 JniValueType args[2] = {{.E = env }, {.p = vm}};
1763 if (sc.Check(soa, true, "Ep", args)) {
1764 JniValueType result;
1765 result.i = baseEnv(env)->GetJavaVM(env, vm);
1766 if (sc.Check(soa, false, "i", &result)) {
1767 return result.i;
1768 }
1769 }
1770 return JNI_ERR;
1771 }
1772
1773 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001774 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07001775 ScopedObjectAccess soa(env);
1776 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1777 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1778 if (sc.Check(soa, true, "EcpI", args)) {
1779 JniValueType result;
1780 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1781 if (sc.Check(soa, false, "i", &result)) {
1782 return result.i;
1783 }
1784 }
1785 return JNI_ERR;
1786 }
1787
1788 static jint UnregisterNatives(JNIEnv* env, jclass c) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001789 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07001790 ScopedObjectAccess soa(env);
1791 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1792 JniValueType args[2] = {{.E = env }, {.c = c}};
1793 if (sc.Check(soa, true, "Ec", args)) {
1794 JniValueType result;
1795 result.i = baseEnv(env)->UnregisterNatives(env, c);
1796 if (sc.Check(soa, false, "i", &result)) {
1797 return result.i;
1798 }
1799 }
1800 return JNI_ERR;
1801 }
1802
1803 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001804 CHECK_ATTACHED_THREAD(__FUNCTION__, JNIInvalidRefType);
Ian Rogersc0542af2014-09-03 16:16:56 -07001805 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1806 // know the object is invalid. The spec says that passing invalid objects or even ones that
1807 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001808 ScopedObjectAccess soa(env);
1809 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001810 JniValueType args[2] = {{.E = env }, {.L = obj}};
1811 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001812 JniValueType result;
1813 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1814 if (sc.Check(soa, false, "w", &result)) {
1815 return result.w;
1816 }
1817 }
1818 return JNIInvalidRefType;
1819 }
1820
1821 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1822 jsize bufLen) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001823 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001824 ScopedObjectAccess soa(env);
1825 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1826 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1827 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1828 JniValueType result;
1829 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1830 if (sc.Check(soa, false, "c", &result)) {
1831 return result.c;
1832 }
1833 }
1834 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001835 }
1836
1837 static jclass FindClass(JNIEnv* env, const char* name) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001838 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001839 ScopedObjectAccess soa(env);
1840 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1841 JniValueType args[2] = {{.E = env}, {.u = name}};
1842 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1843 JniValueType result;
1844 result.c = baseEnv(env)->FindClass(env, name);
1845 if (sc.Check(soa, false, "c", &result)) {
1846 return result.c;
1847 }
1848 }
1849 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001850 }
1851
Elliott Hughese84278b2012-03-22 10:06:53 -07001852 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001853 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001854 ScopedObjectAccess soa(env);
1855 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1856 JniValueType args[2] = {{.E = env}, {.c = c}};
1857 if (sc.Check(soa, true, "Ec", args)) {
1858 JniValueType result;
1859 result.c = baseEnv(env)->GetSuperclass(env, c);
1860 if (sc.Check(soa, false, "c", &result)) {
1861 return result.c;
1862 }
1863 }
1864 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001865 }
1866
Elliott Hughese84278b2012-03-22 10:06:53 -07001867 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001868 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
Ian Rogers68d8b422014-07-17 11:09:10 -07001869 ScopedObjectAccess soa(env);
1870 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1871 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1872 if (sc.Check(soa, true, "Ecc", args)) {
1873 JniValueType result;
1874 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1875 if (sc.Check(soa, false, "b", &result)) {
1876 return result.b;
1877 }
1878 }
1879 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001880 }
1881
1882 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001883 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001884 ScopedObjectAccess soa(env);
1885 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1886 JniValueType args[2] = {{.E = env}, {.L = method}};
1887 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1888 JniValueType result;
1889 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1890 if (sc.Check(soa, false, "m", &result)) {
1891 return result.m;
1892 }
1893 }
1894 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001895 }
1896
1897 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001898 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001899 ScopedObjectAccess soa(env);
1900 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1901 JniValueType args[2] = {{.E = env}, {.L = field}};
1902 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1903 JniValueType result;
1904 result.f = baseEnv(env)->FromReflectedField(env, field);
1905 if (sc.Check(soa, false, "f", &result)) {
1906 return result.f;
1907 }
1908 }
1909 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001910 }
1911
1912 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001913 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001914 ScopedObjectAccess soa(env);
1915 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogers9e937be2018-02-15 17:06:58 -08001916 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.I = isStatic}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001917 if (sc.Check(soa, true, "Ecmb", args)) {
1918 JniValueType result;
1919 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1920 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1921 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1922 return result.L;
1923 }
1924 }
1925 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001926 }
1927
1928 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001929 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001930 ScopedObjectAccess soa(env);
1931 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogers9e937be2018-02-15 17:06:58 -08001932 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.I = isStatic}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001933 if (sc.Check(soa, true, "Ecfb", args)) {
1934 JniValueType result;
1935 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1936 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1937 DCHECK(sc.CheckReflectedField(soa, result.L));
1938 return result.L;
1939 }
1940 }
1941 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001942 }
1943
1944 static jint Throw(JNIEnv* env, jthrowable obj) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001945 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07001946 ScopedObjectAccess soa(env);
1947 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1948 JniValueType args[2] = {{.E = env}, {.t = obj}};
1949 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1950 JniValueType result;
1951 result.i = baseEnv(env)->Throw(env, obj);
1952 if (sc.Check(soa, false, "i", &result)) {
1953 return result.i;
1954 }
1955 }
1956 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001957 }
1958
Elliott Hughese84278b2012-03-22 10:06:53 -07001959 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001960 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07001961 ScopedObjectAccess soa(env);
1962 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001963 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001964 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1965 JniValueType result;
1966 result.i = baseEnv(env)->ThrowNew(env, c, message);
1967 if (sc.Check(soa, false, "i", &result)) {
1968 return result.i;
1969 }
1970 }
1971 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001972 }
1973
1974 static jthrowable ExceptionOccurred(JNIEnv* env) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001975 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07001976 ScopedObjectAccess soa(env);
1977 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1978 JniValueType args[1] = {{.E = env}};
1979 if (sc.Check(soa, true, "E", args)) {
1980 JniValueType result;
1981 result.t = baseEnv(env)->ExceptionOccurred(env);
1982 if (sc.Check(soa, false, "t", &result)) {
1983 return result.t;
1984 }
1985 }
1986 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001987 }
1988
1989 static void ExceptionDescribe(JNIEnv* env) {
Andreas Gampe69944c92018-04-17 11:08:23 -07001990 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Ian Rogers68d8b422014-07-17 11:09:10 -07001991 ScopedObjectAccess soa(env);
1992 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1993 JniValueType args[1] = {{.E = env}};
1994 if (sc.Check(soa, true, "E", args)) {
1995 JniValueType result;
1996 baseEnv(env)->ExceptionDescribe(env);
1997 result.V = nullptr;
1998 sc.Check(soa, false, "V", &result);
1999 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002000 }
2001
2002 static void ExceptionClear(JNIEnv* env) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002003 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Ian Rogers68d8b422014-07-17 11:09:10 -07002004 ScopedObjectAccess soa(env);
2005 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2006 JniValueType args[1] = {{.E = env}};
2007 if (sc.Check(soa, true, "E", args)) {
2008 JniValueType result;
2009 baseEnv(env)->ExceptionClear(env);
2010 result.V = nullptr;
2011 sc.Check(soa, false, "V", &result);
2012 }
2013 }
2014
2015 static jboolean ExceptionCheck(JNIEnv* env) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002016 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
Ian Rogers68d8b422014-07-17 11:09:10 -07002017 ScopedObjectAccess soa(env);
2018 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
2019 JniValueType args[1] = {{.E = env}};
2020 if (sc.Check(soa, true, "E", args)) {
2021 JniValueType result;
2022 result.b = baseEnv(env)->ExceptionCheck(env);
2023 if (sc.Check(soa, false, "b", &result)) {
2024 return result.b;
2025 }
2026 }
2027 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07002028 }
2029
2030 static void FatalError(JNIEnv* env, const char* msg) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002031 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Elliott Hughesc4378df2013-06-14 17:05:13 -07002032 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
2033 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
2034 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07002035 ScopedObjectAccess soa(env);
2036 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
2037 JniValueType args[2] = {{.E = env}, {.u = msg}};
2038 if (sc.Check(soa, true, "Eu", args)) {
2039 JniValueType result;
2040 baseEnv(env)->FatalError(env, msg);
2041 // Unreachable.
2042 result.V = nullptr;
2043 sc.Check(soa, false, "V", &result);
2044 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002045 }
2046
2047 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002048 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002049 ScopedObjectAccess soa(env);
2050 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2051 JniValueType args[2] = {{.E = env}, {.I = capacity}};
2052 if (sc.Check(soa, true, "EI", args)) {
2053 JniValueType result;
2054 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
2055 if (sc.Check(soa, false, "i", &result)) {
2056 return result.i;
2057 }
2058 }
2059 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002060 }
2061
2062 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002063 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002064 ScopedObjectAccess soa(env);
2065 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2066 JniValueType args[2] = {{.E = env}, {.L = res}};
2067 if (sc.Check(soa, true, "EL", args)) {
2068 JniValueType result;
2069 result.L = baseEnv(env)->PopLocalFrame(env, res);
2070 sc.Check(soa, false, "L", &result);
2071 return result.L;
2072 }
2073 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002074 }
2075
2076 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002077 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07002078 }
2079
Ian Rogers68d8b422014-07-17 11:09:10 -07002080 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
2081 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07002082 }
2083
2084 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002085 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07002086 }
2087
Ian Rogers68d8b422014-07-17 11:09:10 -07002088 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
2089 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07002090 }
2091
Ian Rogers68d8b422014-07-17 11:09:10 -07002092 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
2093 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
2094 }
2095
2096 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
2097 DeleteRef(__FUNCTION__, env, obj, kLocal);
2098 }
2099
2100 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002101 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002102 ScopedObjectAccess soa(env);
2103 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2104 JniValueType args[2] = {{.E = env}, {.I = capacity}};
2105 if (sc.Check(soa, true, "EI", args)) {
2106 JniValueType result;
2107 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
2108 if (sc.Check(soa, false, "i", &result)) {
2109 return result.i;
2110 }
2111 }
2112 return JNI_ERR;
2113 }
2114
2115 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002116 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
Ian Rogers68d8b422014-07-17 11:09:10 -07002117 ScopedObjectAccess soa(env);
2118 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2119 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
2120 if (sc.Check(soa, true, "ELL", args)) {
2121 JniValueType result;
2122 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
2123 if (sc.Check(soa, false, "b", &result)) {
2124 return result.b;
2125 }
2126 }
2127 return JNI_FALSE;
2128 }
2129
2130 static jobject AllocObject(JNIEnv* env, jclass c) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002131 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002132 ScopedObjectAccess soa(env);
2133 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2134 JniValueType args[2] = {{.E = env}, {.c = c}};
2135 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
2136 JniValueType result;
2137 result.L = baseEnv(env)->AllocObject(env, c);
2138 if (sc.Check(soa, false, "L", &result)) {
2139 return result.L;
2140 }
2141 }
2142 return nullptr;
2143 }
2144
2145 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002146 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002147 ScopedObjectAccess soa(env);
2148 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002149 VarArgs rest(mid, vargs);
2150 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2151 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002152 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002153 JniValueType result;
2154 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2155 if (sc.Check(soa, false, "L", &result)) {
2156 return result.L;
2157 }
2158 }
2159 return nullptr;
2160 }
2161
2162 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002163 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002164 va_list args;
2165 va_start(args, mid);
2166 jobject result = NewObjectV(env, c, mid, args);
2167 va_end(args);
2168 return result;
2169 }
2170
2171 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002172 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002173 ScopedObjectAccess soa(env);
2174 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002175 VarArgs rest(mid, vargs);
2176 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2177 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002178 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002179 JniValueType result;
2180 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2181 if (sc.Check(soa, false, "L", &result)) {
2182 return result.L;
2183 }
2184 }
2185 return nullptr;
2186 }
2187
2188 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002189 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002190 ScopedObjectAccess soa(env);
2191 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2192 JniValueType args[2] = {{.E = env}, {.L = obj}};
2193 if (sc.Check(soa, true, "EL", args)) {
2194 JniValueType result;
2195 result.c = baseEnv(env)->GetObjectClass(env, obj);
2196 if (sc.Check(soa, false, "c", &result)) {
2197 return result.c;
2198 }
2199 }
2200 return nullptr;
2201 }
2202
2203 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002204 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
Ian Rogers68d8b422014-07-17 11:09:10 -07002205 ScopedObjectAccess soa(env);
2206 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2207 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2208 if (sc.Check(soa, true, "ELc", args)) {
2209 JniValueType result;
2210 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2211 if (sc.Check(soa, false, "b", &result)) {
2212 return result.b;
2213 }
2214 }
2215 return JNI_FALSE;
2216 }
2217
2218 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2219 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2220 }
2221
2222 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2223 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2224 }
2225
2226 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2227 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2228 }
2229
2230 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2231 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2232 }
2233
Ian Rogers9e937be2018-02-15 17:06:58 -08002234#define FIELD_ACCESSORS(jtype, name, ptype, shorty, slot_sized_shorty) \
Ian Rogers68d8b422014-07-17 11:09:10 -07002235 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2236 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2237 } \
2238 \
2239 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2240 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2241 } \
2242 \
2243 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2244 JniValueType value; \
Ian Rogers9e937be2018-02-15 17:06:58 -08002245 value.slot_sized_shorty = v; \
Ian Rogers68d8b422014-07-17 11:09:10 -07002246 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2247 } \
2248 \
2249 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2250 JniValueType value; \
Ian Rogers9e937be2018-02-15 17:06:58 -08002251 value.slot_sized_shorty = v; \
Ian Rogers68d8b422014-07-17 11:09:10 -07002252 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2253 }
2254
Ian Rogers9e937be2018-02-15 17:06:58 -08002255 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L, L)
2256 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z, I)
2257 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B, I)
2258 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C, I)
2259 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S, I)
2260 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I, I)
2261 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J, J)
2262 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F, F)
2263 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D, D)
Ian Rogers68d8b422014-07-17 11:09:10 -07002264#undef FIELD_ACCESSORS
2265
2266 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
2267 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2268 }
2269
2270 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2271 jvalue* vargs) {
2272 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2273 }
2274
2275 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01002276 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07002277 }
2278
2279 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2280 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2281 }
2282
2283 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2284 va_list vargs) {
2285 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2286 }
2287
2288 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2289 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2290 }
2291
2292 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2293 va_list vargs;
2294 va_start(vargs, mid);
2295 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2296 va_end(vargs);
2297 }
2298
2299 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2300 va_list vargs;
2301 va_start(vargs, mid);
2302 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2303 va_end(vargs);
2304 }
2305
2306 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2307 va_list vargs;
2308 va_start(vargs, mid);
2309 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2310 va_end(vargs);
2311 }
2312
2313#define CALL(rtype, name, ptype, shorty) \
2314 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
2315 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2316 } \
2317 \
2318 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2319 jvalue* vargs) { \
2320 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2321 } \
2322 \
2323 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2324 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2325 } \
2326 \
2327 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2328 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2329 } \
2330 \
2331 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2332 va_list vargs) { \
2333 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2334 } \
2335 \
2336 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2337 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2338 } \
2339 \
2340 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2341 va_list vargs; \
2342 va_start(vargs, mid); \
2343 rtype result = \
2344 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2345 va_end(vargs); \
2346 return result; \
2347 } \
2348 \
2349 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2350 ...) { \
2351 va_list vargs; \
2352 va_start(vargs, mid); \
2353 rtype result = \
2354 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2355 va_end(vargs); \
2356 return result; \
2357 } \
2358 \
2359 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2360 va_list vargs; \
2361 va_start(vargs, mid); \
2362 rtype result = \
2363 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2364 va_end(vargs); \
2365 return result; \
2366 }
2367
2368 CALL(jobject, Object, Primitive::kPrimNot, L)
2369 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2370 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2371 CALL(jchar, Char, Primitive::kPrimChar, C)
2372 CALL(jshort, Short, Primitive::kPrimShort, S)
2373 CALL(jint, Int, Primitive::kPrimInt, I)
2374 CALL(jlong, Long, Primitive::kPrimLong, J)
2375 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2376 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2377#undef CALL
2378
2379 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002380 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002381 ScopedObjectAccess soa(env);
2382 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2383 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2384 if (sc.Check(soa, true, "Epz", args)) {
2385 JniValueType result;
2386 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2387 if (sc.Check(soa, false, "s", &result)) {
2388 return result.s;
2389 }
2390 }
2391 return nullptr;
2392 }
2393
2394 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002395 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002396 ScopedObjectAccess soa(env);
2397 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2398 JniValueType args[2] = {{.E = env}, {.u = chars}};
2399 if (sc.Check(soa, true, "Eu", args)) {
2400 JniValueType result;
2401 // TODO: stale? show pointer and truncate string.
2402 result.s = baseEnv(env)->NewStringUTF(env, chars);
2403 if (sc.Check(soa, false, "s", &result)) {
2404 return result.s;
2405 }
2406 }
2407 return nullptr;
2408 }
2409
2410 static jsize GetStringLength(JNIEnv* env, jstring string) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002411 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002412 ScopedObjectAccess soa(env);
2413 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2414 JniValueType args[2] = {{.E = env}, {.s = string}};
2415 if (sc.Check(soa, true, "Es", args)) {
2416 JniValueType result;
2417 result.z = baseEnv(env)->GetStringLength(env, string);
2418 if (sc.Check(soa, false, "z", &result)) {
2419 return result.z;
2420 }
2421 }
2422 return JNI_ERR;
2423 }
2424
2425 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002426 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002427 ScopedObjectAccess soa(env);
2428 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2429 JniValueType args[2] = {{.E = env}, {.s = string}};
2430 if (sc.Check(soa, true, "Es", args)) {
2431 JniValueType result;
2432 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2433 if (sc.Check(soa, false, "z", &result)) {
2434 return result.z;
2435 }
2436 }
2437 return JNI_ERR;
2438 }
2439
2440 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2441 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2442 is_copy, false, false));
2443 }
2444
2445 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2446 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2447 is_copy, true, false));
2448 }
2449
2450 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2451 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2452 is_copy, false, true));
2453 }
2454
2455 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2456 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2457 }
2458
2459 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2460 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2461 }
2462
2463 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2464 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2465 }
2466
2467 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002468 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Ian Rogers68d8b422014-07-17 11:09:10 -07002469 ScopedObjectAccess soa(env);
2470 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2471 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2472 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2473 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2474 if (sc.Check(soa, true, "EsIIp", args)) {
2475 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2476 JniValueType result;
2477 result.V = nullptr;
2478 sc.Check(soa, false, "V", &result);
2479 }
2480 }
2481
2482 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002483 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Ian Rogers68d8b422014-07-17 11:09:10 -07002484 ScopedObjectAccess soa(env);
2485 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2486 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2487 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2488 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2489 if (sc.Check(soa, true, "EsIIp", args)) {
2490 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2491 JniValueType result;
2492 result.V = nullptr;
2493 sc.Check(soa, false, "V", &result);
2494 }
2495 }
2496
2497 static jsize GetArrayLength(JNIEnv* env, jarray array) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002498 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002499 ScopedObjectAccess soa(env);
2500 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2501 JniValueType args[2] = {{.E = env}, {.a = array}};
2502 if (sc.Check(soa, true, "Ea", args)) {
2503 JniValueType result;
2504 result.z = baseEnv(env)->GetArrayLength(env, array);
2505 if (sc.Check(soa, false, "z", &result)) {
2506 return result.z;
2507 }
2508 }
2509 return JNI_ERR;
2510 }
2511
2512 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2513 jobject initial_element) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002514 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002515 ScopedObjectAccess soa(env);
2516 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2517 JniValueType args[4] =
2518 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2519 if (sc.Check(soa, true, "EzcL", args)) {
2520 JniValueType result;
2521 // Note: assignability tests of initial_element are done in the base implementation.
2522 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2523 if (sc.Check(soa, false, "a", &result)) {
2524 return down_cast<jobjectArray>(result.a);
2525 }
2526 }
2527 return nullptr;
2528 }
2529
2530 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002531 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002532 ScopedObjectAccess soa(env);
2533 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2534 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2535 if (sc.Check(soa, true, "Eaz", args)) {
2536 JniValueType result;
2537 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2538 if (sc.Check(soa, false, "L", &result)) {
2539 return result.L;
2540 }
2541 }
2542 return nullptr;
2543 }
2544
2545 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002546 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Ian Rogers68d8b422014-07-17 11:09:10 -07002547 ScopedObjectAccess soa(env);
2548 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2549 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2550 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2551 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2552 // in ArrayStoreExceptions.
2553 if (sc.Check(soa, true, "EaIL", args)) {
2554 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2555 JniValueType result;
2556 result.V = nullptr;
2557 sc.Check(soa, false, "V", &result);
2558 }
2559 }
2560
2561 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2562 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2563 Primitive::kPrimBoolean));
2564 }
2565
2566 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2567 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2568 Primitive::kPrimByte));
2569 }
2570
2571 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2572 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2573 Primitive::kPrimChar));
2574 }
2575
2576 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2577 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2578 Primitive::kPrimShort));
2579 }
2580
2581 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2582 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2583 }
2584
2585 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2586 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2587 Primitive::kPrimLong));
2588 }
2589
2590 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2591 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2592 Primitive::kPrimFloat));
2593 }
2594
2595 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2596 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2597 Primitive::kPrimDouble));
2598 }
2599
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002600// NOLINT added to avoid wrong warning/fix from clang-tidy.
Ian Rogers68d8b422014-07-17 11:09:10 -07002601#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002602 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2603 return reinterpret_cast<ctype*>( /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002604 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2605 } \
2606 \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002607 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002608 jint mode) { \
2609 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2610 } \
2611 \
2612 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002613 ctype* buf) { /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002614 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2615 } \
2616 \
2617 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2618 const ctype* buf) { \
2619 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2620 }
2621
2622 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2623 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2624 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2625 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2626 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2627 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2628 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2629 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2630#undef PRIMITIVE_ARRAY_FUNCTIONS
2631
2632 static jint MonitorEnter(JNIEnv* env, jobject obj) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002633 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002634 ScopedObjectAccess soa(env);
2635 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2636 JniValueType args[2] = {{.E = env}, {.L = obj}};
2637 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002638 if (obj != nullptr) {
2639 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2640 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002641 JniValueType result;
2642 result.i = baseEnv(env)->MonitorEnter(env, obj);
2643 if (sc.Check(soa, false, "i", &result)) {
2644 return result.i;
2645 }
2646 }
2647 return JNI_ERR;
2648 }
2649
2650 static jint MonitorExit(JNIEnv* env, jobject obj) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002651 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002652 ScopedObjectAccess soa(env);
2653 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2654 JniValueType args[2] = {{.E = env}, {.L = obj}};
2655 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002656 if (obj != nullptr) {
2657 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2658 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002659 JniValueType result;
2660 result.i = baseEnv(env)->MonitorExit(env, obj);
2661 if (sc.Check(soa, false, "i", &result)) {
2662 return result.i;
2663 }
2664 }
2665 return JNI_ERR;
2666 }
2667
2668 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002669 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002670 ScopedObjectAccess soa(env);
2671 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2672 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2673 if (sc.Check(soa, true, "Eap", args)) {
2674 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002675 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2676 if (ptr != nullptr && soa.ForceCopy()) {
2677 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002678 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002679 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002680 if (sc.Check(soa, false, "p", &result)) {
2681 return const_cast<void*>(result.p);
2682 }
2683 }
2684 return nullptr;
2685 }
2686
2687 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002688 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
Ian Rogers68d8b422014-07-17 11:09:10 -07002689 ScopedObjectAccess soa(env);
2690 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2691 sc.CheckNonNull(carray);
2692 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2693 if (sc.Check(soa, true, "Eapr", args)) {
2694 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002695 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002696 }
2697 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2698 JniValueType result;
2699 result.V = nullptr;
2700 sc.Check(soa, false, "V", &result);
2701 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002702 }
2703
2704 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002705 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002706 ScopedObjectAccess soa(env);
2707 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2708 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2709 if (sc.Check(soa, true, "EpJ", args)) {
2710 JniValueType result;
2711 // Note: the validity of address and capacity are checked in the base implementation.
2712 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2713 if (sc.Check(soa, false, "L", &result)) {
2714 return result.L;
2715 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002716 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002717 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002718 }
2719
2720 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002721 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002722 ScopedObjectAccess soa(env);
2723 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2724 JniValueType args[2] = {{.E = env}, {.L = buf}};
2725 if (sc.Check(soa, true, "EL", args)) {
2726 JniValueType result;
2727 // Note: this is implemented in the base environment by a GetLongField which will sanity
2728 // check the type of buf in GetLongField above.
2729 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2730 if (sc.Check(soa, false, "p", &result)) {
2731 return const_cast<void*>(result.p);
2732 }
2733 }
2734 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002735 }
2736
2737 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002738 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
Ian Rogers68d8b422014-07-17 11:09:10 -07002739 ScopedObjectAccess soa(env);
2740 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2741 JniValueType args[2] = {{.E = env}, {.L = buf}};
2742 if (sc.Check(soa, true, "EL", args)) {
2743 JniValueType result;
2744 // Note: this is implemented in the base environment by a GetIntField which will sanity
2745 // check the type of buf in GetIntField above.
2746 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2747 if (sc.Check(soa, false, "J", &result)) {
2748 return result.J;
2749 }
2750 }
2751 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002752 }
2753
2754 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002755 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
Ian Rogers55256cb2017-12-21 17:07:11 -08002756 return reinterpret_cast<JNIEnvExt*>(env)->GetVm();
Ian Rogers68d8b422014-07-17 11:09:10 -07002757 }
2758
2759 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Ian Rogersac4d45a2018-02-15 11:19:01 -08002760 return reinterpret_cast<JNIEnvExt*>(env)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07002761 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002762
2763 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002764 CHECK_ATTACHED_THREAD(function_name, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002765 ScopedObjectAccess soa(env);
2766 ScopedCheck sc(kFlag_Default, function_name);
2767 JniValueType args[2] = {{.E = env}, {.L = obj}};
2768 if (sc.Check(soa, true, "EL", args)) {
2769 JniValueType result;
2770 switch (kind) {
2771 case kGlobal:
2772 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2773 break;
2774 case kLocal:
2775 result.L = baseEnv(env)->NewLocalRef(env, obj);
2776 break;
2777 case kWeakGlobal:
2778 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2779 break;
2780 default:
2781 LOG(FATAL) << "Unexpected reference kind: " << kind;
2782 }
2783 if (sc.Check(soa, false, "L", &result)) {
2784 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002785 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002786 return result.L;
2787 }
2788 }
2789 return nullptr;
2790 }
2791
2792 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002793 CHECK_ATTACHED_THREAD_VOID(function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07002794 ScopedObjectAccess soa(env);
2795 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2796 JniValueType args[2] = {{.E = env}, {.L = obj}};
2797 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002798 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002799 JniValueType result;
2800 switch (kind) {
2801 case kGlobal:
2802 baseEnv(env)->DeleteGlobalRef(env, obj);
2803 break;
2804 case kLocal:
2805 baseEnv(env)->DeleteLocalRef(env, obj);
2806 break;
2807 case kWeakGlobal:
2808 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2809 break;
2810 default:
2811 LOG(FATAL) << "Unexpected reference kind: " << kind;
2812 }
2813 result.V = nullptr;
2814 sc.Check(soa, false, "V", &result);
2815 }
2816 }
2817
2818 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2819 const char* name, const char* sig, bool is_static) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002820 CHECK_ATTACHED_THREAD(function_name, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002821 ScopedObjectAccess soa(env);
2822 ScopedCheck sc(kFlag_Default, function_name);
2823 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2824 if (sc.Check(soa, true, "Ecuu", args)) {
2825 JniValueType result;
2826 if (is_static) {
2827 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2828 } else {
2829 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2830 }
2831 if (sc.Check(soa, false, "m", &result)) {
2832 return result.m;
2833 }
2834 }
2835 return nullptr;
2836 }
2837
2838 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2839 const char* name, const char* sig, bool is_static) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002840 CHECK_ATTACHED_THREAD(function_name, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002841 ScopedObjectAccess soa(env);
2842 ScopedCheck sc(kFlag_Default, function_name);
2843 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2844 if (sc.Check(soa, true, "Ecuu", args)) {
2845 JniValueType result;
2846 if (is_static) {
2847 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2848 } else {
2849 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2850 }
2851 if (sc.Check(soa, false, "f", &result)) {
2852 return result.f;
2853 }
2854 }
2855 return nullptr;
2856 }
2857
2858 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2859 bool is_static, Primitive::Type type) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002860 CHECK_ATTACHED_THREAD(function_name, JniValueType());
Ian Rogers68d8b422014-07-17 11:09:10 -07002861 ScopedObjectAccess soa(env);
2862 ScopedCheck sc(kFlag_Default, function_name);
2863 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2864 JniValueType result;
2865 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2866 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2867 const char* result_check = nullptr;
2868 switch (type) {
2869 case Primitive::kPrimNot:
2870 if (is_static) {
2871 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2872 } else {
2873 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2874 }
2875 result_check = "L";
2876 break;
2877 case Primitive::kPrimBoolean:
2878 if (is_static) {
2879 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2880 } else {
2881 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2882 }
2883 result_check = "Z";
2884 break;
2885 case Primitive::kPrimByte:
2886 if (is_static) {
2887 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2888 } else {
2889 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2890 }
2891 result_check = "B";
2892 break;
2893 case Primitive::kPrimChar:
2894 if (is_static) {
2895 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2896 } else {
2897 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2898 }
2899 result_check = "C";
2900 break;
2901 case Primitive::kPrimShort:
2902 if (is_static) {
2903 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2904 } else {
2905 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2906 }
2907 result_check = "S";
2908 break;
2909 case Primitive::kPrimInt:
2910 if (is_static) {
2911 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2912 } else {
2913 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2914 }
2915 result_check = "I";
2916 break;
2917 case Primitive::kPrimLong:
2918 if (is_static) {
2919 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2920 } else {
2921 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2922 }
2923 result_check = "J";
2924 break;
2925 case Primitive::kPrimFloat:
2926 if (is_static) {
2927 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2928 } else {
2929 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2930 }
2931 result_check = "F";
2932 break;
2933 case Primitive::kPrimDouble:
2934 if (is_static) {
2935 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2936 } else {
2937 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2938 }
2939 result_check = "D";
2940 break;
2941 case Primitive::kPrimVoid:
2942 LOG(FATAL) << "Unexpected type: " << type;
2943 break;
2944 }
2945 if (sc.Check(soa, false, result_check, &result)) {
2946 return result;
2947 }
2948 }
2949 result.J = 0;
2950 return result;
2951 }
2952
2953 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2954 bool is_static, Primitive::Type type, JniValueType value) {
Andreas Gampe69944c92018-04-17 11:08:23 -07002955 CHECK_ATTACHED_THREAD_VOID(function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07002956 ScopedObjectAccess soa(env);
2957 ScopedCheck sc(kFlag_Default, function_name);
2958 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2959 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2960 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2961 if (sc.Check(soa, true, sig, args) &&
2962 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2963 switch (type) {
2964 case Primitive::kPrimNot:
2965 if (is_static) {
2966 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2967 } else {
2968 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2969 }
2970 break;
2971 case Primitive::kPrimBoolean:
2972 if (is_static) {
2973 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2974 } else {
2975 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2976 }
2977 break;
2978 case Primitive::kPrimByte:
2979 if (is_static) {
2980 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2981 } else {
2982 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2983 }
2984 break;
2985 case Primitive::kPrimChar:
2986 if (is_static) {
2987 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2988 } else {
2989 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2990 }
2991 break;
2992 case Primitive::kPrimShort:
2993 if (is_static) {
2994 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2995 } else {
2996 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2997 }
2998 break;
2999 case Primitive::kPrimInt:
3000 if (is_static) {
3001 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
3002 } else {
3003 baseEnv(env)->SetIntField(env, obj, fid, value.I);
3004 }
3005 break;
3006 case Primitive::kPrimLong:
3007 if (is_static) {
3008 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
3009 } else {
3010 baseEnv(env)->SetLongField(env, obj, fid, value.J);
3011 }
3012 break;
3013 case Primitive::kPrimFloat:
3014 if (is_static) {
3015 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
3016 } else {
3017 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
3018 }
3019 break;
3020 case Primitive::kPrimDouble:
3021 if (is_static) {
3022 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
3023 } else {
3024 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
3025 }
3026 break;
3027 case Primitive::kPrimVoid:
3028 LOG(FATAL) << "Unexpected type: " << type;
3029 break;
3030 }
3031 JniValueType result;
3032 result.V = nullptr;
3033 sc.Check(soa, false, "V", &result);
3034 }
3035 }
3036
3037 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
Alex Light48ffe062015-08-19 15:23:23 -07003038 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07003039 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003040 bool checked;
3041 switch (invoke) {
3042 case kVirtual: {
3043 DCHECK(c == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07003044 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
3045 checked = sc.Check(soa, true, "ELm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07003046 break;
3047 }
3048 case kDirect: {
Alex Light48ffe062015-08-19 15:23:23 -07003049 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
3050 checked = sc.Check(soa, true, "ELcm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07003051 break;
3052 }
3053 case kStatic: {
3054 DCHECK(obj == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07003055 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
3056 checked = sc.Check(soa, true, "Ecm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07003057 break;
3058 }
3059 default:
3060 LOG(FATAL) << "Unexpected invoke: " << invoke;
3061 checked = false;
3062 break;
3063 }
3064 return checked;
3065 }
3066
3067 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3068 jmethodID mid, jvalue* vargs, Primitive::Type type,
3069 InvokeType invoke) {
Andreas Gampe69944c92018-04-17 11:08:23 -07003070 CHECK_ATTACHED_THREAD(function_name, JniValueType());
Ian Rogers68d8b422014-07-17 11:09:10 -07003071 ScopedObjectAccess soa(env);
3072 ScopedCheck sc(kFlag_Default, function_name);
3073 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003074 VarArgs rest(mid, vargs);
3075 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003076 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3077 const char* result_check;
3078 switch (type) {
3079 case Primitive::kPrimNot:
3080 result_check = "L";
3081 switch (invoke) {
3082 case kVirtual:
3083 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
3084 break;
3085 case kDirect:
3086 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
3087 break;
3088 case kStatic:
3089 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
3090 break;
3091 default:
3092 break;
3093 }
3094 break;
3095 case Primitive::kPrimBoolean:
3096 result_check = "Z";
3097 switch (invoke) {
3098 case kVirtual:
3099 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
3100 break;
3101 case kDirect:
3102 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
3103 break;
3104 case kStatic:
3105 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
3106 break;
3107 default:
3108 break;
3109 }
3110 break;
3111 case Primitive::kPrimByte:
3112 result_check = "B";
3113 switch (invoke) {
3114 case kVirtual:
3115 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
3116 break;
3117 case kDirect:
3118 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
3119 break;
3120 case kStatic:
3121 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
3122 break;
3123 default:
3124 break;
3125 }
3126 break;
3127 case Primitive::kPrimChar:
3128 result_check = "C";
3129 switch (invoke) {
3130 case kVirtual:
3131 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
3132 break;
3133 case kDirect:
3134 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
3135 break;
3136 case kStatic:
3137 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
3138 break;
3139 default:
3140 break;
3141 }
3142 break;
3143 case Primitive::kPrimShort:
3144 result_check = "S";
3145 switch (invoke) {
3146 case kVirtual:
3147 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
3148 break;
3149 case kDirect:
3150 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
3151 break;
3152 case kStatic:
3153 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
3154 break;
3155 default:
3156 break;
3157 }
3158 break;
3159 case Primitive::kPrimInt:
3160 result_check = "I";
3161 switch (invoke) {
3162 case kVirtual:
3163 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
3164 break;
3165 case kDirect:
3166 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
3167 break;
3168 case kStatic:
3169 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
3170 break;
3171 default:
3172 break;
3173 }
3174 break;
3175 case Primitive::kPrimLong:
3176 result_check = "J";
3177 switch (invoke) {
3178 case kVirtual:
3179 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
3180 break;
3181 case kDirect:
3182 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3183 break;
3184 case kStatic:
3185 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3186 break;
3187 default:
3188 break;
3189 }
3190 break;
3191 case Primitive::kPrimFloat:
3192 result_check = "F";
3193 switch (invoke) {
3194 case kVirtual:
3195 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3196 break;
3197 case kDirect:
3198 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3199 break;
3200 case kStatic:
3201 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3202 break;
3203 default:
3204 break;
3205 }
3206 break;
3207 case Primitive::kPrimDouble:
3208 result_check = "D";
3209 switch (invoke) {
3210 case kVirtual:
3211 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3212 break;
3213 case kDirect:
3214 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3215 break;
3216 case kStatic:
3217 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3218 break;
3219 default:
3220 break;
3221 }
3222 break;
3223 case Primitive::kPrimVoid:
3224 result_check = "V";
3225 result.V = nullptr;
3226 switch (invoke) {
3227 case kVirtual:
3228 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3229 break;
3230 case kDirect:
3231 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3232 break;
3233 case kStatic:
3234 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3235 break;
3236 default:
3237 LOG(FATAL) << "Unexpected invoke: " << invoke;
3238 }
3239 break;
3240 default:
3241 LOG(FATAL) << "Unexpected return type: " << type;
3242 result_check = nullptr;
3243 }
3244 if (sc.Check(soa, false, result_check, &result)) {
3245 return result;
3246 }
3247 }
3248 result.J = 0;
3249 return result;
3250 }
3251
3252 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3253 jmethodID mid, va_list vargs, Primitive::Type type,
3254 InvokeType invoke) {
Andreas Gampe69944c92018-04-17 11:08:23 -07003255 CHECK_ATTACHED_THREAD(function_name, JniValueType());
Ian Rogers68d8b422014-07-17 11:09:10 -07003256 ScopedObjectAccess soa(env);
3257 ScopedCheck sc(kFlag_Default, function_name);
3258 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003259 VarArgs rest(mid, vargs);
3260 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003261 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3262 const char* result_check;
3263 switch (type) {
3264 case Primitive::kPrimNot:
3265 result_check = "L";
3266 switch (invoke) {
3267 case kVirtual:
3268 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3269 break;
3270 case kDirect:
3271 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3272 break;
3273 case kStatic:
3274 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3275 break;
3276 default:
3277 LOG(FATAL) << "Unexpected invoke: " << invoke;
3278 }
3279 break;
3280 case Primitive::kPrimBoolean:
3281 result_check = "Z";
3282 switch (invoke) {
3283 case kVirtual:
3284 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3285 break;
3286 case kDirect:
3287 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3288 break;
3289 case kStatic:
3290 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3291 break;
3292 default:
3293 LOG(FATAL) << "Unexpected invoke: " << invoke;
3294 }
3295 break;
3296 case Primitive::kPrimByte:
3297 result_check = "B";
3298 switch (invoke) {
3299 case kVirtual:
3300 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3301 break;
3302 case kDirect:
3303 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3304 break;
3305 case kStatic:
3306 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3307 break;
3308 default:
3309 LOG(FATAL) << "Unexpected invoke: " << invoke;
3310 }
3311 break;
3312 case Primitive::kPrimChar:
3313 result_check = "C";
3314 switch (invoke) {
3315 case kVirtual:
3316 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3317 break;
3318 case kDirect:
3319 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3320 break;
3321 case kStatic:
3322 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3323 break;
3324 default:
3325 LOG(FATAL) << "Unexpected invoke: " << invoke;
3326 }
3327 break;
3328 case Primitive::kPrimShort:
3329 result_check = "S";
3330 switch (invoke) {
3331 case kVirtual:
3332 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3333 break;
3334 case kDirect:
3335 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3336 break;
3337 case kStatic:
3338 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3339 break;
3340 default:
3341 LOG(FATAL) << "Unexpected invoke: " << invoke;
3342 }
3343 break;
3344 case Primitive::kPrimInt:
3345 result_check = "I";
3346 switch (invoke) {
3347 case kVirtual:
3348 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3349 break;
3350 case kDirect:
3351 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3352 break;
3353 case kStatic:
3354 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3355 break;
3356 default:
3357 LOG(FATAL) << "Unexpected invoke: " << invoke;
3358 }
3359 break;
3360 case Primitive::kPrimLong:
3361 result_check = "J";
3362 switch (invoke) {
3363 case kVirtual:
3364 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3365 break;
3366 case kDirect:
3367 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3368 break;
3369 case kStatic:
3370 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3371 break;
3372 default:
3373 LOG(FATAL) << "Unexpected invoke: " << invoke;
3374 }
3375 break;
3376 case Primitive::kPrimFloat:
3377 result_check = "F";
3378 switch (invoke) {
3379 case kVirtual:
3380 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3381 break;
3382 case kDirect:
3383 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3384 break;
3385 case kStatic:
3386 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3387 break;
3388 default:
3389 LOG(FATAL) << "Unexpected invoke: " << invoke;
3390 }
3391 break;
3392 case Primitive::kPrimDouble:
3393 result_check = "D";
3394 switch (invoke) {
3395 case kVirtual:
3396 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3397 break;
3398 case kDirect:
3399 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3400 break;
3401 case kStatic:
3402 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3403 break;
3404 default:
3405 LOG(FATAL) << "Unexpected invoke: " << invoke;
3406 }
3407 break;
3408 case Primitive::kPrimVoid:
3409 result_check = "V";
3410 result.V = nullptr;
3411 switch (invoke) {
3412 case kVirtual:
3413 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3414 break;
3415 case kDirect:
3416 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3417 break;
3418 case kStatic:
3419 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3420 break;
3421 default:
3422 LOG(FATAL) << "Unexpected invoke: " << invoke;
3423 }
3424 break;
3425 default:
3426 LOG(FATAL) << "Unexpected return type: " << type;
3427 result_check = nullptr;
3428 }
3429 if (sc.Check(soa, false, result_check, &result)) {
3430 return result;
3431 }
3432 }
3433 result.J = 0;
3434 return result;
3435 }
3436
3437 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3438 jboolean* is_copy, bool utf, bool critical) {
Andreas Gampe69944c92018-04-17 11:08:23 -07003439 CHECK_ATTACHED_THREAD(function_name, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003440 ScopedObjectAccess soa(env);
3441 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3442 ScopedCheck sc(flags, function_name);
3443 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3444 if (sc.Check(soa, true, "Esp", args)) {
3445 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003446 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003447 if (utf) {
3448 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003449 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3450 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003451 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003452 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3453 baseEnv(env)->GetStringChars(env, string, is_copy));
3454 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003455 }
3456 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003457 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003458 if (utf) {
3459 size_t length_in_bytes = strlen(result.u) + 1;
3460 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003461 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003462 } else {
3463 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3464 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003465 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003466 }
3467 if (is_copy != nullptr) {
3468 *is_copy = JNI_TRUE;
3469 }
3470 }
3471 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3472 return utf ? result.u : result.p;
3473 }
3474 }
3475 return nullptr;
3476 }
3477
3478 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3479 const void* chars, bool utf, bool critical) {
Andreas Gampe69944c92018-04-17 11:08:23 -07003480 CHECK_ATTACHED_THREAD_VOID(function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003481 ScopedObjectAccess soa(env);
3482 int flags = kFlag_ExcepOkay | kFlag_Release;
3483 if (critical) {
3484 flags |= kFlag_CritRelease;
3485 }
3486 ScopedCheck sc(flags, function_name);
3487 sc.CheckNonNull(chars);
3488 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3489 if (force_copy_ok && soa.ForceCopy()) {
3490 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3491 }
3492 if (force_copy_ok) {
3493 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3494 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3495 if (utf) {
3496 CHECK(!critical);
3497 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3498 } else {
3499 if (critical) {
3500 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3501 } else {
3502 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3503 }
3504 }
3505 JniValueType result;
3506 sc.Check(soa, false, "V", &result);
3507 }
3508 }
3509 }
3510
3511 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3512 Primitive::Type type) {
Andreas Gampe69944c92018-04-17 11:08:23 -07003513 CHECK_ATTACHED_THREAD(function_name, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003514 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003515 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003516 JniValueType args[2] = {{.E = env}, {.z = length}};
3517 if (sc.Check(soa, true, "Ez", args)) {
3518 JniValueType result;
3519 switch (type) {
3520 case Primitive::kPrimBoolean:
3521 result.a = baseEnv(env)->NewBooleanArray(env, length);
3522 break;
3523 case Primitive::kPrimByte:
3524 result.a = baseEnv(env)->NewByteArray(env, length);
3525 break;
3526 case Primitive::kPrimChar:
3527 result.a = baseEnv(env)->NewCharArray(env, length);
3528 break;
3529 case Primitive::kPrimShort:
3530 result.a = baseEnv(env)->NewShortArray(env, length);
3531 break;
3532 case Primitive::kPrimInt:
3533 result.a = baseEnv(env)->NewIntArray(env, length);
3534 break;
3535 case Primitive::kPrimLong:
3536 result.a = baseEnv(env)->NewLongArray(env, length);
3537 break;
3538 case Primitive::kPrimFloat:
3539 result.a = baseEnv(env)->NewFloatArray(env, length);
3540 break;
3541 case Primitive::kPrimDouble:
3542 result.a = baseEnv(env)->NewDoubleArray(env, length);
3543 break;
3544 default:
3545 LOG(FATAL) << "Unexpected primitive type: " << type;
3546 }
3547 if (sc.Check(soa, false, "a", &result)) {
3548 return result.a;
3549 }
3550 }
3551 return nullptr;
3552 }
3553
3554 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3555 JNIEnv* env, jarray array, jboolean* is_copy) {
Andreas Gampe69944c92018-04-17 11:08:23 -07003556 CHECK_ATTACHED_THREAD(function_name, nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003557 ScopedObjectAccess soa(env);
3558 ScopedCheck sc(kFlag_Default, function_name);
3559 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3560 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3561 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003562 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003563 switch (type) {
3564 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003565 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3566 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003567 break;
3568 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003569 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003570 break;
3571 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003572 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003573 break;
3574 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003575 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003576 break;
3577 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003578 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003579 break;
3580 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003581 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003582 break;
3583 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003584 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003585 break;
3586 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003587 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003588 break;
3589 default:
3590 LOG(FATAL) << "Unexpected primitive type: " << type;
3591 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003592 if (ptr != nullptr && soa.ForceCopy()) {
3593 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003594 if (is_copy != nullptr) {
3595 *is_copy = JNI_TRUE;
3596 }
3597 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003598 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003599 if (sc.Check(soa, false, "p", &result)) {
3600 return const_cast<void*>(result.p);
3601 }
3602 }
3603 return nullptr;
3604 }
3605
3606 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3607 JNIEnv* env, jarray array, void* elems, jint mode) {
Andreas Gampe69944c92018-04-17 11:08:23 -07003608 CHECK_ATTACHED_THREAD_VOID(function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003609 ScopedObjectAccess soa(env);
3610 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3611 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3612 if (soa.ForceCopy()) {
3613 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3614 }
3615 if (!soa.ForceCopy() || elems != nullptr) {
3616 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3617 if (sc.Check(soa, true, "Eapr", args)) {
3618 switch (type) {
3619 case Primitive::kPrimBoolean:
3620 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3621 reinterpret_cast<jboolean*>(elems), mode);
3622 break;
3623 case Primitive::kPrimByte:
3624 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3625 reinterpret_cast<jbyte*>(elems), mode);
3626 break;
3627 case Primitive::kPrimChar:
3628 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3629 reinterpret_cast<jchar*>(elems), mode);
3630 break;
3631 case Primitive::kPrimShort:
3632 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3633 reinterpret_cast<jshort*>(elems), mode);
3634 break;
3635 case Primitive::kPrimInt:
3636 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3637 reinterpret_cast<jint*>(elems), mode);
3638 break;
3639 case Primitive::kPrimLong:
3640 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3641 reinterpret_cast<jlong*>(elems), mode);
3642 break;
3643 case Primitive::kPrimFloat:
3644 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3645 reinterpret_cast<jfloat*>(elems), mode);
3646 break;
3647 case Primitive::kPrimDouble:
3648 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3649 reinterpret_cast<jdouble*>(elems), mode);
3650 break;
3651 default:
3652 LOG(FATAL) << "Unexpected primitive type: " << type;
3653 }
3654 JniValueType result;
3655 result.V = nullptr;
3656 sc.Check(soa, false, "V", &result);
3657 }
3658 }
3659 }
3660 }
3661
3662 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3663 jarray array, jsize start, jsize len, void* buf) {
Andreas Gampe69944c92018-04-17 11:08:23 -07003664 CHECK_ATTACHED_THREAD_VOID(function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003665 ScopedObjectAccess soa(env);
3666 ScopedCheck sc(kFlag_Default, function_name);
3667 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3668 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3669 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3670 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3671 switch (type) {
3672 case Primitive::kPrimBoolean:
3673 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3674 reinterpret_cast<jboolean*>(buf));
3675 break;
3676 case Primitive::kPrimByte:
3677 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3678 reinterpret_cast<jbyte*>(buf));
3679 break;
3680 case Primitive::kPrimChar:
3681 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3682 reinterpret_cast<jchar*>(buf));
3683 break;
3684 case Primitive::kPrimShort:
3685 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3686 reinterpret_cast<jshort*>(buf));
3687 break;
3688 case Primitive::kPrimInt:
3689 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3690 reinterpret_cast<jint*>(buf));
3691 break;
3692 case Primitive::kPrimLong:
3693 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3694 reinterpret_cast<jlong*>(buf));
3695 break;
3696 case Primitive::kPrimFloat:
3697 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3698 reinterpret_cast<jfloat*>(buf));
3699 break;
3700 case Primitive::kPrimDouble:
3701 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3702 reinterpret_cast<jdouble*>(buf));
3703 break;
3704 default:
3705 LOG(FATAL) << "Unexpected primitive type: " << type;
3706 }
3707 JniValueType result;
3708 result.V = nullptr;
3709 sc.Check(soa, false, "V", &result);
3710 }
3711 }
3712
3713 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3714 jarray array, jsize start, jsize len, const void* buf) {
Andreas Gampe69944c92018-04-17 11:08:23 -07003715 CHECK_ATTACHED_THREAD_VOID(function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003716 ScopedObjectAccess soa(env);
3717 ScopedCheck sc(kFlag_Default, function_name);
3718 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3719 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3720 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3721 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3722 switch (type) {
3723 case Primitive::kPrimBoolean:
3724 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3725 reinterpret_cast<const jboolean*>(buf));
3726 break;
3727 case Primitive::kPrimByte:
3728 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3729 reinterpret_cast<const jbyte*>(buf));
3730 break;
3731 case Primitive::kPrimChar:
3732 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3733 reinterpret_cast<const jchar*>(buf));
3734 break;
3735 case Primitive::kPrimShort:
3736 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3737 reinterpret_cast<const jshort*>(buf));
3738 break;
3739 case Primitive::kPrimInt:
3740 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3741 reinterpret_cast<const jint*>(buf));
3742 break;
3743 case Primitive::kPrimLong:
3744 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3745 reinterpret_cast<const jlong*>(buf));
3746 break;
3747 case Primitive::kPrimFloat:
3748 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3749 reinterpret_cast<const jfloat*>(buf));
3750 break;
3751 case Primitive::kPrimDouble:
3752 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3753 reinterpret_cast<const jdouble*>(buf));
3754 break;
3755 default:
3756 LOG(FATAL) << "Unexpected primitive type: " << type;
3757 }
3758 JniValueType result;
3759 result.V = nullptr;
3760 sc.Check(soa, false, "V", &result);
3761 }
3762 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003763};
3764
3765const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003766 nullptr, // reserved0.
3767 nullptr, // reserved1.
3768 nullptr, // reserved2.
3769 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003770 CheckJNI::GetVersion,
3771 CheckJNI::DefineClass,
3772 CheckJNI::FindClass,
3773 CheckJNI::FromReflectedMethod,
3774 CheckJNI::FromReflectedField,
3775 CheckJNI::ToReflectedMethod,
3776 CheckJNI::GetSuperclass,
3777 CheckJNI::IsAssignableFrom,
3778 CheckJNI::ToReflectedField,
3779 CheckJNI::Throw,
3780 CheckJNI::ThrowNew,
3781 CheckJNI::ExceptionOccurred,
3782 CheckJNI::ExceptionDescribe,
3783 CheckJNI::ExceptionClear,
3784 CheckJNI::FatalError,
3785 CheckJNI::PushLocalFrame,
3786 CheckJNI::PopLocalFrame,
3787 CheckJNI::NewGlobalRef,
3788 CheckJNI::DeleteGlobalRef,
3789 CheckJNI::DeleteLocalRef,
3790 CheckJNI::IsSameObject,
3791 CheckJNI::NewLocalRef,
3792 CheckJNI::EnsureLocalCapacity,
3793 CheckJNI::AllocObject,
3794 CheckJNI::NewObject,
3795 CheckJNI::NewObjectV,
3796 CheckJNI::NewObjectA,
3797 CheckJNI::GetObjectClass,
3798 CheckJNI::IsInstanceOf,
3799 CheckJNI::GetMethodID,
3800 CheckJNI::CallObjectMethod,
3801 CheckJNI::CallObjectMethodV,
3802 CheckJNI::CallObjectMethodA,
3803 CheckJNI::CallBooleanMethod,
3804 CheckJNI::CallBooleanMethodV,
3805 CheckJNI::CallBooleanMethodA,
3806 CheckJNI::CallByteMethod,
3807 CheckJNI::CallByteMethodV,
3808 CheckJNI::CallByteMethodA,
3809 CheckJNI::CallCharMethod,
3810 CheckJNI::CallCharMethodV,
3811 CheckJNI::CallCharMethodA,
3812 CheckJNI::CallShortMethod,
3813 CheckJNI::CallShortMethodV,
3814 CheckJNI::CallShortMethodA,
3815 CheckJNI::CallIntMethod,
3816 CheckJNI::CallIntMethodV,
3817 CheckJNI::CallIntMethodA,
3818 CheckJNI::CallLongMethod,
3819 CheckJNI::CallLongMethodV,
3820 CheckJNI::CallLongMethodA,
3821 CheckJNI::CallFloatMethod,
3822 CheckJNI::CallFloatMethodV,
3823 CheckJNI::CallFloatMethodA,
3824 CheckJNI::CallDoubleMethod,
3825 CheckJNI::CallDoubleMethodV,
3826 CheckJNI::CallDoubleMethodA,
3827 CheckJNI::CallVoidMethod,
3828 CheckJNI::CallVoidMethodV,
3829 CheckJNI::CallVoidMethodA,
3830 CheckJNI::CallNonvirtualObjectMethod,
3831 CheckJNI::CallNonvirtualObjectMethodV,
3832 CheckJNI::CallNonvirtualObjectMethodA,
3833 CheckJNI::CallNonvirtualBooleanMethod,
3834 CheckJNI::CallNonvirtualBooleanMethodV,
3835 CheckJNI::CallNonvirtualBooleanMethodA,
3836 CheckJNI::CallNonvirtualByteMethod,
3837 CheckJNI::CallNonvirtualByteMethodV,
3838 CheckJNI::CallNonvirtualByteMethodA,
3839 CheckJNI::CallNonvirtualCharMethod,
3840 CheckJNI::CallNonvirtualCharMethodV,
3841 CheckJNI::CallNonvirtualCharMethodA,
3842 CheckJNI::CallNonvirtualShortMethod,
3843 CheckJNI::CallNonvirtualShortMethodV,
3844 CheckJNI::CallNonvirtualShortMethodA,
3845 CheckJNI::CallNonvirtualIntMethod,
3846 CheckJNI::CallNonvirtualIntMethodV,
3847 CheckJNI::CallNonvirtualIntMethodA,
3848 CheckJNI::CallNonvirtualLongMethod,
3849 CheckJNI::CallNonvirtualLongMethodV,
3850 CheckJNI::CallNonvirtualLongMethodA,
3851 CheckJNI::CallNonvirtualFloatMethod,
3852 CheckJNI::CallNonvirtualFloatMethodV,
3853 CheckJNI::CallNonvirtualFloatMethodA,
3854 CheckJNI::CallNonvirtualDoubleMethod,
3855 CheckJNI::CallNonvirtualDoubleMethodV,
3856 CheckJNI::CallNonvirtualDoubleMethodA,
3857 CheckJNI::CallNonvirtualVoidMethod,
3858 CheckJNI::CallNonvirtualVoidMethodV,
3859 CheckJNI::CallNonvirtualVoidMethodA,
3860 CheckJNI::GetFieldID,
3861 CheckJNI::GetObjectField,
3862 CheckJNI::GetBooleanField,
3863 CheckJNI::GetByteField,
3864 CheckJNI::GetCharField,
3865 CheckJNI::GetShortField,
3866 CheckJNI::GetIntField,
3867 CheckJNI::GetLongField,
3868 CheckJNI::GetFloatField,
3869 CheckJNI::GetDoubleField,
3870 CheckJNI::SetObjectField,
3871 CheckJNI::SetBooleanField,
3872 CheckJNI::SetByteField,
3873 CheckJNI::SetCharField,
3874 CheckJNI::SetShortField,
3875 CheckJNI::SetIntField,
3876 CheckJNI::SetLongField,
3877 CheckJNI::SetFloatField,
3878 CheckJNI::SetDoubleField,
3879 CheckJNI::GetStaticMethodID,
3880 CheckJNI::CallStaticObjectMethod,
3881 CheckJNI::CallStaticObjectMethodV,
3882 CheckJNI::CallStaticObjectMethodA,
3883 CheckJNI::CallStaticBooleanMethod,
3884 CheckJNI::CallStaticBooleanMethodV,
3885 CheckJNI::CallStaticBooleanMethodA,
3886 CheckJNI::CallStaticByteMethod,
3887 CheckJNI::CallStaticByteMethodV,
3888 CheckJNI::CallStaticByteMethodA,
3889 CheckJNI::CallStaticCharMethod,
3890 CheckJNI::CallStaticCharMethodV,
3891 CheckJNI::CallStaticCharMethodA,
3892 CheckJNI::CallStaticShortMethod,
3893 CheckJNI::CallStaticShortMethodV,
3894 CheckJNI::CallStaticShortMethodA,
3895 CheckJNI::CallStaticIntMethod,
3896 CheckJNI::CallStaticIntMethodV,
3897 CheckJNI::CallStaticIntMethodA,
3898 CheckJNI::CallStaticLongMethod,
3899 CheckJNI::CallStaticLongMethodV,
3900 CheckJNI::CallStaticLongMethodA,
3901 CheckJNI::CallStaticFloatMethod,
3902 CheckJNI::CallStaticFloatMethodV,
3903 CheckJNI::CallStaticFloatMethodA,
3904 CheckJNI::CallStaticDoubleMethod,
3905 CheckJNI::CallStaticDoubleMethodV,
3906 CheckJNI::CallStaticDoubleMethodA,
3907 CheckJNI::CallStaticVoidMethod,
3908 CheckJNI::CallStaticVoidMethodV,
3909 CheckJNI::CallStaticVoidMethodA,
3910 CheckJNI::GetStaticFieldID,
3911 CheckJNI::GetStaticObjectField,
3912 CheckJNI::GetStaticBooleanField,
3913 CheckJNI::GetStaticByteField,
3914 CheckJNI::GetStaticCharField,
3915 CheckJNI::GetStaticShortField,
3916 CheckJNI::GetStaticIntField,
3917 CheckJNI::GetStaticLongField,
3918 CheckJNI::GetStaticFloatField,
3919 CheckJNI::GetStaticDoubleField,
3920 CheckJNI::SetStaticObjectField,
3921 CheckJNI::SetStaticBooleanField,
3922 CheckJNI::SetStaticByteField,
3923 CheckJNI::SetStaticCharField,
3924 CheckJNI::SetStaticShortField,
3925 CheckJNI::SetStaticIntField,
3926 CheckJNI::SetStaticLongField,
3927 CheckJNI::SetStaticFloatField,
3928 CheckJNI::SetStaticDoubleField,
3929 CheckJNI::NewString,
3930 CheckJNI::GetStringLength,
3931 CheckJNI::GetStringChars,
3932 CheckJNI::ReleaseStringChars,
3933 CheckJNI::NewStringUTF,
3934 CheckJNI::GetStringUTFLength,
3935 CheckJNI::GetStringUTFChars,
3936 CheckJNI::ReleaseStringUTFChars,
3937 CheckJNI::GetArrayLength,
3938 CheckJNI::NewObjectArray,
3939 CheckJNI::GetObjectArrayElement,
3940 CheckJNI::SetObjectArrayElement,
3941 CheckJNI::NewBooleanArray,
3942 CheckJNI::NewByteArray,
3943 CheckJNI::NewCharArray,
3944 CheckJNI::NewShortArray,
3945 CheckJNI::NewIntArray,
3946 CheckJNI::NewLongArray,
3947 CheckJNI::NewFloatArray,
3948 CheckJNI::NewDoubleArray,
3949 CheckJNI::GetBooleanArrayElements,
3950 CheckJNI::GetByteArrayElements,
3951 CheckJNI::GetCharArrayElements,
3952 CheckJNI::GetShortArrayElements,
3953 CheckJNI::GetIntArrayElements,
3954 CheckJNI::GetLongArrayElements,
3955 CheckJNI::GetFloatArrayElements,
3956 CheckJNI::GetDoubleArrayElements,
3957 CheckJNI::ReleaseBooleanArrayElements,
3958 CheckJNI::ReleaseByteArrayElements,
3959 CheckJNI::ReleaseCharArrayElements,
3960 CheckJNI::ReleaseShortArrayElements,
3961 CheckJNI::ReleaseIntArrayElements,
3962 CheckJNI::ReleaseLongArrayElements,
3963 CheckJNI::ReleaseFloatArrayElements,
3964 CheckJNI::ReleaseDoubleArrayElements,
3965 CheckJNI::GetBooleanArrayRegion,
3966 CheckJNI::GetByteArrayRegion,
3967 CheckJNI::GetCharArrayRegion,
3968 CheckJNI::GetShortArrayRegion,
3969 CheckJNI::GetIntArrayRegion,
3970 CheckJNI::GetLongArrayRegion,
3971 CheckJNI::GetFloatArrayRegion,
3972 CheckJNI::GetDoubleArrayRegion,
3973 CheckJNI::SetBooleanArrayRegion,
3974 CheckJNI::SetByteArrayRegion,
3975 CheckJNI::SetCharArrayRegion,
3976 CheckJNI::SetShortArrayRegion,
3977 CheckJNI::SetIntArrayRegion,
3978 CheckJNI::SetLongArrayRegion,
3979 CheckJNI::SetFloatArrayRegion,
3980 CheckJNI::SetDoubleArrayRegion,
3981 CheckJNI::RegisterNatives,
3982 CheckJNI::UnregisterNatives,
3983 CheckJNI::MonitorEnter,
3984 CheckJNI::MonitorExit,
3985 CheckJNI::GetJavaVM,
3986 CheckJNI::GetStringRegion,
3987 CheckJNI::GetStringUTFRegion,
3988 CheckJNI::GetPrimitiveArrayCritical,
3989 CheckJNI::ReleasePrimitiveArrayCritical,
3990 CheckJNI::GetStringCritical,
3991 CheckJNI::ReleaseStringCritical,
3992 CheckJNI::NewWeakGlobalRef,
3993 CheckJNI::DeleteWeakGlobalRef,
3994 CheckJNI::ExceptionCheck,
3995 CheckJNI::NewDirectByteBuffer,
3996 CheckJNI::GetDirectBufferAddress,
3997 CheckJNI::GetDirectBufferCapacity,
3998 CheckJNI::GetObjectRefType,
3999};
4000
Elliott Hughesa2501992011-08-26 19:39:54 -07004001class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08004002 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07004003 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07004004 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
4005 JniValueType args[1] = {{.v = vm}};
4006 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
4007 JniValueType result;
4008 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08004009 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
4010 // which will delete the JavaVMExt.
4011 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07004012 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07004013 }
4014
4015 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07004016 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4017 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
4018 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
4019 JniValueType result;
4020 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
4021 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4022 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07004023 }
4024
4025 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07004026 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4027 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
4028 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
4029 JniValueType result;
4030 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
4031 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4032 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07004033 }
4034
4035 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07004036 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4037 JniValueType args[1] = {{.v = vm}};
4038 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
4039 JniValueType result;
4040 result.i = BaseVm(vm)->DetachCurrentThread(vm);
4041 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4042 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07004043 }
4044
Ian Rogers68d8b422014-07-17 11:09:10 -07004045 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
4046 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4047 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
4048 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
4049 JniValueType result;
4050 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
4051 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4052 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07004053 }
4054
4055 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07004056 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
4057 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07004058 }
4059};
4060
4061const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08004062 nullptr, // reserved0
4063 nullptr, // reserved1
4064 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07004065 CheckJII::DestroyJavaVM,
4066 CheckJII::AttachCurrentThread,
4067 CheckJII::DetachCurrentThread,
4068 CheckJII::GetEnv,
4069 CheckJII::AttachCurrentThreadAsDaemon
4070};
4071
Ian Rogersac4d45a2018-02-15 11:19:01 -08004072} // anonymous namespace
4073
4074const JNINativeInterface* GetCheckJniNativeInterface() {
4075 return &gCheckNativeInterface;
4076}
4077
Elliott Hughesa2501992011-08-26 19:39:54 -07004078const JNIInvokeInterface* GetCheckJniInvokeInterface() {
4079 return &gCheckInvokeInterface;
4080}
4081
4082} // namespace art