blob: 900ce0eac3de4dad37120c330ddfccf641c67755 [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"
Ian Rogers68d8b422014-07-17 11:09:10 -070037#include "java_vm_ext.h"
Andreas Gampe277ccbd2014-11-03 21:36:10 -080038#include "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
Elliott Hughesa2501992011-08-26 19:39:54 -0700276class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800277 public:
Ian Rogers55256cb2017-12-21 17:07:11 -0800278 ScopedCheck(uint16_t flags, const char* functionName, bool has_method = true)
279 : function_name_(functionName), indent_(0), flags_(flags), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700280 }
281
Ian Rogers68d8b422014-07-17 11:09:10 -0700282 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700283
Elliott Hughes81ff3182012-03-23 20:35:56 -0700284 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
285 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
286 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
287 // circumstances, but this is incorrect.
Ian Rogers68d8b422014-07-17 11:09:10 -0700288 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700289 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700290 AbortF("illegal class name '%s'\n"
291 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
292 class_name);
293 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700294 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700295 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700296 }
297
298 /*
299 * Verify that this instance field ID is valid for this object.
300 *
301 * Assumes "jobj" has already been validated.
302 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700303 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700304 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700305 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Ian Rogers68d8b422014-07-17 11:09:10 -0700306 if (o == nullptr) {
307 AbortF("field operation on NULL object: %p", java_object);
308 return false;
309 }
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700310 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700311 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700312 AbortF("field operation on invalid %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700313 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700314 java_object);
315 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700316 }
317
Andreas Gampe08883de2016-11-08 13:20:52 -0800318 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800319 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700320 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700321 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800322 mirror::Class* c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700323 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700324 AbortF("jfieldID %s not valid for an object of class %s",
David Sehr709b0702016-10-13 09:12:37 -0700325 f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700326 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700327 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700328 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700329 }
330
331 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700332 * Verify that the pointer value is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -0700333 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700334 bool CheckNonNull(const void* ptr) {
335 if (UNLIKELY(ptr == nullptr)) {
336 AbortF("non-nullable argument was NULL");
337 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700338 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700339 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700340 }
341
342 /*
343 * Verify that the method's return type matches the type of call.
344 * 'expectedType' will be "L" for all objects, including arrays.
345 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700346 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
347 jmethodID mid, Primitive::Type type, InvokeType invoke)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700348 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800349 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800350 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700351 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700352 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700353 if (type != Primitive::GetType(m->GetShorty()[0])) {
David Sehr709b0702016-10-13 09:12:37 -0700354 AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700355 return false;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700356 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700357 bool is_static = (invoke == kStatic);
358 if (is_static != m->IsStatic()) {
359 if (is_static) {
360 AbortF("calling non-static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700361 m->PrettyMethod().c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700362 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700363 AbortF("calling static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700364 m->PrettyMethod().c_str(), function_name_);
Ian Rogers68d8b422014-07-17 11:09:10 -0700365 }
366 return false;
367 }
368 if (invoke != kVirtual) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700369 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700370 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700371 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
David Sehr709b0702016-10-13 09:12:37 -0700372 m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700373 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700374 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700375 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700376 if (invoke != kStatic) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700377 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700378 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700379 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700380 return false;
381 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700382 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
383 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700384 return false;
385 }
386 }
387 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700388 }
389
390 /*
391 * Verify that this static field ID is valid for this class.
392 *
393 * Assumes "java_class" has already been validated.
394 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700395 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700396 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700397 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Andreas Gampe08883de2016-11-08 13:20:52 -0800398 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800399 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700400 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700401 }
Alex Lighte4033fa2017-12-13 10:32:59 -0800402 if (!f->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700403 AbortF("static jfieldID %p not valid for class %s", fid,
404 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700405 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700406 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700407 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700408 }
409
410 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700411 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700412 *
413 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700414 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700415 * allow bad code in the system though.
416 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700417 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700418 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700419 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700420 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800421 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800422 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700423 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700424 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700425 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700426 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700427 AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
428 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700429 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700430 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700431 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700432 }
433
434 /*
435 * Verify that "mid" is appropriate for "jobj".
436 *
437 * Make sure the object is an instance of the method's declaring class.
438 * (Note the mid might point to a declaration in an interface; this
439 * will be handled automatically by the instanceof check.)
440 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700441 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700442 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800443 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800444 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700445 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700446 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700447 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700448 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700449 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700450 return false;
451 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700452 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
453 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700454 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700455 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700456 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700457 }
458
459 /**
460 * The format string is a sequence of the following characters,
461 * and must be followed by arguments of the corresponding types
462 * in the same order.
463 *
464 * Java primitive types:
465 * B - jbyte
466 * C - jchar
467 * D - jdouble
468 * F - jfloat
469 * I - jint
470 * J - jlong
471 * S - jshort
472 * Z - jboolean (shown as true and false)
473 * V - void
474 *
475 * Java reference types:
476 * L - jobject
477 * a - jarray
478 * c - jclass
479 * s - jstring
480 *
481 * JNI types:
482 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
483 * f - jfieldID
484 * m - jmethodID
485 * p - void*
486 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700487 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700488 * z - jsize (for lengths; use i if negative values are okay)
489 * v - JavaVM*
490 * E - JNIEnv*
Alex Light48ffe062015-08-19 15:23:23 -0700491 * . - VarArgs* for Jni calls with variable length arguments
Elliott Hughesa2501992011-08-26 19:39:54 -0700492 *
493 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
494 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700495 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700496 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700497 ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700498 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700499 // We need to guard some of the invocation interface's calls: a bad caller might
500 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700501 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800502 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
503 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700504 }
505 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700506
Ian Rogersef7d42f2014-01-06 12:55:46 -0800507 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700508 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700509 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700510 for (size_t i = 0; fmt[i] != '\0'; ++i) {
511 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
512 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700513 StringAppendF(&msg, ", ");
514 }
515 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700516
Elliott Hughes485cac42011-12-09 17:49:35 -0800517 if ((flags_ & kFlag_ForceTrace) != 0) {
518 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
519 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700520 if (has_method_) {
David Sehr709b0702016-10-13 09:12:37 -0700521 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700522 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
523 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700524 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700525 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
526 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700527 }
528 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700529 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700530 }
531 }
532
533 // We always do the thorough checks on entry, and never on exit...
534 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700535 for (size_t i = 0; fmt[i] != '\0'; ++i) {
536 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
537 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700538 }
539 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700540 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700541 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700542 }
543
Ian Rogers68d8b422014-07-17 11:09:10 -0700544 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
545 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800546 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700547 // We need to guard some of the invocation interface's calls: a bad caller might
548 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
549 Thread* self = Thread::Current();
550 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
551 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700552 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700553 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
554 }
555 }
556 if (should_trace) {
557 std::string msg;
558 for (size_t i = 0; fmt[i] != '\0'; ++i) {
559 TraceNonHeapValue(fmt[i], args[i], &msg);
560 if (fmt[i + 1] != '\0') {
561 StringAppendF(&msg, ", ");
562 }
563 }
564
565 if ((flags_ & kFlag_ForceTrace) != 0) {
566 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
567 } else if (entry) {
568 if (has_method_) {
569 Thread* self = Thread::Current();
570 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700571 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
David Sehr709b0702016-10-13 09:12:37 -0700572 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Ian Rogers68d8b422014-07-17 11:09:10 -0700573 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
574 indent_ = methodName.size() + 1;
575 } else {
576 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
577 indent_ = 0;
578 }
579 } else {
580 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
581 }
582 }
583
584 // We always do the thorough checks on entry, and never on exit...
585 if (entry) {
586 for (size_t i = 0; fmt[i] != '\0'; ++i) {
587 if (!CheckNonHeapValue(fmt[i], args[i])) {
588 return false;
589 }
590 }
591 }
592 return true;
593 }
594
595 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700596 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700597 ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700598 if (method == nullptr) {
599 AbortF("expected non-null method");
600 return false;
601 }
602 mirror::Class* c = method->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700603 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c &&
604 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700605 AbortF("expected java.lang.reflect.Method or "
606 "java.lang.reflect.Constructor but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700607 method->PrettyTypeOf().c_str(), jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700608 return false;
609 }
610 return true;
611 }
612
Andreas Gampe13b27842016-11-07 16:48:23 -0800613 bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
614 ArtMethod* method = jni::DecodeArtMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700615 if (method == nullptr) {
616 AbortF("expected non-null constructor");
617 return false;
618 }
619 if (!method->IsConstructor() || method->IsStatic()) {
David Sehr709b0702016-10-13 09:12:37 -0700620 AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700621 return false;
622 }
623 return true;
624 }
625
626 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700627 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700628 ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700629 if (field == nullptr) {
630 AbortF("expected non-null java.lang.reflect.Field");
631 return false;
632 }
633 mirror::Class* c = field->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700634 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700635 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700636 field->PrettyTypeOf().c_str(), jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700637 return false;
638 }
639 return true;
640 }
641
642 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700643 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700644 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700645 if (!obj->GetClass()->IsThrowableClass()) {
646 AbortF("expected java.lang.Throwable but got object of type "
David Sehr709b0702016-10-13 09:12:37 -0700647 "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700648 return false;
649 }
650 return true;
651 }
652
653 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700654 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700655 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700656 if (!c->IsThrowableClass()) {
657 AbortF("expected java.lang.Throwable class but got object of "
David Sehr709b0702016-10-13 09:12:37 -0700658 "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700659 return false;
660 }
661 return true;
662 }
663
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700664 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700665 IndirectRefKind found_kind;
666 if (expected_kind == kLocal) {
Andreas Gampedc061d02016-10-24 13:19:37 -0700667 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700668 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
669 found_kind = kLocal;
670 }
671 } else {
Andreas Gampedc061d02016-10-24 13:19:37 -0700672 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700673 }
674 if (obj != nullptr && found_kind != expected_kind) {
675 AbortF("expected reference of kind %s but found %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700676 GetIndirectRefKindString(expected_kind),
677 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700678 obj);
679 return false;
680 }
681 return true;
682 }
683
684 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700685 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700686 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700687 if (!c->IsInstantiableNonArray()) {
David Sehr709b0702016-10-13 09:12:37 -0700688 AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700689 return false;
690 }
691 return true;
692 }
693
694 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700695 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700696 if (!CheckArray(soa, array)) {
697 return false;
698 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700699 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700700 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
701 AbortF("incompatible array type %s expected %s[]: %p",
David Sehr709b0702016-10-13 09:12:37 -0700702 a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700703 return false;
704 }
705 return true;
706 }
707
708 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
709 Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700710 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700711 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
712 return false;
713 }
714 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
715 return false;
716 }
Andreas Gampe08883de2016-11-08 13:20:52 -0800717 ArtField* field = jni::DecodeArtField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700718 DCHECK(field != nullptr); // Already checked by Check.
719 if (is_static != field->IsStatic()) {
720 AbortF("attempt to access %s field %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700721 field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700722 return false;
723 }
724 if (type != field->GetTypeAsPrimitiveType()) {
725 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700726 field->PrettyField().c_str(),
727 PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
Ian Rogers68d8b422014-07-17 11:09:10 -0700728 PrettyDescriptor(type).c_str(), fid);
729 return false;
730 }
731 if (is_static) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700732 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700733 if (o == nullptr || !o->IsClass()) {
734 AbortF("attempt to access static field %s with a class argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700735 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700736 return false;
737 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700738 ObjPtr<mirror::Class> c = o->AsClass();
Alex Lighte4033fa2017-12-13 10:32:59 -0800739 if (!field->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700740 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700741 field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700742 return false;
743 }
744 } else {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700745 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700746 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
747 AbortF("attempt to access field %s from an object argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700748 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700749 return false;
750 }
751 }
752 return true;
753 }
754
755 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800756 enum InstanceKind {
757 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700758 kDirectByteBuffer,
759 kObject,
760 kString,
761 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800762 };
763
764 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700765 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800766 * an instance of expectedClass.
767 *
768 * Because we're looking at an object on the GC heap, we have to switch
769 * to "running" mode before doing the checks.
770 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700771 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700772 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800773 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800774 switch (kind) {
775 case kClass:
776 what = "jclass";
777 break;
778 case kDirectByteBuffer:
779 what = "direct ByteBuffer";
780 break;
781 case kObject:
782 what = "jobject";
783 break;
784 case kString:
785 what = "jstring";
786 break;
787 case kThrowable:
788 what = "jthrowable";
789 break;
790 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700791 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800792 }
793
Ian Rogersef7d42f2014-01-06 12:55:46 -0800794 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700795 if (null_ok) {
796 return true;
797 } else {
798 AbortF("%s received NULL %s", function_name_, what);
799 return false;
800 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800801 }
802
Mathieu Chartier0795f232016-09-27 18:43:30 -0700803 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700804 if (obj == nullptr) {
805 // Either java_object is invalid or is a cleared weak.
806 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
807 bool okay;
Andreas Gampedc061d02016-10-24 13:19:37 -0700808 if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) {
Ian Rogersc0542af2014-09-03 16:16:56 -0700809 okay = false;
810 } else {
811 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
Mathieu Chartierc4f39252016-10-05 18:32:08 -0700812 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
Ian Rogersc0542af2014-09-03 16:16:56 -0700813 }
814 if (!okay) {
815 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700816 what,
817 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
818 java_object,
819 obj.Ptr());
Ian Rogersc0542af2014-09-03 16:16:56 -0700820 return false;
821 }
822 }
823
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700824 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700825 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700826 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700827 what,
828 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
829 java_object,
830 obj.Ptr());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800831 return false;
832 }
833
834 bool okay = true;
835 switch (kind) {
836 case kClass:
837 okay = obj->IsClass();
838 break;
839 case kDirectByteBuffer:
840 UNIMPLEMENTED(FATAL);
841 break;
842 case kString:
843 okay = obj->GetClass()->IsStringClass();
844 break;
845 case kThrowable:
846 okay = obj->GetClass()->IsThrowableClass();
847 break;
848 case kObject:
849 break;
850 }
851 if (!okay) {
David Sehr709b0702016-10-13 09:12:37 -0700852 AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800853 return false;
854 }
855
856 return true;
857 }
858
Ian Rogers68d8b422014-07-17 11:09:10 -0700859 /*
860 * Verify that the "mode" argument passed to a primitive array Release
861 * function is one of the valid values.
862 */
863 bool CheckReleaseMode(jint mode) {
864 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
865 AbortF("unknown value for release mode: %d", mode);
866 return false;
867 }
868 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700869 }
870
Ian Rogers68d8b422014-07-17 11:09:10 -0700871 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700872 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700873 switch (fmt) {
874 case 'a': // jarray
875 return CheckArray(soa, arg.a);
876 case 'c': // jclass
877 return CheckInstance(soa, kClass, arg.c, false);
878 case 'f': // jfieldID
Andreas Gampe08883de2016-11-08 13:20:52 -0800879 return CheckFieldID(arg.f) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700880 case 'm': // jmethodID
Andreas Gampe13b27842016-11-07 16:48:23 -0800881 return CheckMethodID(arg.m) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700882 case 'r': // release int
883 return CheckReleaseMode(arg.r);
884 case 's': // jstring
885 return CheckInstance(soa, kString, arg.s, false);
886 case 't': // jthrowable
887 return CheckInstance(soa, kThrowable, arg.t, false);
888 case 'E': // JNIEnv*
889 return CheckThread(arg.E);
890 case 'L': // jobject
891 return CheckInstance(soa, kObject, arg.L, true);
Alex Light48ffe062015-08-19 15:23:23 -0700892 case '.': // A VarArgs list
893 return CheckVarArgs(soa, arg.va);
Ian Rogers68d8b422014-07-17 11:09:10 -0700894 default:
895 return CheckNonHeapValue(fmt, arg);
896 }
897 }
898
Alex Light48ffe062015-08-19 15:23:23 -0700899 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700900 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Light48ffe062015-08-19 15:23:23 -0700901 CHECK(args_p != nullptr);
902 VarArgs args(args_p->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800903 ArtMethod* m = CheckMethodID(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700904 if (m == nullptr) {
905 return false;
906 }
907 uint32_t len = 0;
908 const char* shorty = m->GetShorty(&len);
909 // Skip the return type
910 CHECK_GE(len, 1u);
911 len--;
912 shorty++;
913 for (uint32_t i = 0; i < len; i++) {
914 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
915 return false;
916 }
917 }
918 return true;
919 }
920
Ian Rogers68d8b422014-07-17 11:09:10 -0700921 bool CheckNonHeapValue(char fmt, JniValueType arg) {
922 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700923 case 'p': // TODO: pointer - null or readable?
924 case 'v': // JavaVM*
Ian Rogers68d8b422014-07-17 11:09:10 -0700925 case 'D': // jdouble
926 case 'F': // jfloat
Ian Rogers68d8b422014-07-17 11:09:10 -0700927 case 'J': // jlong
Ian Rogers9e937be2018-02-15 17:06:58 -0800928 case 'I': // jint
Ian Rogers68d8b422014-07-17 11:09:10 -0700929 break; // Ignored.
930 case 'b': // jboolean, why two? Fall-through.
931 case 'Z':
Ian Rogers9e937be2018-02-15 17:06:58 -0800932 return CheckBoolean(arg.I);
933 case 'B': // jbyte
934 return CheckByte(arg.I);
935 case 'C': // jchar
936 return CheckChar(arg.I);
937 case 'S': // jshort
938 return CheckShort(arg.I);
Ian Rogers68d8b422014-07-17 11:09:10 -0700939 case 'u': // utf8
940 if ((flags_ & kFlag_Release) != 0) {
941 return CheckNonNull(arg.u);
942 } else {
943 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
944 return CheckUtfString(arg.u, nullable);
945 }
946 case 'w': // jobjectRefType
947 switch (arg.w) {
948 case JNIInvalidRefType:
949 case JNILocalRefType:
950 case JNIGlobalRefType:
951 case JNIWeakGlobalRefType:
952 break;
953 default:
954 AbortF("Unknown reference type");
955 return false;
956 }
957 break;
958 case 'z': // jsize
959 return CheckLengthPositive(arg.z);
960 default:
961 AbortF("unknown format specifier: '%c'", fmt);
962 return false;
963 }
964 return true;
965 }
966
967 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
968 std::string* msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700969 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700970 switch (fmt) {
971 case 'L': // jobject fall-through.
972 case 'a': // jarray fall-through.
973 case 's': // jstring fall-through.
974 case 't': // jthrowable fall-through.
975 if (arg.L == nullptr) {
976 *msg += "NULL";
977 } else {
978 StringAppendF(msg, "%p", arg.L);
979 }
980 break;
981 case 'c': { // jclass
982 jclass jc = arg.c;
Mathieu Chartier0795f232016-09-27 18:43:30 -0700983 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700984 if (c == nullptr) {
985 *msg += "NULL";
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700986 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700987 StringAppendF(msg, "INVALID POINTER:%p", jc);
988 } else if (!c->IsClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700989 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
Ian Rogers68d8b422014-07-17 11:09:10 -0700990 } else {
David Sehr709b0702016-10-13 09:12:37 -0700991 *msg += c->PrettyClass();
Ian Rogers68d8b422014-07-17 11:09:10 -0700992 if (!entry) {
993 StringAppendF(msg, " (%p)", jc);
994 }
995 }
996 break;
997 }
998 case 'f': { // jfieldID
999 jfieldID fid = arg.f;
Andreas Gampe08883de2016-11-08 13:20:52 -08001000 ArtField* f = jni::DecodeArtField(fid);
David Sehr709b0702016-10-13 09:12:37 -07001001 *msg += ArtField::PrettyField(f);
Ian Rogers68d8b422014-07-17 11:09:10 -07001002 if (!entry) {
1003 StringAppendF(msg, " (%p)", fid);
1004 }
1005 break;
1006 }
1007 case 'm': { // jmethodID
1008 jmethodID mid = arg.m;
Andreas Gampe13b27842016-11-07 16:48:23 -08001009 ArtMethod* m = jni::DecodeArtMethod(mid);
David Sehr709b0702016-10-13 09:12:37 -07001010 *msg += ArtMethod::PrettyMethod(m);
Ian Rogers68d8b422014-07-17 11:09:10 -07001011 if (!entry) {
1012 StringAppendF(msg, " (%p)", mid);
1013 }
1014 break;
1015 }
Alex Light48ffe062015-08-19 15:23:23 -07001016 case '.': {
1017 const VarArgs* va = arg.va;
1018 VarArgs args(va->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -08001019 ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -07001020 uint32_t len;
1021 const char* shorty = m->GetShorty(&len);
1022 CHECK_GE(len, 1u);
1023 // Skip past return value.
1024 len--;
1025 shorty++;
1026 // Remove the previous ', ' from the message.
1027 msg->erase(msg->length() - 2);
1028 for (uint32_t i = 0; i < len; i++) {
1029 *msg += ", ";
1030 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
1031 }
1032 break;
1033 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001034 default:
1035 TraceNonHeapValue(fmt, arg, msg);
1036 break;
1037 }
1038 }
1039
1040 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
1041 switch (fmt) {
1042 case 'B': // jbyte
1043 if (arg.B >= 0 && arg.B < 10) {
1044 StringAppendF(msg, "%d", arg.B);
1045 } else {
1046 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1047 }
1048 break;
1049 case 'C': // jchar
1050 if (arg.C < 0x7f && arg.C >= ' ') {
1051 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1052 } else {
1053 StringAppendF(msg, "U+%x", arg.C);
1054 }
1055 break;
1056 case 'F': // jfloat
1057 StringAppendF(msg, "%g", arg.F);
1058 break;
1059 case 'D': // jdouble
1060 StringAppendF(msg, "%g", arg.D);
1061 break;
1062 case 'S': // jshort
1063 StringAppendF(msg, "%d", arg.S);
1064 break;
1065 case 'i': // jint - fall-through.
1066 case 'I': // jint
1067 StringAppendF(msg, "%d", arg.I);
1068 break;
1069 case 'J': // jlong
1070 StringAppendF(msg, "%" PRId64, arg.J);
1071 break;
1072 case 'Z': // jboolean
1073 case 'b': // jboolean (JNI-style)
1074 *msg += arg.b == JNI_TRUE ? "true" : "false";
1075 break;
1076 case 'V': // void
1077 DCHECK(arg.V == nullptr);
1078 *msg += "void";
1079 break;
1080 case 'v': // JavaVM*
1081 StringAppendF(msg, "(JavaVM*)%p", arg.v);
1082 break;
1083 case 'E':
1084 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1085 break;
1086 case 'z': // non-negative jsize
1087 // You might expect jsize to be size_t, but it's not; it's the same as jint.
1088 // We only treat this specially so we can do the non-negative check.
1089 // TODO: maybe this wasn't worth it?
1090 StringAppendF(msg, "%d", arg.z);
1091 break;
1092 case 'p': // void* ("pointer")
1093 if (arg.p == nullptr) {
1094 *msg += "NULL";
1095 } else {
1096 StringAppendF(msg, "(void*) %p", arg.p);
1097 }
1098 break;
1099 case 'r': { // jint (release mode)
1100 jint releaseMode = arg.r;
1101 if (releaseMode == 0) {
1102 *msg += "0";
1103 } else if (releaseMode == JNI_ABORT) {
1104 *msg += "JNI_ABORT";
1105 } else if (releaseMode == JNI_COMMIT) {
1106 *msg += "JNI_COMMIT";
1107 } else {
1108 StringAppendF(msg, "invalid release mode %d", releaseMode);
1109 }
1110 break;
1111 }
1112 case 'u': // const char* (Modified UTF-8)
1113 if (arg.u == nullptr) {
1114 *msg += "NULL";
1115 } else {
1116 StringAppendF(msg, "\"%s\"", arg.u);
1117 }
1118 break;
1119 case 'w': // jobjectRefType
1120 switch (arg.w) {
1121 case JNIInvalidRefType:
1122 *msg += "invalid reference type";
1123 break;
1124 case JNILocalRefType:
1125 *msg += "local ref type";
1126 break;
1127 case JNIGlobalRefType:
1128 *msg += "global ref type";
1129 break;
1130 case JNIWeakGlobalRefType:
1131 *msg += "weak global ref type";
1132 break;
1133 default:
1134 *msg += "unknown ref type";
1135 break;
1136 }
1137 break;
Ian Rogers68d8b422014-07-17 11:09:10 -07001138 default:
1139 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1140 }
1141 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001142 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001143 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -07001144 *
1145 * Since we're dealing with objects, switch to "running" mode.
1146 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001147 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001148 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001149 if (UNLIKELY(java_array == nullptr)) {
1150 AbortF("jarray was NULL");
1151 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001152 }
1153
Mathieu Chartier0795f232016-09-27 18:43:30 -07001154 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001155 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001156 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001157 AbortF("jarray is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -07001158 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)),
1159 java_array,
1160 a.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -07001161 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001162 } else if (!a->IsArrayInstance()) {
David Sehr709b0702016-10-13 09:12:37 -07001163 AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001164 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001165 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001166 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001167 }
1168
Ian Rogers9e937be2018-02-15 17:06:58 -08001169 bool CheckBoolean(jint z) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001170 if (z != JNI_TRUE && z != JNI_FALSE) {
Ian Rogers9e937be2018-02-15 17:06:58 -08001171 // Note, broken booleans are always fatal.
Ian Rogers68d8b422014-07-17 11:09:10 -07001172 AbortF("unexpected jboolean value: %d", z);
1173 return false;
1174 }
1175 return true;
1176 }
1177
Ian Rogers9e937be2018-02-15 17:06:58 -08001178 bool CheckByte(jint b) {
1179 if (b < std::numeric_limits<jbyte>::min() ||
1180 b > std::numeric_limits<jbyte>::max()) {
1181 if (kBrokenPrimitivesAreFatal) {
1182 AbortF("unexpected jbyte value: %d", b);
1183 return false;
1184 } else {
1185 LOG(WARNING) << "Unexpected jbyte value: " << b;
1186 }
1187 }
1188 return true;
1189 }
1190
1191 bool CheckShort(jint s) {
1192 if (s < std::numeric_limits<jshort>::min() ||
1193 s > std::numeric_limits<jshort>::max()) {
1194 if (kBrokenPrimitivesAreFatal) {
1195 AbortF("unexpected jshort value: %d", s);
1196 return false;
1197 } else {
1198 LOG(WARNING) << "Unexpected jshort value: " << s;
1199 }
1200 }
1201 return true;
1202 }
1203
1204 bool CheckChar(jint c) {
1205 if (c < std::numeric_limits<jchar>::min() ||
1206 c > std::numeric_limits<jchar>::max()) {
1207 if (kBrokenPrimitivesAreFatal) {
1208 AbortF("unexpected jchar value: %d", c);
1209 return false;
1210 } else {
1211 LOG(WARNING) << "Unexpected jchar value: " << c;
1212 }
1213 }
1214 return true;
1215 }
1216
Ian Rogers68d8b422014-07-17 11:09:10 -07001217 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001218 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001219 AbortF("negative jsize: %d", length);
1220 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001221 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001222 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001223 }
1224
Andreas Gampe08883de2016-11-08 13:20:52 -08001225 ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001226 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001227 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001228 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001229 }
Andreas Gampe08883de2016-11-08 13:20:52 -08001230 ArtField* f = jni::DecodeArtField(fid);
Mathieu Chartierc7853442015-03-27 14:35:38 -07001231 // TODO: Better check here.
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001232 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001233 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001234 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001235 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001236 }
1237 return f;
1238 }
1239
Andreas Gampe13b27842016-11-07 16:48:23 -08001240 ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001241 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001242 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001243 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001244 }
Andreas Gampe13b27842016-11-07 16:48:23 -08001245 ArtMethod* m = jni::DecodeArtMethod(mid);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001246 // TODO: Better check here.
1247 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001248 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001249 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001250 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001251 }
1252 return m;
1253 }
1254
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001255 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001256 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001257 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001258 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1259 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001260 }
1261
Daniel Erat35e827a2016-05-10 18:07:18 -06001262 // Get the current thread's JNIEnv by going through our TLS pointer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001263 JNIEnvExt* threadEnv = self->GetJniEnv();
1264
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001265 // Verify that the current thread is (a) attached and (b) associated with
1266 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001267 if (env != threadEnv) {
Daniel Erat35e827a2016-05-10 18:07:18 -06001268 // Get the thread owning the JNIEnv that's being used.
Ian Rogersac4d45a2018-02-15 11:19:01 -08001269 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->GetSelf();
Ian Rogers68d8b422014-07-17 11:09:10 -07001270 AbortF("thread %s using JNIEnv* from thread %s",
Daniel Erat35e827a2016-05-10 18:07:18 -06001271 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001272 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001273 }
1274
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001275 // Verify that, if this thread previously made a critical "get" call, we
1276 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001277 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001278 case kFlag_CritOkay: // okay to call this method
1279 break;
1280 case kFlag_CritBad: // not okay to call
Ian Rogersac4d45a2018-02-15 11:19:01 -08001281 if (threadEnv->GetCritical() > 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001282 AbortF("thread %s using JNI after critical get",
1283 ToStr<Thread>(*self).c_str());
1284 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001285 }
1286 break;
1287 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001288 // Don't check here; we allow nested gets.
Ian Rogersac4d45a2018-02-15 11:19:01 -08001289 if (threadEnv->GetCritical() == 0) {
1290 threadEnv->SetCriticalStartUs(self->GetCpuMicroTime());
Ian Rogers55256cb2017-12-21 17:07:11 -08001291 }
Ian Rogersac4d45a2018-02-15 11:19:01 -08001292 threadEnv->SetCritical(threadEnv->GetCritical() + 1);
Elliott Hughesa2501992011-08-26 19:39:54 -07001293 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001294 case kFlag_CritRelease: // this is a "release" call
Ian Rogersac4d45a2018-02-15 11:19:01 -08001295 if (threadEnv->GetCritical() == 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001296 AbortF("thread %s called too many critical releases",
1297 ToStr<Thread>(*self).c_str());
1298 return false;
Ian Rogersac4d45a2018-02-15 11:19:01 -08001299 } else if (threadEnv->GetCritical() == 1) {
Ian Rogers55256cb2017-12-21 17:07:11 -08001300 // Leaving the critical region, possibly warn about long critical regions.
Ian Rogersac4d45a2018-02-15 11:19:01 -08001301 uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->GetCriticalStartUs();
Ian Rogers55256cb2017-12-21 17:07:11 -08001302 if (critical_duration_us > kCriticalWarnTimeUs) {
1303 LOG(WARNING) << "JNI critical lock held for "
1304 << PrettyDuration(UsToNs(critical_duration_us)) << " on " << *self;
1305 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001306 }
Ian Rogersac4d45a2018-02-15 11:19:01 -08001307 threadEnv->SetCritical(threadEnv->GetCritical() - 1);
Elliott Hughesa2501992011-08-26 19:39:54 -07001308 break;
1309 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001310 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001311 }
1312
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001313 // Verify that, if an exception has been raised, the native code doesn't
1314 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001315 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001316 mirror::Throwable* exception = self->GetException();
1317 AbortF("JNI %s called with pending exception %s",
1318 function_name_,
1319 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001320 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001321 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001322 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001323 }
1324
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001325 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001326 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001327 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001328 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001329 AbortF("non-nullable const char* was NULL");
1330 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001331 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001332 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001333 }
1334
Ian Rogersef7d42f2014-01-06 12:55:46 -08001335 const char* errorKind = nullptr;
Andreas Gampeef4afe92015-07-27 21:03:25 -07001336 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001337 if (errorKind != nullptr) {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001338 // This is an expensive loop that will resize often, but this isn't supposed to hit in
1339 // practice anyways.
1340 std::ostringstream oss;
1341 oss << std::hex;
1342 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1343 while (*tmp != 0) {
1344 if (tmp == utf8) {
1345 oss << "<";
1346 }
1347 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1348 if (tmp == utf8) {
1349 oss << '>';
1350 }
1351 tmp++;
1352 if (*tmp != 0) {
1353 oss << ' ';
1354 }
1355 }
1356
Ian Rogers68d8b422014-07-17 11:09:10 -07001357 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
Andreas Gampeef4afe92015-07-27 21:03:25 -07001358 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001359 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001360 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001361 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001362 }
1363
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001364 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1365 // sequences in place of encoded surrogate pairs.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001366 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001367 while (*bytes != '\0') {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001368 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
Elliott Hughesa2501992011-08-26 19:39:54 -07001369 // Switch on the high four bits.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001370 switch (*utf8 >> 4) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001371 case 0x00:
1372 case 0x01:
1373 case 0x02:
1374 case 0x03:
1375 case 0x04:
1376 case 0x05:
1377 case 0x06:
1378 case 0x07:
1379 // Bit pattern 0xxx. No need for any extra bytes.
1380 break;
1381 case 0x08:
1382 case 0x09:
1383 case 0x0a:
1384 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001385 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001386 *errorKind = "start";
1387 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001388 case 0x0f:
1389 // Bit pattern 1111, which might be the start of a 4 byte sequence.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001390 if ((*utf8 & 0x08) == 0) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001391 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1392 // We consume one continuation byte here, and fall through to consume two more.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001393 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1394 if ((*utf8 & 0xc0) != 0x80) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001395 *errorKind = "continuation";
1396 return utf8;
1397 }
1398 } else {
1399 *errorKind = "start";
1400 return utf8;
1401 }
1402
1403 // Fall through to the cases below to consume two more continuation bytes.
1404 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001405 case 0x0e:
1406 // Bit pattern 1110, so there are two additional bytes.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001407 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1408 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001409 *errorKind = "continuation";
1410 return utf8;
1411 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001412
1413 // Fall through to consume one more continuation byte.
1414 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001415 case 0x0c:
1416 case 0x0d:
1417 // Bit pattern 110x, so there is one additional byte.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001418 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1419 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001420 *errorKind = "continuation";
1421 return utf8;
1422 }
1423 break;
1424 }
1425 }
1426 return 0;
1427 }
1428
Ian Rogers68d8b422014-07-17 11:09:10 -07001429 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1430 va_list args;
1431 va_start(args, fmt);
1432 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1433 va_end(args);
1434 }
1435
1436 // The name of the JNI function being checked.
1437 const char* const function_name_;
1438
Elliott Hughes92cb4982011-12-16 16:57:28 -08001439 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001440
Ian Rogers55256cb2017-12-21 17:07:11 -08001441 const uint16_t flags_;
1442
Ian Rogers68d8b422014-07-17 11:09:10 -07001443 const bool has_method_;
1444
Elliott Hughesa2501992011-08-26 19:39:54 -07001445 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1446};
1447
Elliott Hughesa2501992011-08-26 19:39:54 -07001448/*
1449 * ===========================================================================
1450 * Guarded arrays
1451 * ===========================================================================
1452 */
1453
Elliott Hughesa2501992011-08-26 19:39:54 -07001454/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001455class GuardedCopy {
1456 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001457 /*
1458 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1459 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001460 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001461 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001462 const size_t new_len = LengthIncludingRedZones(len);
1463 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001464
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001465 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001466 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001467 if (!mod_okay) {
1468 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001469 }
1470
Ian Rogers68d8b422014-07-17 11:09:10 -07001471 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001472
Ian Rogers68d8b422014-07-17 11:09:10 -07001473 // Fill begin region with canary pattern.
1474 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1475 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1476 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1477 if (kCanary[j] == '\0') {
1478 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001479 } else {
1480 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001481 }
1482 }
1483
1484 // Copy the data in; note "len" could be zero.
1485 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1486
1487 // Fill end region with canary pattern.
1488 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1489 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1490 if (kCanary[j] == '\0') {
1491 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001492 } else {
1493 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001494 }
1495 }
1496
1497 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001498 }
1499
1500 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001501 * Create a guarded copy of a primitive array. Modifications to the copied
1502 * data are allowed. Returns a pointer to the copied data.
1503 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001504 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1505 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001506 ScopedObjectAccess soa(env);
1507
Mathieu Chartier0795f232016-09-27 18:43:30 -07001508 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Ian Rogers68d8b422014-07-17 11:09:10 -07001509 size_t component_size = a->GetClass()->GetComponentSize();
1510 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001511 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001512 if (is_copy != nullptr) {
1513 *is_copy = JNI_TRUE;
1514 }
1515 return result;
1516 }
1517
1518 /*
1519 * Perform the array "release" operation, which may or may not copy data
1520 * back into the managed heap, and may or may not release the underlying storage.
1521 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001522 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1523 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1524 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001525 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001526 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1527 return nullptr;
1528 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001529 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1530 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001531 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001532 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001533 }
1534 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001535 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001536 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001537 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001538 }
1539
1540
1541 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001542 * Free up the guard buffer, scrub it, and return the original pointer.
1543 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001544 static void* Destroy(void* embedded_buf) {
1545 GuardedCopy* copy = FromEmbedded(embedded_buf);
1546 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1547 size_t len = LengthIncludingRedZones(copy->original_length_);
1548 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001549 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001550 }
1551
1552 /*
1553 * Verify the guard area and, if "modOkay" is false, that the data itself
1554 * has not been altered.
1555 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001556 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001557 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001558 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1559 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1560 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001561 }
1562
1563 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001564 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001565 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1566 }
1567
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001568 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001569 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001570 if (result == MAP_FAILED) {
1571 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1572 }
1573 return reinterpret_cast<uint8_t*>(result);
1574 }
1575
Ian Rogers68d8b422014-07-17 11:09:10 -07001576 static void DebugFree(void* buf, size_t len) {
1577 if (munmap(buf, len) != 0) {
1578 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001579 }
1580 }
1581
Ian Rogers68d8b422014-07-17 11:09:10 -07001582 static size_t LengthIncludingRedZones(size_t len) {
1583 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001584 }
1585
Ian Rogers68d8b422014-07-17 11:09:10 -07001586 // Get the GuardedCopy from the interior pointer.
1587 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1588 return reinterpret_cast<GuardedCopy*>(
1589 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001590 }
1591
Ian Rogers68d8b422014-07-17 11:09:10 -07001592 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1593 return reinterpret_cast<const GuardedCopy*>(
1594 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001595 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001596
1597 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1598 va_list args;
1599 va_start(args, fmt);
1600 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1601 va_end(args);
1602 }
1603
1604 bool CheckHeader(const char* function_name, bool mod_okay) const {
1605 static const uint32_t kMagicCmp = kGuardMagic;
1606
1607 // Before we do anything with "pExtra", check the magic number. We
1608 // do the check with memcmp rather than "==" in case the pointer is
1609 // unaligned. If it points to completely bogus memory we're going
1610 // to crash, but there's no easy way around that.
1611 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1612 uint8_t buf[4];
1613 memcpy(buf, &magic_, 4);
1614 AbortF(function_name,
1615 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1616 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1617 return false;
1618 }
1619
1620 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1621 // told the client that we made a copy, there's no reason they can't alter the buffer.
1622 if (!mod_okay) {
1623 uLong computed_adler =
1624 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1625 if (computed_adler != adler_) {
1626 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1627 computed_adler, adler_, this);
1628 return false;
1629 }
1630 }
1631 return true;
1632 }
1633
1634 bool CheckRedZones(const char* function_name) const {
1635 // Check the begin red zone.
1636 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1637 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1638 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1639 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1640 return false;
1641 }
1642 if (kCanary[j] == '\0') {
1643 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001644 } else {
1645 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001646 }
1647 }
1648
1649 // Check end region.
1650 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1651 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1652 size_t offset_from_buffer_start =
1653 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1654 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1655 offset_from_buffer_start);
1656 return false;
1657 }
1658 if (kCanary[j] == '\0') {
1659 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001660 } else {
1661 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001662 }
1663 }
1664 return true;
1665 }
1666
1667 // Location that canary value will be written before the guarded region.
1668 const char* StartRedZone() const {
1669 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1670 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1671 }
1672
1673 // Return the interior embedded buffer.
1674 const uint8_t* BufferWithinRedZones() const {
1675 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1676 return embedded_buf;
1677 }
1678
1679 // Location that canary value will be written after the guarded region.
1680 const char* EndRedZone() const {
1681 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1682 size_t buf_len = LengthIncludingRedZones(original_length_);
1683 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1684 }
1685
1686 static constexpr size_t kRedZoneSize = 512;
1687 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1688
1689 // Value written before and after the guarded array.
1690 static const char* const kCanary;
1691
1692 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1693
1694 const uint32_t magic_;
1695 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001696 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001697 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001698};
Ian Rogers68d8b422014-07-17 11:09:10 -07001699const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001700
1701/*
1702 * ===========================================================================
1703 * JNI functions
1704 * ===========================================================================
1705 */
1706
1707class CheckJNI {
1708 public:
1709 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001710 ScopedObjectAccess soa(env);
1711 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1712 JniValueType args[1] = {{.E = env }};
1713 if (sc.Check(soa, true, "E", args)) {
1714 JniValueType result;
1715 result.I = baseEnv(env)->GetVersion(env);
1716 if (sc.Check(soa, false, "I", &result)) {
1717 return result.I;
1718 }
1719 }
1720 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001721 }
1722
Ian Rogers68d8b422014-07-17 11:09:10 -07001723 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1724 ScopedObjectAccess soa(env);
1725 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1726 JniValueType args[2] = {{.E = env }, {.p = vm}};
1727 if (sc.Check(soa, true, "Ep", args)) {
1728 JniValueType result;
1729 result.i = baseEnv(env)->GetJavaVM(env, vm);
1730 if (sc.Check(soa, false, "i", &result)) {
1731 return result.i;
1732 }
1733 }
1734 return JNI_ERR;
1735 }
1736
1737 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1738 ScopedObjectAccess soa(env);
1739 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1740 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1741 if (sc.Check(soa, true, "EcpI", args)) {
1742 JniValueType result;
1743 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1744 if (sc.Check(soa, false, "i", &result)) {
1745 return result.i;
1746 }
1747 }
1748 return JNI_ERR;
1749 }
1750
1751 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1752 ScopedObjectAccess soa(env);
1753 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1754 JniValueType args[2] = {{.E = env }, {.c = c}};
1755 if (sc.Check(soa, true, "Ec", args)) {
1756 JniValueType result;
1757 result.i = baseEnv(env)->UnregisterNatives(env, c);
1758 if (sc.Check(soa, false, "i", &result)) {
1759 return result.i;
1760 }
1761 }
1762 return JNI_ERR;
1763 }
1764
1765 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001766 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1767 // know the object is invalid. The spec says that passing invalid objects or even ones that
1768 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001769 ScopedObjectAccess soa(env);
1770 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001771 JniValueType args[2] = {{.E = env }, {.L = obj}};
1772 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001773 JniValueType result;
1774 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1775 if (sc.Check(soa, false, "w", &result)) {
1776 return result.w;
1777 }
1778 }
1779 return JNIInvalidRefType;
1780 }
1781
1782 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1783 jsize bufLen) {
1784 ScopedObjectAccess soa(env);
1785 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1786 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1787 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1788 JniValueType result;
1789 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1790 if (sc.Check(soa, false, "c", &result)) {
1791 return result.c;
1792 }
1793 }
1794 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001795 }
1796
1797 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001798 ScopedObjectAccess soa(env);
1799 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1800 JniValueType args[2] = {{.E = env}, {.u = name}};
1801 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1802 JniValueType result;
1803 result.c = baseEnv(env)->FindClass(env, name);
1804 if (sc.Check(soa, false, "c", &result)) {
1805 return result.c;
1806 }
1807 }
1808 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001809 }
1810
Elliott Hughese84278b2012-03-22 10:06:53 -07001811 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001812 ScopedObjectAccess soa(env);
1813 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1814 JniValueType args[2] = {{.E = env}, {.c = c}};
1815 if (sc.Check(soa, true, "Ec", args)) {
1816 JniValueType result;
1817 result.c = baseEnv(env)->GetSuperclass(env, c);
1818 if (sc.Check(soa, false, "c", &result)) {
1819 return result.c;
1820 }
1821 }
1822 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001823 }
1824
Elliott Hughese84278b2012-03-22 10:06:53 -07001825 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001826 ScopedObjectAccess soa(env);
1827 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1828 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1829 if (sc.Check(soa, true, "Ecc", args)) {
1830 JniValueType result;
1831 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1832 if (sc.Check(soa, false, "b", &result)) {
1833 return result.b;
1834 }
1835 }
1836 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001837 }
1838
1839 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001840 ScopedObjectAccess soa(env);
1841 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1842 JniValueType args[2] = {{.E = env}, {.L = method}};
1843 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1844 JniValueType result;
1845 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1846 if (sc.Check(soa, false, "m", &result)) {
1847 return result.m;
1848 }
1849 }
1850 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001851 }
1852
1853 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001854 ScopedObjectAccess soa(env);
1855 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1856 JniValueType args[2] = {{.E = env}, {.L = field}};
1857 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1858 JniValueType result;
1859 result.f = baseEnv(env)->FromReflectedField(env, field);
1860 if (sc.Check(soa, false, "f", &result)) {
1861 return result.f;
1862 }
1863 }
1864 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001865 }
1866
1867 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001868 ScopedObjectAccess soa(env);
1869 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogers9e937be2018-02-15 17:06:58 -08001870 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.I = isStatic}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001871 if (sc.Check(soa, true, "Ecmb", args)) {
1872 JniValueType result;
1873 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1874 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1875 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1876 return result.L;
1877 }
1878 }
1879 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001880 }
1881
1882 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001883 ScopedObjectAccess soa(env);
1884 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogers9e937be2018-02-15 17:06:58 -08001885 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.I = isStatic}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001886 if (sc.Check(soa, true, "Ecfb", args)) {
1887 JniValueType result;
1888 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1889 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1890 DCHECK(sc.CheckReflectedField(soa, result.L));
1891 return result.L;
1892 }
1893 }
1894 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001895 }
1896
1897 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001898 ScopedObjectAccess soa(env);
1899 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1900 JniValueType args[2] = {{.E = env}, {.t = obj}};
1901 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1902 JniValueType result;
1903 result.i = baseEnv(env)->Throw(env, obj);
1904 if (sc.Check(soa, false, "i", &result)) {
1905 return result.i;
1906 }
1907 }
1908 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001909 }
1910
Elliott Hughese84278b2012-03-22 10:06:53 -07001911 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001912 ScopedObjectAccess soa(env);
1913 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001914 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001915 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1916 JniValueType result;
1917 result.i = baseEnv(env)->ThrowNew(env, c, message);
1918 if (sc.Check(soa, false, "i", &result)) {
1919 return result.i;
1920 }
1921 }
1922 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001923 }
1924
1925 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001926 ScopedObjectAccess soa(env);
1927 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1928 JniValueType args[1] = {{.E = env}};
1929 if (sc.Check(soa, true, "E", args)) {
1930 JniValueType result;
1931 result.t = baseEnv(env)->ExceptionOccurred(env);
1932 if (sc.Check(soa, false, "t", &result)) {
1933 return result.t;
1934 }
1935 }
1936 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001937 }
1938
1939 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001940 ScopedObjectAccess soa(env);
1941 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1942 JniValueType args[1] = {{.E = env}};
1943 if (sc.Check(soa, true, "E", args)) {
1944 JniValueType result;
1945 baseEnv(env)->ExceptionDescribe(env);
1946 result.V = nullptr;
1947 sc.Check(soa, false, "V", &result);
1948 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001949 }
1950
1951 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001952 ScopedObjectAccess soa(env);
1953 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1954 JniValueType args[1] = {{.E = env}};
1955 if (sc.Check(soa, true, "E", args)) {
1956 JniValueType result;
1957 baseEnv(env)->ExceptionClear(env);
1958 result.V = nullptr;
1959 sc.Check(soa, false, "V", &result);
1960 }
1961 }
1962
1963 static jboolean ExceptionCheck(JNIEnv* env) {
1964 ScopedObjectAccess soa(env);
1965 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1966 JniValueType args[1] = {{.E = env}};
1967 if (sc.Check(soa, true, "E", args)) {
1968 JniValueType result;
1969 result.b = baseEnv(env)->ExceptionCheck(env);
1970 if (sc.Check(soa, false, "b", &result)) {
1971 return result.b;
1972 }
1973 }
1974 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001975 }
1976
1977 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001978 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1979 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1980 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001981 ScopedObjectAccess soa(env);
1982 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1983 JniValueType args[2] = {{.E = env}, {.u = msg}};
1984 if (sc.Check(soa, true, "Eu", args)) {
1985 JniValueType result;
1986 baseEnv(env)->FatalError(env, msg);
1987 // Unreachable.
1988 result.V = nullptr;
1989 sc.Check(soa, false, "V", &result);
1990 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001991 }
1992
1993 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001994 ScopedObjectAccess soa(env);
1995 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1996 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1997 if (sc.Check(soa, true, "EI", args)) {
1998 JniValueType result;
1999 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
2000 if (sc.Check(soa, false, "i", &result)) {
2001 return result.i;
2002 }
2003 }
2004 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002005 }
2006
2007 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002008 ScopedObjectAccess soa(env);
2009 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2010 JniValueType args[2] = {{.E = env}, {.L = res}};
2011 if (sc.Check(soa, true, "EL", args)) {
2012 JniValueType result;
2013 result.L = baseEnv(env)->PopLocalFrame(env, res);
2014 sc.Check(soa, false, "L", &result);
2015 return result.L;
2016 }
2017 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002018 }
2019
2020 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002021 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07002022 }
2023
Ian Rogers68d8b422014-07-17 11:09:10 -07002024 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
2025 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07002026 }
2027
2028 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002029 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07002030 }
2031
Ian Rogers68d8b422014-07-17 11:09:10 -07002032 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
2033 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07002034 }
2035
Ian Rogers68d8b422014-07-17 11:09:10 -07002036 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
2037 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
2038 }
2039
2040 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
2041 DeleteRef(__FUNCTION__, env, obj, kLocal);
2042 }
2043
2044 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
2045 ScopedObjectAccess soa(env);
2046 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2047 JniValueType args[2] = {{.E = env}, {.I = capacity}};
2048 if (sc.Check(soa, true, "EI", args)) {
2049 JniValueType result;
2050 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
2051 if (sc.Check(soa, false, "i", &result)) {
2052 return result.i;
2053 }
2054 }
2055 return JNI_ERR;
2056 }
2057
2058 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
2059 ScopedObjectAccess soa(env);
2060 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2061 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
2062 if (sc.Check(soa, true, "ELL", args)) {
2063 JniValueType result;
2064 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
2065 if (sc.Check(soa, false, "b", &result)) {
2066 return result.b;
2067 }
2068 }
2069 return JNI_FALSE;
2070 }
2071
2072 static jobject AllocObject(JNIEnv* env, jclass c) {
2073 ScopedObjectAccess soa(env);
2074 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2075 JniValueType args[2] = {{.E = env}, {.c = c}};
2076 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
2077 JniValueType result;
2078 result.L = baseEnv(env)->AllocObject(env, c);
2079 if (sc.Check(soa, false, "L", &result)) {
2080 return result.L;
2081 }
2082 }
2083 return nullptr;
2084 }
2085
2086 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2087 ScopedObjectAccess soa(env);
2088 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002089 VarArgs rest(mid, vargs);
2090 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2091 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002092 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002093 JniValueType result;
2094 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2095 if (sc.Check(soa, false, "L", &result)) {
2096 return result.L;
2097 }
2098 }
2099 return nullptr;
2100 }
2101
2102 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2103 va_list args;
2104 va_start(args, mid);
2105 jobject result = NewObjectV(env, c, mid, args);
2106 va_end(args);
2107 return result;
2108 }
2109
2110 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2111 ScopedObjectAccess soa(env);
2112 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002113 VarArgs rest(mid, vargs);
2114 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2115 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002116 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002117 JniValueType result;
2118 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2119 if (sc.Check(soa, false, "L", &result)) {
2120 return result.L;
2121 }
2122 }
2123 return nullptr;
2124 }
2125
2126 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2127 ScopedObjectAccess soa(env);
2128 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2129 JniValueType args[2] = {{.E = env}, {.L = obj}};
2130 if (sc.Check(soa, true, "EL", args)) {
2131 JniValueType result;
2132 result.c = baseEnv(env)->GetObjectClass(env, obj);
2133 if (sc.Check(soa, false, "c", &result)) {
2134 return result.c;
2135 }
2136 }
2137 return nullptr;
2138 }
2139
2140 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2141 ScopedObjectAccess soa(env);
2142 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2143 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2144 if (sc.Check(soa, true, "ELc", args)) {
2145 JniValueType result;
2146 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2147 if (sc.Check(soa, false, "b", &result)) {
2148 return result.b;
2149 }
2150 }
2151 return JNI_FALSE;
2152 }
2153
2154 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2155 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2156 }
2157
2158 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2159 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2160 }
2161
2162 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2163 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2164 }
2165
2166 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2167 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2168 }
2169
Ian Rogers9e937be2018-02-15 17:06:58 -08002170#define FIELD_ACCESSORS(jtype, name, ptype, shorty, slot_sized_shorty) \
Ian Rogers68d8b422014-07-17 11:09:10 -07002171 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2172 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2173 } \
2174 \
2175 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2176 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2177 } \
2178 \
2179 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2180 JniValueType value; \
Ian Rogers9e937be2018-02-15 17:06:58 -08002181 value.slot_sized_shorty = v; \
Ian Rogers68d8b422014-07-17 11:09:10 -07002182 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2183 } \
2184 \
2185 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2186 JniValueType value; \
Ian Rogers9e937be2018-02-15 17:06:58 -08002187 value.slot_sized_shorty = v; \
Ian Rogers68d8b422014-07-17 11:09:10 -07002188 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2189 }
2190
Ian Rogers9e937be2018-02-15 17:06:58 -08002191 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L, L)
2192 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z, I)
2193 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B, I)
2194 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C, I)
2195 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S, I)
2196 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I, I)
2197 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J, J)
2198 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F, F)
2199 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D, D)
Ian Rogers68d8b422014-07-17 11:09:10 -07002200#undef FIELD_ACCESSORS
2201
2202 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
2203 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2204 }
2205
2206 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2207 jvalue* vargs) {
2208 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2209 }
2210
2211 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01002212 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07002213 }
2214
2215 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2216 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2217 }
2218
2219 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2220 va_list vargs) {
2221 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2222 }
2223
2224 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2225 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2226 }
2227
2228 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2229 va_list vargs;
2230 va_start(vargs, mid);
2231 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2232 va_end(vargs);
2233 }
2234
2235 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2236 va_list vargs;
2237 va_start(vargs, mid);
2238 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2239 va_end(vargs);
2240 }
2241
2242 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2243 va_list vargs;
2244 va_start(vargs, mid);
2245 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2246 va_end(vargs);
2247 }
2248
2249#define CALL(rtype, name, ptype, shorty) \
2250 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
2251 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2252 } \
2253 \
2254 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2255 jvalue* vargs) { \
2256 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2257 } \
2258 \
2259 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2260 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2261 } \
2262 \
2263 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2264 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2265 } \
2266 \
2267 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2268 va_list vargs) { \
2269 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2270 } \
2271 \
2272 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2273 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2274 } \
2275 \
2276 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2277 va_list vargs; \
2278 va_start(vargs, mid); \
2279 rtype result = \
2280 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2281 va_end(vargs); \
2282 return result; \
2283 } \
2284 \
2285 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2286 ...) { \
2287 va_list vargs; \
2288 va_start(vargs, mid); \
2289 rtype result = \
2290 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2291 va_end(vargs); \
2292 return result; \
2293 } \
2294 \
2295 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2296 va_list vargs; \
2297 va_start(vargs, mid); \
2298 rtype result = \
2299 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2300 va_end(vargs); \
2301 return result; \
2302 }
2303
2304 CALL(jobject, Object, Primitive::kPrimNot, L)
2305 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2306 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2307 CALL(jchar, Char, Primitive::kPrimChar, C)
2308 CALL(jshort, Short, Primitive::kPrimShort, S)
2309 CALL(jint, Int, Primitive::kPrimInt, I)
2310 CALL(jlong, Long, Primitive::kPrimLong, J)
2311 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2312 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2313#undef CALL
2314
2315 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2316 ScopedObjectAccess soa(env);
2317 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2318 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2319 if (sc.Check(soa, true, "Epz", args)) {
2320 JniValueType result;
2321 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2322 if (sc.Check(soa, false, "s", &result)) {
2323 return result.s;
2324 }
2325 }
2326 return nullptr;
2327 }
2328
2329 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2330 ScopedObjectAccess soa(env);
2331 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2332 JniValueType args[2] = {{.E = env}, {.u = chars}};
2333 if (sc.Check(soa, true, "Eu", args)) {
2334 JniValueType result;
2335 // TODO: stale? show pointer and truncate string.
2336 result.s = baseEnv(env)->NewStringUTF(env, chars);
2337 if (sc.Check(soa, false, "s", &result)) {
2338 return result.s;
2339 }
2340 }
2341 return nullptr;
2342 }
2343
2344 static jsize GetStringLength(JNIEnv* env, jstring string) {
2345 ScopedObjectAccess soa(env);
2346 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2347 JniValueType args[2] = {{.E = env}, {.s = string}};
2348 if (sc.Check(soa, true, "Es", args)) {
2349 JniValueType result;
2350 result.z = baseEnv(env)->GetStringLength(env, string);
2351 if (sc.Check(soa, false, "z", &result)) {
2352 return result.z;
2353 }
2354 }
2355 return JNI_ERR;
2356 }
2357
2358 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2359 ScopedObjectAccess soa(env);
2360 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2361 JniValueType args[2] = {{.E = env}, {.s = string}};
2362 if (sc.Check(soa, true, "Es", args)) {
2363 JniValueType result;
2364 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2365 if (sc.Check(soa, false, "z", &result)) {
2366 return result.z;
2367 }
2368 }
2369 return JNI_ERR;
2370 }
2371
2372 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2373 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2374 is_copy, false, false));
2375 }
2376
2377 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2378 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2379 is_copy, true, false));
2380 }
2381
2382 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2383 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2384 is_copy, false, true));
2385 }
2386
2387 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2388 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2389 }
2390
2391 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2392 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2393 }
2394
2395 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2396 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2397 }
2398
2399 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2400 ScopedObjectAccess soa(env);
2401 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2402 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2403 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2404 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2405 if (sc.Check(soa, true, "EsIIp", args)) {
2406 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2407 JniValueType result;
2408 result.V = nullptr;
2409 sc.Check(soa, false, "V", &result);
2410 }
2411 }
2412
2413 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2414 ScopedObjectAccess soa(env);
2415 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2416 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2417 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2418 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2419 if (sc.Check(soa, true, "EsIIp", args)) {
2420 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2421 JniValueType result;
2422 result.V = nullptr;
2423 sc.Check(soa, false, "V", &result);
2424 }
2425 }
2426
2427 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2428 ScopedObjectAccess soa(env);
2429 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2430 JniValueType args[2] = {{.E = env}, {.a = array}};
2431 if (sc.Check(soa, true, "Ea", args)) {
2432 JniValueType result;
2433 result.z = baseEnv(env)->GetArrayLength(env, array);
2434 if (sc.Check(soa, false, "z", &result)) {
2435 return result.z;
2436 }
2437 }
2438 return JNI_ERR;
2439 }
2440
2441 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2442 jobject initial_element) {
2443 ScopedObjectAccess soa(env);
2444 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2445 JniValueType args[4] =
2446 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2447 if (sc.Check(soa, true, "EzcL", args)) {
2448 JniValueType result;
2449 // Note: assignability tests of initial_element are done in the base implementation.
2450 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2451 if (sc.Check(soa, false, "a", &result)) {
2452 return down_cast<jobjectArray>(result.a);
2453 }
2454 }
2455 return nullptr;
2456 }
2457
2458 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2459 ScopedObjectAccess soa(env);
2460 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2461 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2462 if (sc.Check(soa, true, "Eaz", args)) {
2463 JniValueType result;
2464 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2465 if (sc.Check(soa, false, "L", &result)) {
2466 return result.L;
2467 }
2468 }
2469 return nullptr;
2470 }
2471
2472 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2473 ScopedObjectAccess soa(env);
2474 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2475 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2476 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2477 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2478 // in ArrayStoreExceptions.
2479 if (sc.Check(soa, true, "EaIL", args)) {
2480 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2481 JniValueType result;
2482 result.V = nullptr;
2483 sc.Check(soa, false, "V", &result);
2484 }
2485 }
2486
2487 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2488 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2489 Primitive::kPrimBoolean));
2490 }
2491
2492 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2493 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2494 Primitive::kPrimByte));
2495 }
2496
2497 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2498 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2499 Primitive::kPrimChar));
2500 }
2501
2502 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2503 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2504 Primitive::kPrimShort));
2505 }
2506
2507 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2508 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2509 }
2510
2511 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2512 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2513 Primitive::kPrimLong));
2514 }
2515
2516 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2517 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2518 Primitive::kPrimFloat));
2519 }
2520
2521 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2522 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2523 Primitive::kPrimDouble));
2524 }
2525
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002526// NOLINT added to avoid wrong warning/fix from clang-tidy.
Ian Rogers68d8b422014-07-17 11:09:10 -07002527#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002528 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2529 return reinterpret_cast<ctype*>( /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002530 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2531 } \
2532 \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002533 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002534 jint mode) { \
2535 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2536 } \
2537 \
2538 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002539 ctype* buf) { /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002540 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2541 } \
2542 \
2543 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2544 const ctype* buf) { \
2545 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2546 }
2547
2548 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2549 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2550 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2551 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2552 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2553 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2554 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2555 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2556#undef PRIMITIVE_ARRAY_FUNCTIONS
2557
2558 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2559 ScopedObjectAccess soa(env);
2560 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2561 JniValueType args[2] = {{.E = env}, {.L = obj}};
2562 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002563 if (obj != nullptr) {
2564 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2565 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002566 JniValueType result;
2567 result.i = baseEnv(env)->MonitorEnter(env, obj);
2568 if (sc.Check(soa, false, "i", &result)) {
2569 return result.i;
2570 }
2571 }
2572 return JNI_ERR;
2573 }
2574
2575 static jint MonitorExit(JNIEnv* env, jobject obj) {
2576 ScopedObjectAccess soa(env);
2577 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2578 JniValueType args[2] = {{.E = env}, {.L = obj}};
2579 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002580 if (obj != nullptr) {
2581 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2582 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002583 JniValueType result;
2584 result.i = baseEnv(env)->MonitorExit(env, obj);
2585 if (sc.Check(soa, false, "i", &result)) {
2586 return result.i;
2587 }
2588 }
2589 return JNI_ERR;
2590 }
2591
2592 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2593 ScopedObjectAccess soa(env);
2594 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2595 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2596 if (sc.Check(soa, true, "Eap", args)) {
2597 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002598 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2599 if (ptr != nullptr && soa.ForceCopy()) {
2600 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002601 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002602 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002603 if (sc.Check(soa, false, "p", &result)) {
2604 return const_cast<void*>(result.p);
2605 }
2606 }
2607 return nullptr;
2608 }
2609
2610 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2611 ScopedObjectAccess soa(env);
2612 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2613 sc.CheckNonNull(carray);
2614 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2615 if (sc.Check(soa, true, "Eapr", args)) {
2616 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002617 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002618 }
2619 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2620 JniValueType result;
2621 result.V = nullptr;
2622 sc.Check(soa, false, "V", &result);
2623 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002624 }
2625
2626 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002627 ScopedObjectAccess soa(env);
2628 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2629 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2630 if (sc.Check(soa, true, "EpJ", args)) {
2631 JniValueType result;
2632 // Note: the validity of address and capacity are checked in the base implementation.
2633 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2634 if (sc.Check(soa, false, "L", &result)) {
2635 return result.L;
2636 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002637 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002638 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002639 }
2640
2641 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002642 ScopedObjectAccess soa(env);
2643 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2644 JniValueType args[2] = {{.E = env}, {.L = buf}};
2645 if (sc.Check(soa, true, "EL", args)) {
2646 JniValueType result;
2647 // Note: this is implemented in the base environment by a GetLongField which will sanity
2648 // check the type of buf in GetLongField above.
2649 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2650 if (sc.Check(soa, false, "p", &result)) {
2651 return const_cast<void*>(result.p);
2652 }
2653 }
2654 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002655 }
2656
2657 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002658 ScopedObjectAccess soa(env);
2659 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2660 JniValueType args[2] = {{.E = env}, {.L = buf}};
2661 if (sc.Check(soa, true, "EL", args)) {
2662 JniValueType result;
2663 // Note: this is implemented in the base environment by a GetIntField which will sanity
2664 // check the type of buf in GetIntField above.
2665 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2666 if (sc.Check(soa, false, "J", &result)) {
2667 return result.J;
2668 }
2669 }
2670 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002671 }
2672
2673 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002674 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
Ian Rogers55256cb2017-12-21 17:07:11 -08002675 return reinterpret_cast<JNIEnvExt*>(env)->GetVm();
Ian Rogers68d8b422014-07-17 11:09:10 -07002676 }
2677
2678 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Ian Rogersac4d45a2018-02-15 11:19:01 -08002679 return reinterpret_cast<JNIEnvExt*>(env)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07002680 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002681
2682 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2683 ScopedObjectAccess soa(env);
2684 ScopedCheck sc(kFlag_Default, function_name);
2685 JniValueType args[2] = {{.E = env}, {.L = obj}};
2686 if (sc.Check(soa, true, "EL", args)) {
2687 JniValueType result;
2688 switch (kind) {
2689 case kGlobal:
2690 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2691 break;
2692 case kLocal:
2693 result.L = baseEnv(env)->NewLocalRef(env, obj);
2694 break;
2695 case kWeakGlobal:
2696 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2697 break;
2698 default:
2699 LOG(FATAL) << "Unexpected reference kind: " << kind;
2700 }
2701 if (sc.Check(soa, false, "L", &result)) {
2702 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002703 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002704 return result.L;
2705 }
2706 }
2707 return nullptr;
2708 }
2709
2710 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2711 ScopedObjectAccess soa(env);
2712 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2713 JniValueType args[2] = {{.E = env}, {.L = obj}};
2714 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002715 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002716 JniValueType result;
2717 switch (kind) {
2718 case kGlobal:
2719 baseEnv(env)->DeleteGlobalRef(env, obj);
2720 break;
2721 case kLocal:
2722 baseEnv(env)->DeleteLocalRef(env, obj);
2723 break;
2724 case kWeakGlobal:
2725 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2726 break;
2727 default:
2728 LOG(FATAL) << "Unexpected reference kind: " << kind;
2729 }
2730 result.V = nullptr;
2731 sc.Check(soa, false, "V", &result);
2732 }
2733 }
2734
2735 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2736 const char* name, const char* sig, bool is_static) {
2737 ScopedObjectAccess soa(env);
2738 ScopedCheck sc(kFlag_Default, function_name);
2739 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2740 if (sc.Check(soa, true, "Ecuu", args)) {
2741 JniValueType result;
2742 if (is_static) {
2743 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2744 } else {
2745 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2746 }
2747 if (sc.Check(soa, false, "m", &result)) {
2748 return result.m;
2749 }
2750 }
2751 return nullptr;
2752 }
2753
2754 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2755 const char* name, const char* sig, bool is_static) {
2756 ScopedObjectAccess soa(env);
2757 ScopedCheck sc(kFlag_Default, function_name);
2758 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2759 if (sc.Check(soa, true, "Ecuu", args)) {
2760 JniValueType result;
2761 if (is_static) {
2762 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2763 } else {
2764 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2765 }
2766 if (sc.Check(soa, false, "f", &result)) {
2767 return result.f;
2768 }
2769 }
2770 return nullptr;
2771 }
2772
2773 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2774 bool is_static, Primitive::Type type) {
2775 ScopedObjectAccess soa(env);
2776 ScopedCheck sc(kFlag_Default, function_name);
2777 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2778 JniValueType result;
2779 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2780 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2781 const char* result_check = nullptr;
2782 switch (type) {
2783 case Primitive::kPrimNot:
2784 if (is_static) {
2785 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2786 } else {
2787 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2788 }
2789 result_check = "L";
2790 break;
2791 case Primitive::kPrimBoolean:
2792 if (is_static) {
2793 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2794 } else {
2795 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2796 }
2797 result_check = "Z";
2798 break;
2799 case Primitive::kPrimByte:
2800 if (is_static) {
2801 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2802 } else {
2803 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2804 }
2805 result_check = "B";
2806 break;
2807 case Primitive::kPrimChar:
2808 if (is_static) {
2809 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2810 } else {
2811 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2812 }
2813 result_check = "C";
2814 break;
2815 case Primitive::kPrimShort:
2816 if (is_static) {
2817 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2818 } else {
2819 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2820 }
2821 result_check = "S";
2822 break;
2823 case Primitive::kPrimInt:
2824 if (is_static) {
2825 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2826 } else {
2827 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2828 }
2829 result_check = "I";
2830 break;
2831 case Primitive::kPrimLong:
2832 if (is_static) {
2833 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2834 } else {
2835 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2836 }
2837 result_check = "J";
2838 break;
2839 case Primitive::kPrimFloat:
2840 if (is_static) {
2841 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2842 } else {
2843 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2844 }
2845 result_check = "F";
2846 break;
2847 case Primitive::kPrimDouble:
2848 if (is_static) {
2849 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2850 } else {
2851 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2852 }
2853 result_check = "D";
2854 break;
2855 case Primitive::kPrimVoid:
2856 LOG(FATAL) << "Unexpected type: " << type;
2857 break;
2858 }
2859 if (sc.Check(soa, false, result_check, &result)) {
2860 return result;
2861 }
2862 }
2863 result.J = 0;
2864 return result;
2865 }
2866
2867 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2868 bool is_static, Primitive::Type type, JniValueType value) {
2869 ScopedObjectAccess soa(env);
2870 ScopedCheck sc(kFlag_Default, function_name);
2871 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2872 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2873 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2874 if (sc.Check(soa, true, sig, args) &&
2875 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2876 switch (type) {
2877 case Primitive::kPrimNot:
2878 if (is_static) {
2879 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2880 } else {
2881 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2882 }
2883 break;
2884 case Primitive::kPrimBoolean:
2885 if (is_static) {
2886 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2887 } else {
2888 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2889 }
2890 break;
2891 case Primitive::kPrimByte:
2892 if (is_static) {
2893 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2894 } else {
2895 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2896 }
2897 break;
2898 case Primitive::kPrimChar:
2899 if (is_static) {
2900 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2901 } else {
2902 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2903 }
2904 break;
2905 case Primitive::kPrimShort:
2906 if (is_static) {
2907 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2908 } else {
2909 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2910 }
2911 break;
2912 case Primitive::kPrimInt:
2913 if (is_static) {
2914 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2915 } else {
2916 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2917 }
2918 break;
2919 case Primitive::kPrimLong:
2920 if (is_static) {
2921 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2922 } else {
2923 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2924 }
2925 break;
2926 case Primitive::kPrimFloat:
2927 if (is_static) {
2928 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2929 } else {
2930 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2931 }
2932 break;
2933 case Primitive::kPrimDouble:
2934 if (is_static) {
2935 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2936 } else {
2937 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2938 }
2939 break;
2940 case Primitive::kPrimVoid:
2941 LOG(FATAL) << "Unexpected type: " << type;
2942 break;
2943 }
2944 JniValueType result;
2945 result.V = nullptr;
2946 sc.Check(soa, false, "V", &result);
2947 }
2948 }
2949
2950 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
Alex Light48ffe062015-08-19 15:23:23 -07002951 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07002952 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002953 bool checked;
2954 switch (invoke) {
2955 case kVirtual: {
2956 DCHECK(c == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002957 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
2958 checked = sc.Check(soa, true, "ELm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002959 break;
2960 }
2961 case kDirect: {
Alex Light48ffe062015-08-19 15:23:23 -07002962 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
2963 checked = sc.Check(soa, true, "ELcm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002964 break;
2965 }
2966 case kStatic: {
2967 DCHECK(obj == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002968 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
2969 checked = sc.Check(soa, true, "Ecm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002970 break;
2971 }
2972 default:
2973 LOG(FATAL) << "Unexpected invoke: " << invoke;
2974 checked = false;
2975 break;
2976 }
2977 return checked;
2978 }
2979
2980 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2981 jmethodID mid, jvalue* vargs, Primitive::Type type,
2982 InvokeType invoke) {
2983 ScopedObjectAccess soa(env);
2984 ScopedCheck sc(kFlag_Default, function_name);
2985 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07002986 VarArgs rest(mid, vargs);
2987 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07002988 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2989 const char* result_check;
2990 switch (type) {
2991 case Primitive::kPrimNot:
2992 result_check = "L";
2993 switch (invoke) {
2994 case kVirtual:
2995 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2996 break;
2997 case kDirect:
2998 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2999 break;
3000 case kStatic:
3001 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
3002 break;
3003 default:
3004 break;
3005 }
3006 break;
3007 case Primitive::kPrimBoolean:
3008 result_check = "Z";
3009 switch (invoke) {
3010 case kVirtual:
3011 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
3012 break;
3013 case kDirect:
3014 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
3015 break;
3016 case kStatic:
3017 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
3018 break;
3019 default:
3020 break;
3021 }
3022 break;
3023 case Primitive::kPrimByte:
3024 result_check = "B";
3025 switch (invoke) {
3026 case kVirtual:
3027 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
3028 break;
3029 case kDirect:
3030 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
3031 break;
3032 case kStatic:
3033 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
3034 break;
3035 default:
3036 break;
3037 }
3038 break;
3039 case Primitive::kPrimChar:
3040 result_check = "C";
3041 switch (invoke) {
3042 case kVirtual:
3043 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
3044 break;
3045 case kDirect:
3046 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
3047 break;
3048 case kStatic:
3049 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
3050 break;
3051 default:
3052 break;
3053 }
3054 break;
3055 case Primitive::kPrimShort:
3056 result_check = "S";
3057 switch (invoke) {
3058 case kVirtual:
3059 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
3060 break;
3061 case kDirect:
3062 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
3063 break;
3064 case kStatic:
3065 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
3066 break;
3067 default:
3068 break;
3069 }
3070 break;
3071 case Primitive::kPrimInt:
3072 result_check = "I";
3073 switch (invoke) {
3074 case kVirtual:
3075 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
3076 break;
3077 case kDirect:
3078 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
3079 break;
3080 case kStatic:
3081 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
3082 break;
3083 default:
3084 break;
3085 }
3086 break;
3087 case Primitive::kPrimLong:
3088 result_check = "J";
3089 switch (invoke) {
3090 case kVirtual:
3091 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
3092 break;
3093 case kDirect:
3094 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3095 break;
3096 case kStatic:
3097 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3098 break;
3099 default:
3100 break;
3101 }
3102 break;
3103 case Primitive::kPrimFloat:
3104 result_check = "F";
3105 switch (invoke) {
3106 case kVirtual:
3107 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3108 break;
3109 case kDirect:
3110 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3111 break;
3112 case kStatic:
3113 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3114 break;
3115 default:
3116 break;
3117 }
3118 break;
3119 case Primitive::kPrimDouble:
3120 result_check = "D";
3121 switch (invoke) {
3122 case kVirtual:
3123 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3124 break;
3125 case kDirect:
3126 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3127 break;
3128 case kStatic:
3129 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3130 break;
3131 default:
3132 break;
3133 }
3134 break;
3135 case Primitive::kPrimVoid:
3136 result_check = "V";
3137 result.V = nullptr;
3138 switch (invoke) {
3139 case kVirtual:
3140 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3141 break;
3142 case kDirect:
3143 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3144 break;
3145 case kStatic:
3146 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3147 break;
3148 default:
3149 LOG(FATAL) << "Unexpected invoke: " << invoke;
3150 }
3151 break;
3152 default:
3153 LOG(FATAL) << "Unexpected return type: " << type;
3154 result_check = nullptr;
3155 }
3156 if (sc.Check(soa, false, result_check, &result)) {
3157 return result;
3158 }
3159 }
3160 result.J = 0;
3161 return result;
3162 }
3163
3164 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3165 jmethodID mid, va_list vargs, Primitive::Type type,
3166 InvokeType invoke) {
3167 ScopedObjectAccess soa(env);
3168 ScopedCheck sc(kFlag_Default, function_name);
3169 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003170 VarArgs rest(mid, vargs);
3171 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003172 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3173 const char* result_check;
3174 switch (type) {
3175 case Primitive::kPrimNot:
3176 result_check = "L";
3177 switch (invoke) {
3178 case kVirtual:
3179 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3180 break;
3181 case kDirect:
3182 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3183 break;
3184 case kStatic:
3185 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3186 break;
3187 default:
3188 LOG(FATAL) << "Unexpected invoke: " << invoke;
3189 }
3190 break;
3191 case Primitive::kPrimBoolean:
3192 result_check = "Z";
3193 switch (invoke) {
3194 case kVirtual:
3195 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3196 break;
3197 case kDirect:
3198 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3199 break;
3200 case kStatic:
3201 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3202 break;
3203 default:
3204 LOG(FATAL) << "Unexpected invoke: " << invoke;
3205 }
3206 break;
3207 case Primitive::kPrimByte:
3208 result_check = "B";
3209 switch (invoke) {
3210 case kVirtual:
3211 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3212 break;
3213 case kDirect:
3214 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3215 break;
3216 case kStatic:
3217 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3218 break;
3219 default:
3220 LOG(FATAL) << "Unexpected invoke: " << invoke;
3221 }
3222 break;
3223 case Primitive::kPrimChar:
3224 result_check = "C";
3225 switch (invoke) {
3226 case kVirtual:
3227 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3228 break;
3229 case kDirect:
3230 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3231 break;
3232 case kStatic:
3233 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3234 break;
3235 default:
3236 LOG(FATAL) << "Unexpected invoke: " << invoke;
3237 }
3238 break;
3239 case Primitive::kPrimShort:
3240 result_check = "S";
3241 switch (invoke) {
3242 case kVirtual:
3243 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3244 break;
3245 case kDirect:
3246 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3247 break;
3248 case kStatic:
3249 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3250 break;
3251 default:
3252 LOG(FATAL) << "Unexpected invoke: " << invoke;
3253 }
3254 break;
3255 case Primitive::kPrimInt:
3256 result_check = "I";
3257 switch (invoke) {
3258 case kVirtual:
3259 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3260 break;
3261 case kDirect:
3262 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3263 break;
3264 case kStatic:
3265 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3266 break;
3267 default:
3268 LOG(FATAL) << "Unexpected invoke: " << invoke;
3269 }
3270 break;
3271 case Primitive::kPrimLong:
3272 result_check = "J";
3273 switch (invoke) {
3274 case kVirtual:
3275 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3276 break;
3277 case kDirect:
3278 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3279 break;
3280 case kStatic:
3281 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3282 break;
3283 default:
3284 LOG(FATAL) << "Unexpected invoke: " << invoke;
3285 }
3286 break;
3287 case Primitive::kPrimFloat:
3288 result_check = "F";
3289 switch (invoke) {
3290 case kVirtual:
3291 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3292 break;
3293 case kDirect:
3294 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3295 break;
3296 case kStatic:
3297 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3298 break;
3299 default:
3300 LOG(FATAL) << "Unexpected invoke: " << invoke;
3301 }
3302 break;
3303 case Primitive::kPrimDouble:
3304 result_check = "D";
3305 switch (invoke) {
3306 case kVirtual:
3307 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3308 break;
3309 case kDirect:
3310 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3311 break;
3312 case kStatic:
3313 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3314 break;
3315 default:
3316 LOG(FATAL) << "Unexpected invoke: " << invoke;
3317 }
3318 break;
3319 case Primitive::kPrimVoid:
3320 result_check = "V";
3321 result.V = nullptr;
3322 switch (invoke) {
3323 case kVirtual:
3324 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3325 break;
3326 case kDirect:
3327 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3328 break;
3329 case kStatic:
3330 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3331 break;
3332 default:
3333 LOG(FATAL) << "Unexpected invoke: " << invoke;
3334 }
3335 break;
3336 default:
3337 LOG(FATAL) << "Unexpected return type: " << type;
3338 result_check = nullptr;
3339 }
3340 if (sc.Check(soa, false, result_check, &result)) {
3341 return result;
3342 }
3343 }
3344 result.J = 0;
3345 return result;
3346 }
3347
3348 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3349 jboolean* is_copy, bool utf, bool critical) {
3350 ScopedObjectAccess soa(env);
3351 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3352 ScopedCheck sc(flags, function_name);
3353 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3354 if (sc.Check(soa, true, "Esp", args)) {
3355 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003356 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003357 if (utf) {
3358 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003359 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3360 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003361 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003362 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3363 baseEnv(env)->GetStringChars(env, string, is_copy));
3364 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003365 }
3366 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003367 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003368 if (utf) {
3369 size_t length_in_bytes = strlen(result.u) + 1;
3370 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003371 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003372 } else {
3373 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3374 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003375 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003376 }
3377 if (is_copy != nullptr) {
3378 *is_copy = JNI_TRUE;
3379 }
3380 }
3381 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3382 return utf ? result.u : result.p;
3383 }
3384 }
3385 return nullptr;
3386 }
3387
3388 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3389 const void* chars, bool utf, bool critical) {
3390 ScopedObjectAccess soa(env);
3391 int flags = kFlag_ExcepOkay | kFlag_Release;
3392 if (critical) {
3393 flags |= kFlag_CritRelease;
3394 }
3395 ScopedCheck sc(flags, function_name);
3396 sc.CheckNonNull(chars);
3397 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3398 if (force_copy_ok && soa.ForceCopy()) {
3399 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3400 }
3401 if (force_copy_ok) {
3402 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3403 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3404 if (utf) {
3405 CHECK(!critical);
3406 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3407 } else {
3408 if (critical) {
3409 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3410 } else {
3411 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3412 }
3413 }
3414 JniValueType result;
3415 sc.Check(soa, false, "V", &result);
3416 }
3417 }
3418 }
3419
3420 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3421 Primitive::Type type) {
3422 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003423 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003424 JniValueType args[2] = {{.E = env}, {.z = length}};
3425 if (sc.Check(soa, true, "Ez", args)) {
3426 JniValueType result;
3427 switch (type) {
3428 case Primitive::kPrimBoolean:
3429 result.a = baseEnv(env)->NewBooleanArray(env, length);
3430 break;
3431 case Primitive::kPrimByte:
3432 result.a = baseEnv(env)->NewByteArray(env, length);
3433 break;
3434 case Primitive::kPrimChar:
3435 result.a = baseEnv(env)->NewCharArray(env, length);
3436 break;
3437 case Primitive::kPrimShort:
3438 result.a = baseEnv(env)->NewShortArray(env, length);
3439 break;
3440 case Primitive::kPrimInt:
3441 result.a = baseEnv(env)->NewIntArray(env, length);
3442 break;
3443 case Primitive::kPrimLong:
3444 result.a = baseEnv(env)->NewLongArray(env, length);
3445 break;
3446 case Primitive::kPrimFloat:
3447 result.a = baseEnv(env)->NewFloatArray(env, length);
3448 break;
3449 case Primitive::kPrimDouble:
3450 result.a = baseEnv(env)->NewDoubleArray(env, length);
3451 break;
3452 default:
3453 LOG(FATAL) << "Unexpected primitive type: " << type;
3454 }
3455 if (sc.Check(soa, false, "a", &result)) {
3456 return result.a;
3457 }
3458 }
3459 return nullptr;
3460 }
3461
3462 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3463 JNIEnv* env, jarray array, jboolean* is_copy) {
3464 ScopedObjectAccess soa(env);
3465 ScopedCheck sc(kFlag_Default, function_name);
3466 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3467 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3468 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003469 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003470 switch (type) {
3471 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003472 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3473 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003474 break;
3475 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003476 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003477 break;
3478 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003479 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003480 break;
3481 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003482 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003483 break;
3484 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003485 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003486 break;
3487 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003488 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003489 break;
3490 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003491 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003492 break;
3493 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003494 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003495 break;
3496 default:
3497 LOG(FATAL) << "Unexpected primitive type: " << type;
3498 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003499 if (ptr != nullptr && soa.ForceCopy()) {
3500 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003501 if (is_copy != nullptr) {
3502 *is_copy = JNI_TRUE;
3503 }
3504 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003505 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003506 if (sc.Check(soa, false, "p", &result)) {
3507 return const_cast<void*>(result.p);
3508 }
3509 }
3510 return nullptr;
3511 }
3512
3513 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3514 JNIEnv* env, jarray array, void* elems, jint mode) {
3515 ScopedObjectAccess soa(env);
3516 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3517 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3518 if (soa.ForceCopy()) {
3519 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3520 }
3521 if (!soa.ForceCopy() || elems != nullptr) {
3522 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3523 if (sc.Check(soa, true, "Eapr", args)) {
3524 switch (type) {
3525 case Primitive::kPrimBoolean:
3526 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3527 reinterpret_cast<jboolean*>(elems), mode);
3528 break;
3529 case Primitive::kPrimByte:
3530 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3531 reinterpret_cast<jbyte*>(elems), mode);
3532 break;
3533 case Primitive::kPrimChar:
3534 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3535 reinterpret_cast<jchar*>(elems), mode);
3536 break;
3537 case Primitive::kPrimShort:
3538 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3539 reinterpret_cast<jshort*>(elems), mode);
3540 break;
3541 case Primitive::kPrimInt:
3542 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3543 reinterpret_cast<jint*>(elems), mode);
3544 break;
3545 case Primitive::kPrimLong:
3546 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3547 reinterpret_cast<jlong*>(elems), mode);
3548 break;
3549 case Primitive::kPrimFloat:
3550 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3551 reinterpret_cast<jfloat*>(elems), mode);
3552 break;
3553 case Primitive::kPrimDouble:
3554 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3555 reinterpret_cast<jdouble*>(elems), mode);
3556 break;
3557 default:
3558 LOG(FATAL) << "Unexpected primitive type: " << type;
3559 }
3560 JniValueType result;
3561 result.V = nullptr;
3562 sc.Check(soa, false, "V", &result);
3563 }
3564 }
3565 }
3566 }
3567
3568 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3569 jarray array, jsize start, jsize len, void* buf) {
3570 ScopedObjectAccess soa(env);
3571 ScopedCheck sc(kFlag_Default, function_name);
3572 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3573 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3574 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3575 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3576 switch (type) {
3577 case Primitive::kPrimBoolean:
3578 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3579 reinterpret_cast<jboolean*>(buf));
3580 break;
3581 case Primitive::kPrimByte:
3582 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3583 reinterpret_cast<jbyte*>(buf));
3584 break;
3585 case Primitive::kPrimChar:
3586 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3587 reinterpret_cast<jchar*>(buf));
3588 break;
3589 case Primitive::kPrimShort:
3590 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3591 reinterpret_cast<jshort*>(buf));
3592 break;
3593 case Primitive::kPrimInt:
3594 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3595 reinterpret_cast<jint*>(buf));
3596 break;
3597 case Primitive::kPrimLong:
3598 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3599 reinterpret_cast<jlong*>(buf));
3600 break;
3601 case Primitive::kPrimFloat:
3602 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3603 reinterpret_cast<jfloat*>(buf));
3604 break;
3605 case Primitive::kPrimDouble:
3606 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3607 reinterpret_cast<jdouble*>(buf));
3608 break;
3609 default:
3610 LOG(FATAL) << "Unexpected primitive type: " << type;
3611 }
3612 JniValueType result;
3613 result.V = nullptr;
3614 sc.Check(soa, false, "V", &result);
3615 }
3616 }
3617
3618 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3619 jarray array, jsize start, jsize len, const void* buf) {
3620 ScopedObjectAccess soa(env);
3621 ScopedCheck sc(kFlag_Default, function_name);
3622 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3623 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3624 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3625 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3626 switch (type) {
3627 case Primitive::kPrimBoolean:
3628 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3629 reinterpret_cast<const jboolean*>(buf));
3630 break;
3631 case Primitive::kPrimByte:
3632 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3633 reinterpret_cast<const jbyte*>(buf));
3634 break;
3635 case Primitive::kPrimChar:
3636 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3637 reinterpret_cast<const jchar*>(buf));
3638 break;
3639 case Primitive::kPrimShort:
3640 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3641 reinterpret_cast<const jshort*>(buf));
3642 break;
3643 case Primitive::kPrimInt:
3644 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3645 reinterpret_cast<const jint*>(buf));
3646 break;
3647 case Primitive::kPrimLong:
3648 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3649 reinterpret_cast<const jlong*>(buf));
3650 break;
3651 case Primitive::kPrimFloat:
3652 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3653 reinterpret_cast<const jfloat*>(buf));
3654 break;
3655 case Primitive::kPrimDouble:
3656 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3657 reinterpret_cast<const jdouble*>(buf));
3658 break;
3659 default:
3660 LOG(FATAL) << "Unexpected primitive type: " << type;
3661 }
3662 JniValueType result;
3663 result.V = nullptr;
3664 sc.Check(soa, false, "V", &result);
3665 }
3666 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003667};
3668
3669const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003670 nullptr, // reserved0.
3671 nullptr, // reserved1.
3672 nullptr, // reserved2.
3673 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003674 CheckJNI::GetVersion,
3675 CheckJNI::DefineClass,
3676 CheckJNI::FindClass,
3677 CheckJNI::FromReflectedMethod,
3678 CheckJNI::FromReflectedField,
3679 CheckJNI::ToReflectedMethod,
3680 CheckJNI::GetSuperclass,
3681 CheckJNI::IsAssignableFrom,
3682 CheckJNI::ToReflectedField,
3683 CheckJNI::Throw,
3684 CheckJNI::ThrowNew,
3685 CheckJNI::ExceptionOccurred,
3686 CheckJNI::ExceptionDescribe,
3687 CheckJNI::ExceptionClear,
3688 CheckJNI::FatalError,
3689 CheckJNI::PushLocalFrame,
3690 CheckJNI::PopLocalFrame,
3691 CheckJNI::NewGlobalRef,
3692 CheckJNI::DeleteGlobalRef,
3693 CheckJNI::DeleteLocalRef,
3694 CheckJNI::IsSameObject,
3695 CheckJNI::NewLocalRef,
3696 CheckJNI::EnsureLocalCapacity,
3697 CheckJNI::AllocObject,
3698 CheckJNI::NewObject,
3699 CheckJNI::NewObjectV,
3700 CheckJNI::NewObjectA,
3701 CheckJNI::GetObjectClass,
3702 CheckJNI::IsInstanceOf,
3703 CheckJNI::GetMethodID,
3704 CheckJNI::CallObjectMethod,
3705 CheckJNI::CallObjectMethodV,
3706 CheckJNI::CallObjectMethodA,
3707 CheckJNI::CallBooleanMethod,
3708 CheckJNI::CallBooleanMethodV,
3709 CheckJNI::CallBooleanMethodA,
3710 CheckJNI::CallByteMethod,
3711 CheckJNI::CallByteMethodV,
3712 CheckJNI::CallByteMethodA,
3713 CheckJNI::CallCharMethod,
3714 CheckJNI::CallCharMethodV,
3715 CheckJNI::CallCharMethodA,
3716 CheckJNI::CallShortMethod,
3717 CheckJNI::CallShortMethodV,
3718 CheckJNI::CallShortMethodA,
3719 CheckJNI::CallIntMethod,
3720 CheckJNI::CallIntMethodV,
3721 CheckJNI::CallIntMethodA,
3722 CheckJNI::CallLongMethod,
3723 CheckJNI::CallLongMethodV,
3724 CheckJNI::CallLongMethodA,
3725 CheckJNI::CallFloatMethod,
3726 CheckJNI::CallFloatMethodV,
3727 CheckJNI::CallFloatMethodA,
3728 CheckJNI::CallDoubleMethod,
3729 CheckJNI::CallDoubleMethodV,
3730 CheckJNI::CallDoubleMethodA,
3731 CheckJNI::CallVoidMethod,
3732 CheckJNI::CallVoidMethodV,
3733 CheckJNI::CallVoidMethodA,
3734 CheckJNI::CallNonvirtualObjectMethod,
3735 CheckJNI::CallNonvirtualObjectMethodV,
3736 CheckJNI::CallNonvirtualObjectMethodA,
3737 CheckJNI::CallNonvirtualBooleanMethod,
3738 CheckJNI::CallNonvirtualBooleanMethodV,
3739 CheckJNI::CallNonvirtualBooleanMethodA,
3740 CheckJNI::CallNonvirtualByteMethod,
3741 CheckJNI::CallNonvirtualByteMethodV,
3742 CheckJNI::CallNonvirtualByteMethodA,
3743 CheckJNI::CallNonvirtualCharMethod,
3744 CheckJNI::CallNonvirtualCharMethodV,
3745 CheckJNI::CallNonvirtualCharMethodA,
3746 CheckJNI::CallNonvirtualShortMethod,
3747 CheckJNI::CallNonvirtualShortMethodV,
3748 CheckJNI::CallNonvirtualShortMethodA,
3749 CheckJNI::CallNonvirtualIntMethod,
3750 CheckJNI::CallNonvirtualIntMethodV,
3751 CheckJNI::CallNonvirtualIntMethodA,
3752 CheckJNI::CallNonvirtualLongMethod,
3753 CheckJNI::CallNonvirtualLongMethodV,
3754 CheckJNI::CallNonvirtualLongMethodA,
3755 CheckJNI::CallNonvirtualFloatMethod,
3756 CheckJNI::CallNonvirtualFloatMethodV,
3757 CheckJNI::CallNonvirtualFloatMethodA,
3758 CheckJNI::CallNonvirtualDoubleMethod,
3759 CheckJNI::CallNonvirtualDoubleMethodV,
3760 CheckJNI::CallNonvirtualDoubleMethodA,
3761 CheckJNI::CallNonvirtualVoidMethod,
3762 CheckJNI::CallNonvirtualVoidMethodV,
3763 CheckJNI::CallNonvirtualVoidMethodA,
3764 CheckJNI::GetFieldID,
3765 CheckJNI::GetObjectField,
3766 CheckJNI::GetBooleanField,
3767 CheckJNI::GetByteField,
3768 CheckJNI::GetCharField,
3769 CheckJNI::GetShortField,
3770 CheckJNI::GetIntField,
3771 CheckJNI::GetLongField,
3772 CheckJNI::GetFloatField,
3773 CheckJNI::GetDoubleField,
3774 CheckJNI::SetObjectField,
3775 CheckJNI::SetBooleanField,
3776 CheckJNI::SetByteField,
3777 CheckJNI::SetCharField,
3778 CheckJNI::SetShortField,
3779 CheckJNI::SetIntField,
3780 CheckJNI::SetLongField,
3781 CheckJNI::SetFloatField,
3782 CheckJNI::SetDoubleField,
3783 CheckJNI::GetStaticMethodID,
3784 CheckJNI::CallStaticObjectMethod,
3785 CheckJNI::CallStaticObjectMethodV,
3786 CheckJNI::CallStaticObjectMethodA,
3787 CheckJNI::CallStaticBooleanMethod,
3788 CheckJNI::CallStaticBooleanMethodV,
3789 CheckJNI::CallStaticBooleanMethodA,
3790 CheckJNI::CallStaticByteMethod,
3791 CheckJNI::CallStaticByteMethodV,
3792 CheckJNI::CallStaticByteMethodA,
3793 CheckJNI::CallStaticCharMethod,
3794 CheckJNI::CallStaticCharMethodV,
3795 CheckJNI::CallStaticCharMethodA,
3796 CheckJNI::CallStaticShortMethod,
3797 CheckJNI::CallStaticShortMethodV,
3798 CheckJNI::CallStaticShortMethodA,
3799 CheckJNI::CallStaticIntMethod,
3800 CheckJNI::CallStaticIntMethodV,
3801 CheckJNI::CallStaticIntMethodA,
3802 CheckJNI::CallStaticLongMethod,
3803 CheckJNI::CallStaticLongMethodV,
3804 CheckJNI::CallStaticLongMethodA,
3805 CheckJNI::CallStaticFloatMethod,
3806 CheckJNI::CallStaticFloatMethodV,
3807 CheckJNI::CallStaticFloatMethodA,
3808 CheckJNI::CallStaticDoubleMethod,
3809 CheckJNI::CallStaticDoubleMethodV,
3810 CheckJNI::CallStaticDoubleMethodA,
3811 CheckJNI::CallStaticVoidMethod,
3812 CheckJNI::CallStaticVoidMethodV,
3813 CheckJNI::CallStaticVoidMethodA,
3814 CheckJNI::GetStaticFieldID,
3815 CheckJNI::GetStaticObjectField,
3816 CheckJNI::GetStaticBooleanField,
3817 CheckJNI::GetStaticByteField,
3818 CheckJNI::GetStaticCharField,
3819 CheckJNI::GetStaticShortField,
3820 CheckJNI::GetStaticIntField,
3821 CheckJNI::GetStaticLongField,
3822 CheckJNI::GetStaticFloatField,
3823 CheckJNI::GetStaticDoubleField,
3824 CheckJNI::SetStaticObjectField,
3825 CheckJNI::SetStaticBooleanField,
3826 CheckJNI::SetStaticByteField,
3827 CheckJNI::SetStaticCharField,
3828 CheckJNI::SetStaticShortField,
3829 CheckJNI::SetStaticIntField,
3830 CheckJNI::SetStaticLongField,
3831 CheckJNI::SetStaticFloatField,
3832 CheckJNI::SetStaticDoubleField,
3833 CheckJNI::NewString,
3834 CheckJNI::GetStringLength,
3835 CheckJNI::GetStringChars,
3836 CheckJNI::ReleaseStringChars,
3837 CheckJNI::NewStringUTF,
3838 CheckJNI::GetStringUTFLength,
3839 CheckJNI::GetStringUTFChars,
3840 CheckJNI::ReleaseStringUTFChars,
3841 CheckJNI::GetArrayLength,
3842 CheckJNI::NewObjectArray,
3843 CheckJNI::GetObjectArrayElement,
3844 CheckJNI::SetObjectArrayElement,
3845 CheckJNI::NewBooleanArray,
3846 CheckJNI::NewByteArray,
3847 CheckJNI::NewCharArray,
3848 CheckJNI::NewShortArray,
3849 CheckJNI::NewIntArray,
3850 CheckJNI::NewLongArray,
3851 CheckJNI::NewFloatArray,
3852 CheckJNI::NewDoubleArray,
3853 CheckJNI::GetBooleanArrayElements,
3854 CheckJNI::GetByteArrayElements,
3855 CheckJNI::GetCharArrayElements,
3856 CheckJNI::GetShortArrayElements,
3857 CheckJNI::GetIntArrayElements,
3858 CheckJNI::GetLongArrayElements,
3859 CheckJNI::GetFloatArrayElements,
3860 CheckJNI::GetDoubleArrayElements,
3861 CheckJNI::ReleaseBooleanArrayElements,
3862 CheckJNI::ReleaseByteArrayElements,
3863 CheckJNI::ReleaseCharArrayElements,
3864 CheckJNI::ReleaseShortArrayElements,
3865 CheckJNI::ReleaseIntArrayElements,
3866 CheckJNI::ReleaseLongArrayElements,
3867 CheckJNI::ReleaseFloatArrayElements,
3868 CheckJNI::ReleaseDoubleArrayElements,
3869 CheckJNI::GetBooleanArrayRegion,
3870 CheckJNI::GetByteArrayRegion,
3871 CheckJNI::GetCharArrayRegion,
3872 CheckJNI::GetShortArrayRegion,
3873 CheckJNI::GetIntArrayRegion,
3874 CheckJNI::GetLongArrayRegion,
3875 CheckJNI::GetFloatArrayRegion,
3876 CheckJNI::GetDoubleArrayRegion,
3877 CheckJNI::SetBooleanArrayRegion,
3878 CheckJNI::SetByteArrayRegion,
3879 CheckJNI::SetCharArrayRegion,
3880 CheckJNI::SetShortArrayRegion,
3881 CheckJNI::SetIntArrayRegion,
3882 CheckJNI::SetLongArrayRegion,
3883 CheckJNI::SetFloatArrayRegion,
3884 CheckJNI::SetDoubleArrayRegion,
3885 CheckJNI::RegisterNatives,
3886 CheckJNI::UnregisterNatives,
3887 CheckJNI::MonitorEnter,
3888 CheckJNI::MonitorExit,
3889 CheckJNI::GetJavaVM,
3890 CheckJNI::GetStringRegion,
3891 CheckJNI::GetStringUTFRegion,
3892 CheckJNI::GetPrimitiveArrayCritical,
3893 CheckJNI::ReleasePrimitiveArrayCritical,
3894 CheckJNI::GetStringCritical,
3895 CheckJNI::ReleaseStringCritical,
3896 CheckJNI::NewWeakGlobalRef,
3897 CheckJNI::DeleteWeakGlobalRef,
3898 CheckJNI::ExceptionCheck,
3899 CheckJNI::NewDirectByteBuffer,
3900 CheckJNI::GetDirectBufferAddress,
3901 CheckJNI::GetDirectBufferCapacity,
3902 CheckJNI::GetObjectRefType,
3903};
3904
Elliott Hughesa2501992011-08-26 19:39:54 -07003905class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003906 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003907 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003908 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3909 JniValueType args[1] = {{.v = vm}};
3910 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3911 JniValueType result;
3912 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08003913 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3914 // which will delete the JavaVMExt.
3915 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07003916 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003917 }
3918
3919 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003920 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3921 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3922 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3923 JniValueType result;
3924 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3925 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3926 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003927 }
3928
3929 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003930 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3931 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3932 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3933 JniValueType result;
3934 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3935 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3936 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003937 }
3938
3939 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003940 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3941 JniValueType args[1] = {{.v = vm}};
3942 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3943 JniValueType result;
3944 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3945 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3946 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003947 }
3948
Ian Rogers68d8b422014-07-17 11:09:10 -07003949 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3950 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3951 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3952 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3953 JniValueType result;
3954 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3955 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3956 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003957 }
3958
3959 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003960 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3961 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003962 }
3963};
3964
3965const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003966 nullptr, // reserved0
3967 nullptr, // reserved1
3968 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003969 CheckJII::DestroyJavaVM,
3970 CheckJII::AttachCurrentThread,
3971 CheckJII::DetachCurrentThread,
3972 CheckJII::GetEnv,
3973 CheckJII::AttachCurrentThreadAsDaemon
3974};
3975
Ian Rogersac4d45a2018-02-15 11:19:01 -08003976} // anonymous namespace
3977
3978const JNINativeInterface* GetCheckJniNativeInterface() {
3979 return &gCheckNativeInterface;
3980}
3981
Elliott Hughesa2501992011-08-26 19:39:54 -07003982const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3983 return &gCheckInvokeInterface;
3984}
3985
3986} // namespace art