CheckJni.cpp revision ce0968340f9ddd54f20e38d4946bfd2ef8f1f343
1/*
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
17/*
18 * Support for -Xcheck:jni (the "careful" version of the JNI interfaces).
19 *
20 * We want to verify types, make sure class and field IDs are valid, and
21 * ensure that JNI's semantic expectations are being met.  JNI seems to
22 * be relatively lax when it comes to requirements for permission checks,
23 * e.g. access to private methods is generally allowed from anywhere.
24 */
25
26#include "Dalvik.h"
27#include "JniInternal.h"
28
29#include <sys/mman.h>
30#include <zlib.h>
31
32/*
33 * Abort if we are configured to bail out on JNI warnings.
34 */
35static void abortMaybe() {
36    if (!gDvmJni.warnOnly) {
37        dvmDumpThread(dvmThreadSelf(), false);
38        dvmAbort();
39    }
40}
41
42/*
43 * ===========================================================================
44 *      JNI call bridge wrapper
45 * ===========================================================================
46 */
47
48/*
49 * Check the result of a native method call that returns an object reference.
50 *
51 * The primary goal here is to verify that native code is returning the
52 * correct type of object.  If it's declared to return a String but actually
53 * returns a byte array, things will fail in strange ways later on.
54 *
55 * This can be a fairly expensive operation, since we have to look up the
56 * return type class by name in method->clazz' class loader.  We take a
57 * shortcut here and allow the call to succeed if the descriptor strings
58 * match.  This will allow some false-positives when a class is redefined
59 * by a class loader, but that's rare enough that it doesn't seem worth
60 * testing for.
61 *
62 * At this point, pResult->l has already been converted to an object pointer.
63 */
64static void checkCallResultCommon(const u4* args, const JValue* pResult,
65        const Method* method, Thread* self)
66{
67    assert(pResult->l != NULL);
68    const Object* resultObj = (const Object*) pResult->l;
69
70    if (resultObj == kInvalidIndirectRefObject) {
71        LOGW("JNI WARNING: invalid reference returned from native code");
72        const Method* method = dvmGetCurrentJNIMethod();
73        char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
74        LOGW("             in %s.%s:%s", method->clazz->descriptor, method->name, desc);
75        free(desc);
76        abortMaybe();
77        return;
78    }
79
80    ClassObject* objClazz = resultObj->clazz;
81
82    /*
83     * Make sure that pResult->l is an instance of the type this
84     * method was expected to return.
85     */
86    const char* declType = dexProtoGetReturnType(&method->prototype);
87    const char* objType = objClazz->descriptor;
88    if (strcmp(declType, objType) == 0) {
89        /* names match; ignore class loader issues and allow it */
90        LOGV("Check %s.%s: %s io %s (FAST-OK)",
91            method->clazz->descriptor, method->name, objType, declType);
92    } else {
93        /*
94         * Names didn't match.  We need to resolve declType in the context
95         * of method->clazz->classLoader, and compare the class objects
96         * for equality.
97         *
98         * Since we're returning an instance of declType, it's safe to
99         * assume that it has been loaded and initialized (or, for the case
100         * of an array, generated).  However, the current class loader may
101         * not be listed as an initiating loader, so we can't just look for
102         * it in the loaded-classes list.
103         */
104        ClassObject* declClazz = dvmFindClassNoInit(declType, method->clazz->classLoader);
105        if (declClazz == NULL) {
106            LOGW("JNI WARNING: method declared to return '%s' returned '%s'",
107                declType, objType);
108            LOGW("             failed in %s.%s ('%s' not found)",
109                method->clazz->descriptor, method->name, declType);
110            abortMaybe();
111            return;
112        }
113        if (!dvmInstanceof(objClazz, declClazz)) {
114            LOGW("JNI WARNING: method declared to return '%s' returned '%s'",
115                declType, objType);
116            LOGW("             failed in %s.%s",
117                method->clazz->descriptor, method->name);
118            abortMaybe();
119            return;
120        } else {
121            LOGV("Check %s.%s: %s io %s (SLOW-OK)",
122                method->clazz->descriptor, method->name, objType, declType);
123        }
124    }
125}
126
127/*
128 * Determine if we need to check the return type coming out of the call.
129 *
130 * (We don't simply do this at the top of checkCallResultCommon() because
131 * this is on the critical path for native method calls.)
132 */
133static inline bool callNeedsCheck(const u4* args, JValue* pResult,
134    const Method* method, Thread* self)
135{
136    return (method->shorty[0] == 'L' && !dvmCheckException(self) && pResult->l != NULL);
137}
138
139/*
140 * Check a call into native code.
141 */
142void dvmCheckCallJNIMethod_general(const u4* args, JValue* pResult,
143    const Method* method, Thread* self)
144{
145    dvmCallJNIMethod_general(args, pResult, method, self);
146    if (callNeedsCheck(args, pResult, method, self)) {
147        checkCallResultCommon(args, pResult, method, self);
148    }
149}
150
151/*
152 * Check a synchronized call into native code.
153 */
154void dvmCheckCallJNIMethod_synchronized(const u4* args, JValue* pResult,
155    const Method* method, Thread* self)
156{
157    dvmCallJNIMethod_synchronized(args, pResult, method, self);
158    if (callNeedsCheck(args, pResult, method, self)) {
159        checkCallResultCommon(args, pResult, method, self);
160    }
161}
162
163/*
164 * Check a virtual call with no reference arguments (other than "this").
165 */
166void dvmCheckCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
167    const Method* method, Thread* self)
168{
169    dvmCallJNIMethod_virtualNoRef(args, pResult, method, self);
170    if (callNeedsCheck(args, pResult, method, self)) {
171        checkCallResultCommon(args, pResult, method, self);
172    }
173}
174
175/*
176 * Check a static call with no reference arguments (other than "clazz").
177 */
178void dvmCheckCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
179    const Method* method, Thread* self)
180{
181    dvmCallJNIMethod_staticNoRef(args, pResult, method, self);
182    if (callNeedsCheck(args, pResult, method, self)) {
183        checkCallResultCommon(args, pResult, method, self);
184    }
185}
186
187
188/*
189 * ===========================================================================
190 *      JNI function helpers
191 * ===========================================================================
192 */
193
194static inline const JNINativeInterface* baseEnv(JNIEnv* env) {
195    return ((JNIEnvExt*) env)->baseFuncTable;
196}
197
198static inline const JNIInvokeInterface* baseVm(JavaVM* vm) {
199    return ((JavaVMExt*) vm)->baseFuncTable;
200}
201
202/*
203 * Prints trace messages when a native method calls a JNI function such as
204 * NewByteArray. Enabled if both "-Xcheck:jni" and "-verbose:jni" are enabled.
205 */
206static inline void jniTrace(bool hasMethod, const char* functionName) {
207    static const char* classDescriptor = "???";
208    static const char* methodName = "???";
209    if (hasMethod) {
210        const Method* method = dvmGetCurrentJNIMethod();
211        classDescriptor = method->clazz->descriptor;
212        methodName = method->name;
213    }
214    /* use +6 to drop the leading "Check_" */
215    LOGI("JNI: %s (from %s.%s)", functionName + 6, classDescriptor, methodName);
216}
217
218class ScopedJniThreadState {
219public:
220    explicit ScopedJniThreadState(JNIEnv* env) {
221        dvmChangeStatus(NULL, THREAD_RUNNING);
222    }
223
224    ~ScopedJniThreadState() {
225        dvmChangeStatus(NULL, THREAD_NATIVE);
226    }
227
228private:
229    // Disallow copy and assignment.
230    ScopedJniThreadState(const ScopedJniThreadState&);
231    void operator=(const ScopedJniThreadState&);
232};
233
234class ScopedVmCheck {
235public:
236    /*
237     * Set "hasMethod" to true if we have a valid thread with a method pointer.
238     * We won't have one before attaching a thread, after detaching a thread, or
239     * after destroying the VM.
240     */
241    ScopedVmCheck(bool hasMethod, const char* functionName) {
242        if (gDvm.verboseJni) {
243            jniTrace(hasMethod, functionName);
244        }
245    }
246
247private:
248    // Disallow copy and assignment.
249    ScopedVmCheck(const ScopedVmCheck&);
250    void operator=(const ScopedVmCheck&);
251};
252
253/*
254 * Flags passed into ScopedCheck.
255 */
256#define kFlag_Default       0x0000
257
258#define kFlag_CritBad       0x0000      /* calling while in critical is bad */
259#define kFlag_CritOkay      0x0001      /* ...okay */
260#define kFlag_CritGet       0x0002      /* this is a critical "get" */
261#define kFlag_CritRelease   0x0003      /* this is a critical "release" */
262#define kFlag_CritMask      0x0003      /* bit mask to get "crit" value */
263
264#define kFlag_ExcepBad      0x0000      /* raised exceptions are bad */
265#define kFlag_ExcepOkay     0x0004      /* ...okay */
266
267static const char* indirectRefKindName(IndirectRef iref)
268{
269    return indirectRefKindToString(indirectRefKind(iref));
270}
271
272class ScopedCheck {
273public:
274    explicit ScopedCheck(JNIEnv* env, int flags, const char* functionName)
275    : mEnv(env), mFunctionName(functionName)
276    {
277        if (gDvm.verboseJni) {
278            jniTrace(true, mFunctionName);
279        }
280        checkThread(flags);
281    }
282
283    /*
284     * Verify that "array" is non-NULL and points to an Array object.
285     *
286     * Since we're dealing with objects, switch to "running" mode.
287     */
288    void checkArray(jarray jarr) {
289        if (jarr == NULL) {
290            LOGW("JNI WARNING: received null array");
291            showLocation();
292            abortMaybe();
293            return;
294        }
295
296        ScopedJniThreadState ts(mEnv);
297        bool printWarn = false;
298
299        Object* obj = dvmDecodeIndirectRef(mEnv, jarr);
300
301        if (!dvmIsValidObject(obj)) {
302            LOGW("JNI WARNING: jarray is an invalid %s reference (%p)",
303                    indirectRefKindName(jarr), jarr);
304            printWarn = true;
305        } else if (obj->clazz->descriptor[0] != '[') {
306            LOGW("JNI WARNING: jarray arg has wrong type (expected array, got %s)",
307                    obj->clazz->descriptor);
308            printWarn = true;
309        }
310
311        if (printWarn) {
312            showLocation();
313            abortMaybe();
314        }
315    }
316
317    /*
318     * In some circumstances the VM will screen class names, but it doesn't
319     * for class lookup.  When things get bounced through a class loader, they
320     * can actually get normalized a couple of times; as a result, passing in
321     * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
322     * work in some circumstances.
323     *
324     * This is incorrect and could cause strange behavior or compatibility
325     * problems, so we want to screen that out here.
326     *
327     * We expect "full-qualified" class names, like "java/lang/Thread" or
328     * "[Ljava/lang/Object;".
329     */
330    void checkClassName(const char* className) {
331        if (!dexIsValidClassName(className, false)) {
332            LOGW("JNI WARNING: illegal class name '%s' (%s)", className, mFunctionName);
333            LOGW("             (should be formed like 'dalvik/system/DexFile')");
334            LOGW("             or '[Ldalvik/system/DexFile;' or '[[B')");
335            abortMaybe();
336        }
337    }
338
339    /*
340     * Verify that the field is of the appropriate type.  If the field has an
341     * object type, "jobj" is the object we're trying to assign into it.
342     *
343     * Works for both static and instance fields.
344     */
345    void checkFieldType(jobject jobj, jfieldID fieldID, PrimitiveType prim, bool isStatic) {
346        if (fieldID == NULL) {
347            LOGW("JNI WARNING: null field ID");
348            showLocation();
349            abortMaybe();
350        }
351
352        bool printWarn = false;
353        Field* field = (Field*) fieldID;
354        if ((field->signature[0] == 'L' || field->signature[0] == '[') && jobj != NULL) {
355            ScopedJniThreadState ts(mEnv);
356            Object* obj = dvmDecodeIndirectRef(mEnv, jobj);
357            /*
358             * If jobj is a weak global ref whose referent has been cleared,
359             * obj will be NULL.  Otherwise, obj should always be non-NULL
360             * and valid.
361             */
362            if (obj != NULL && !dvmIsValidObject(obj)) {
363                LOGW("JNI WARNING: field operation on invalid %s reference (%p)",
364                        indirectRefKindName(jobj), jobj);
365                printWarn = true;
366            } else {
367                ClassObject* fieldClass = dvmFindLoadedClass(field->signature);
368                ClassObject* objClass = obj->clazz;
369
370                assert(fieldClass != NULL);
371                assert(objClass != NULL);
372
373                if (!dvmInstanceof(objClass, fieldClass)) {
374                    LOGW("JNI WARNING: set field '%s' expected type %s, got %s",
375                            field->name, field->signature, objClass->descriptor);
376                    printWarn = true;
377                }
378            }
379        } else if (dexGetPrimitiveTypeFromDescriptorChar(field->signature[0]) != prim) {
380            LOGW("JNI WARNING: set field '%s' expected type %s, got %s",
381                    field->name, field->signature, primitiveTypeToName(prim));
382            printWarn = true;
383        } else if (isStatic && !dvmIsStaticField(field)) {
384            if (isStatic) {
385                LOGW("JNI WARNING: accessing non-static field %s as static", field->name);
386            } else {
387                LOGW("JNI WARNING: accessing static field %s as non-static", field->name);
388            }
389            printWarn = true;
390        }
391
392        if (printWarn) {
393            showLocation();
394            abortMaybe();
395        }
396    }
397
398    /*
399     * Verify that this instance field ID is valid for this object.
400     *
401     * Assumes "jobj" has already been validated.
402     */
403    void checkInstanceFieldID(jobject jobj, jfieldID fieldID) {
404        ScopedJniThreadState ts(mEnv);
405
406        Object* obj = dvmDecodeIndirectRef(mEnv, jobj);
407        if (!dvmIsValidObject(obj)) {
408            LOGW("JNI ERROR: field operation on invalid reference (%p)", jobj);
409            dvmAbort();
410        }
411
412        /*
413         * Check this class and all of its superclasses for a matching field.
414         * Don't need to scan interfaces.
415         */
416        ClassObject* clazz = obj->clazz;
417        while (clazz != NULL) {
418            if ((InstField*) fieldID >= clazz->ifields &&
419                    (InstField*) fieldID < clazz->ifields + clazz->ifieldCount) {
420                return;
421            }
422
423            clazz = clazz->super;
424        }
425
426        LOGW("JNI WARNING: instance fieldID %p not valid for class %s",
427                fieldID, obj->clazz->descriptor);
428        showLocation();
429        abortMaybe();
430    }
431
432    /*
433     * Verify that the length argument to array-creation calls is >= 0.
434     */
435    void checkLengthPositive(jsize length) {
436        if (length < 0) {
437            LOGW("JNI WARNING: negative length for array allocation (%s)", mFunctionName);
438            abortMaybe();
439        }
440    }
441
442    /*
443     * Verify that the pointer value is non-NULL.
444     */
445    void checkNonNull(const void* ptr) {
446        if (ptr == NULL) {
447            LOGW("JNI WARNING: invalid null pointer (%s)", mFunctionName);
448            abortMaybe();
449        }
450    }
451
452    /*
453     * Verify that "jobj" is a valid object, and that it's an object that JNI
454     * is allowed to know about.  We allow NULL references.
455     *
456     * Switches to "running" mode before performing checks.
457     */
458    void checkObject(jobject jobj) {
459        if (jobj == NULL) {
460            return;
461        }
462
463        ScopedJniThreadState ts(mEnv);
464
465        bool printWarn = false;
466        if (dvmGetJNIRefType(mEnv, jobj) == JNIInvalidRefType) {
467            LOGW("JNI WARNING: %p is not a valid JNI reference", jobj);
468            printWarn = true;
469        } else {
470            Object* obj = dvmDecodeIndirectRef(mEnv, jobj);
471
472            /*
473             * The decoded object will be NULL if this is a weak global ref
474             * with a cleared referent.
475             */
476            if (obj == kInvalidIndirectRefObject || (obj != NULL && !dvmIsValidObject(obj))) {
477                LOGW("JNI WARNING: native code passing in bad object %p %p", jobj, obj);
478                printWarn = true;
479            }
480        }
481
482        if (printWarn) {
483            showLocation();
484            abortMaybe();
485        }
486    }
487
488    /*
489     * Verify that the "mode" argument passed to a primitive array Release
490     * function is one of the valid values.
491     */
492    void checkReleaseMode(jint mode) {
493        if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
494            LOGW("JNI WARNING: bad value for mode (%d) (%s)", mode, mFunctionName);
495            abortMaybe();
496        }
497    }
498
499    /*
500     * Verify that the method's return type matches the type of call.
501     *
502     * "expectedSigByte" will be 'L' for all objects, including arrays.
503     */
504    void checkSig(jmethodID methodID, char expectedSigByte, bool isStatic) {
505        const Method* method = (const Method*) methodID;
506        bool printWarn = false;
507
508        if (expectedSigByte != method->shorty[0]) {
509            LOGW("JNI WARNING: expected return type '%c'", expectedSigByte);
510            printWarn = true;
511        } else if (isStatic && !dvmIsStaticMethod(method)) {
512            if (isStatic) {
513                LOGW("JNI WARNING: calling non-static method with static call");
514            } else {
515                LOGW("JNI WARNING: calling static method with non-static call");
516            }
517            printWarn = true;
518        }
519
520        if (printWarn) {
521            char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
522            LOGW("             calling %s.%s %s", method->clazz->descriptor, method->name, desc);
523            free(desc);
524            showLocation();
525            abortMaybe();
526        }
527    }
528
529    /*
530     * Verify that this static field ID is valid for this class.
531     *
532     * Assumes "jclazz" has already been validated.
533     */
534    void checkStaticFieldID(jclass jclazz, jfieldID fieldID) {
535        ScopedJniThreadState ts(mEnv);
536        ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(mEnv, jclazz);
537        StaticField* base = &clazz->sfields[0];
538        int fieldCount = clazz->sfieldCount;
539        if ((StaticField*) fieldID < base || (StaticField*) fieldID >= base + fieldCount) {
540            LOGW("JNI WARNING: static fieldID %p not valid for class %s",
541                    fieldID, clazz->descriptor);
542            LOGW("             base=%p count=%d", base, fieldCount);
543            showLocation();
544            abortMaybe();
545        }
546    }
547
548    /*
549     * Verify that "methodID" is appropriate for "clazz".
550     *
551     * A mismatch isn't dangerous, because the jmethodID defines the class.  In
552     * fact, jclazz is unused in the implementation.  It's best if we don't
553     * allow bad code in the system though.
554     *
555     * Instances of "jclazz" must be instances of the method's declaring class.
556     */
557    void checkStaticMethod(jclass jclazz, jmethodID methodID) {
558        ScopedJniThreadState ts(mEnv);
559
560        ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(mEnv, jclazz);
561        const Method* method = (const Method*) methodID;
562
563        if (!dvmInstanceof(clazz, method->clazz)) {
564            LOGW("JNI WARNING: can't call static %s.%s on class %s",
565                    method->clazz->descriptor, method->name, clazz->descriptor);
566            showLocation();
567            // no abort?
568        }
569    }
570
571    void checkString(jstring s) {
572        checkInstance(s, gDvm.classJavaLangString, "jstring");
573    }
574
575    void checkClass(jclass c) {
576        checkInstance(c, gDvm.classJavaLangClass, "jclass");
577    }
578
579    /*
580     * Verify that "bytes" points to valid "modified UTF-8" data.
581     * If "identifier" is NULL, "bytes" is allowed to be NULL; otherwise,
582     * "identifier" is the name to use when reporting the null pointer.
583     */
584    void checkUtfString(const char* bytes, const char* identifier) {
585        if (bytes == NULL) {
586            if (identifier != NULL) {
587                LOGW("JNI WARNING: %s == NULL", identifier);
588                showLocation();
589                abortMaybe();
590            }
591            return;
592        }
593
594        const char* errorKind = NULL;
595        u1 utf8 = checkUtfBytes(bytes, &errorKind);
596        if (errorKind != NULL) {
597            LOGW("JNI WARNING: input is not valid UTF-8: illegal %s byte %#x", errorKind, utf8);
598            LOGW("             string: '%s'", bytes);
599            showLocation();
600            abortMaybe();
601        }
602    }
603
604    /*
605     * Verify that "methodID" is appropriate for "jobj".
606     *
607     * Make sure the object is an instance of the method's declaring class.
608     * (Note the methodID might point to a declaration in an interface; this
609     * will be handled automatically by the instanceof check.)
610     */
611    void checkVirtualMethod(jobject jobj, jmethodID methodID) {
612        ScopedJniThreadState ts(mEnv);
613
614        Object* obj = dvmDecodeIndirectRef(mEnv, jobj);
615        const Method* method = (const Method*) methodID;
616
617        if (!dvmInstanceof(obj->clazz, method->clazz)) {
618            LOGW("JNI WARNING: can't call %s.%s on instance of %s",
619                    method->clazz->descriptor, method->name, obj->clazz->descriptor);
620            showLocation();
621            abortMaybe();
622        }
623    }
624
625private:
626    JNIEnv* mEnv;
627    const char* mFunctionName;
628
629    void checkThread(int flags) {
630        // Get the *correct* JNIEnv by going through our TLS pointer.
631        JNIEnvExt* threadEnv = dvmGetJNIEnvForThread();
632
633        /*
634         * Verify that the current thread is (a) attached and (b) associated with
635         * this particular instance of JNIEnv.
636         */
637        bool printWarn = false;
638        if (threadEnv == NULL) {
639            LOGE("JNI ERROR: non-VM thread making JNI calls");
640            // don't set printWarn -- it'll try to call showLocation()
641            dvmAbort();
642        } else if ((JNIEnvExt*) mEnv != threadEnv) {
643            if (dvmThreadSelf()->threadId != threadEnv->envThreadId) {
644                LOGE("JNI: threadEnv != thread->env?");
645                dvmAbort();
646            }
647
648            LOGW("JNI WARNING: threadid=%d using env from threadid=%d",
649                    threadEnv->envThreadId, ((JNIEnvExt*) mEnv)->envThreadId);
650            printWarn = true;
651
652            /* this is a bad idea -- need to throw as we exit, or abort func */
653            //dvmThrowRuntimeException("invalid use of JNI env ptr");
654        } else if (((JNIEnvExt*) mEnv)->self != dvmThreadSelf()) {
655            /* correct JNIEnv*; make sure the "self" pointer is correct */
656            LOGE("JNI ERROR: env->self != thread-self (%p vs. %p)",
657                    ((JNIEnvExt*) mEnv)->self, dvmThreadSelf());
658            dvmAbort();
659        }
660
661        /*
662         * Verify that, if this thread previously made a critical "get" call, we
663         * do the corresponding "release" call before we try anything else.
664         */
665        switch (flags & kFlag_CritMask) {
666        case kFlag_CritOkay:    // okay to call this method
667            break;
668        case kFlag_CritBad:     // not okay to call
669            if (threadEnv->critical) {
670                LOGW("JNI WARNING: threadid=%d using JNI after critical get",
671                        threadEnv->envThreadId);
672                printWarn = true;
673            }
674            break;
675        case kFlag_CritGet:     // this is a "get" call
676            /* don't check here; we allow nested gets */
677            threadEnv->critical++;
678            break;
679        case kFlag_CritRelease: // this is a "release" call
680            threadEnv->critical--;
681            if (threadEnv->critical < 0) {
682                LOGW("JNI WARNING: threadid=%d called too many crit releases",
683                        threadEnv->envThreadId);
684                printWarn = true;
685            }
686            break;
687        default:
688            assert(false);
689        }
690
691        /*
692         * Verify that, if an exception has been raised, the native code doesn't
693         * make any JNI calls other than the Exception* methods.
694         */
695        bool printException = false;
696        if ((flags & kFlag_ExcepOkay) == 0 && dvmCheckException(dvmThreadSelf())) {
697            LOGW("JNI WARNING: JNI method called with exception pending");
698            printWarn = true;
699            printException = true;
700        }
701
702        if (printWarn) {
703            showLocation();
704        }
705        if (printException) {
706            LOGW("Pending exception is:");
707            dvmLogExceptionStackTrace();
708        }
709        if (printWarn) {
710            abortMaybe();
711        }
712    }
713
714    /*
715     * Verify that "jobj" is a valid non-NULL object reference, and points to
716     * an instance of expectedClass.
717     *
718     * Because we're looking at an object on the GC heap, we have to switch
719     * to "running" mode before doing the checks.
720     */
721    void checkInstance(jobject jobj, ClassObject* expectedClass, const char* argName) {
722        if (jobj == NULL) {
723            LOGW("JNI WARNING: received null %s", argName);
724            showLocation();
725            abortMaybe();
726            return;
727        }
728
729        ScopedJniThreadState ts(mEnv);
730        bool printWarn = false;
731
732        Object* obj = dvmDecodeIndirectRef(mEnv, jobj);
733
734        if (!dvmIsValidObject(obj)) {
735            LOGW("JNI WARNING: %s is an invalid %s reference (%p)",
736                    argName, indirectRefKindName(jobj), jobj);
737            printWarn = true;
738        } else if (obj->clazz != expectedClass) {
739            LOGW("JNI WARNING: %s arg has wrong type (expected %s, got %s)",
740                    argName, expectedClass->descriptor, obj->clazz->descriptor);
741            printWarn = true;
742        }
743
744        if (printWarn) {
745            showLocation();
746            abortMaybe();
747        }
748    }
749
750    static u1 checkUtfBytes(const char* bytes, const char** errorKind) {
751        while (*bytes != '\0') {
752            u1 utf8 = *(bytes++);
753            // Switch on the high four bits.
754            switch (utf8 >> 4) {
755            case 0x00:
756            case 0x01:
757            case 0x02:
758            case 0x03:
759            case 0x04:
760            case 0x05:
761            case 0x06:
762            case 0x07:
763                // Bit pattern 0xxx. No need for any extra bytes.
764                break;
765            case 0x08:
766            case 0x09:
767            case 0x0a:
768            case 0x0b:
769            case 0x0f:
770                /*
771                 * Bit pattern 10xx or 1111, which are illegal start bytes.
772                 * Note: 1111 is valid for normal UTF-8, but not the
773                 * modified UTF-8 used here.
774                 */
775                *errorKind = "start";
776                return utf8;
777            case 0x0e:
778                // Bit pattern 1110, so there are two additional bytes.
779                utf8 = *(bytes++);
780                if ((utf8 & 0xc0) != 0x80) {
781                    *errorKind = "continuation";
782                    return utf8;
783                }
784                // Fall through to take care of the final byte.
785            case 0x0c:
786            case 0x0d:
787                // Bit pattern 110x, so there is one additional byte.
788                utf8 = *(bytes++);
789                if ((utf8 & 0xc0) != 0x80) {
790                    *errorKind = "continuation";
791                    return utf8;
792                }
793                break;
794            }
795        }
796        return 0;
797    }
798
799    /**
800     * Returns a human-readable name for the given primitive type.
801     */
802    static const char* primitiveTypeToName(PrimitiveType primType) {
803        switch (primType) {
804        case PRIM_VOID:    return "void";
805        case PRIM_BOOLEAN: return "boolean";
806        case PRIM_BYTE:    return "byte";
807        case PRIM_SHORT:   return "short";
808        case PRIM_CHAR:    return "char";
809        case PRIM_INT:     return "int";
810        case PRIM_LONG:    return "long";
811        case PRIM_FLOAT:   return "float";
812        case PRIM_DOUBLE:  return "double";
813        case PRIM_NOT:     return "Object/array";
814        default:           return "???";
815        }
816    }
817
818    void showLocation() {
819        // mFunctionName looks like "Check_DeleteLocalRef"; we drop the "Check_".
820        const char* name = mFunctionName + 6;
821        const Method* method = dvmGetCurrentJNIMethod();
822        char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
823        LOGW("             in %s.%s:%s (%s)", method->clazz->descriptor, method->name, desc, name);
824        free(desc);
825    }
826
827    // Disallow copy and assignment.
828    ScopedCheck(const ScopedCheck&);
829    void operator=(const ScopedCheck&);
830};
831
832/*
833 * ===========================================================================
834 *      Guarded arrays
835 * ===========================================================================
836 */
837
838#define kGuardLen       512         /* must be multiple of 2 */
839#define kGuardPattern   0xd5e3      /* uncommon values; d5e3d5e3 invalid addr */
840#define kGuardMagic     0xffd5aa96
841
842/* this gets tucked in at the start of the buffer; struct size must be even */
843struct GuardedCopy {
844    u4          magic;
845    uLong       adler;
846    size_t      originalLen;
847    const void* originalPtr;
848
849    /* find the GuardedCopy given the pointer into the "live" data */
850    static inline const GuardedCopy* fromData(const void* dataBuf) {
851        return reinterpret_cast<const GuardedCopy*>(actualBuffer(dataBuf));
852    }
853
854    /*
855     * Create an over-sized buffer to hold the contents of "buf".  Copy it in,
856     * filling in the area around it with guard data.
857     *
858     * We use a 16-bit pattern to make a rogue memset less likely to elude us.
859     */
860    static void* create(const void* buf, size_t len, bool modOkay) {
861        size_t newLen = actualLength(len);
862        u1* newBuf = debugAlloc(newLen);
863
864        /* fill it in with a pattern */
865        u2* pat = (u2*) newBuf;
866        for (size_t i = 0; i < newLen / 2; i++) {
867            *pat++ = kGuardPattern;
868        }
869
870        /* copy the data in; note "len" could be zero */
871        memcpy(newBuf + kGuardLen / 2, buf, len);
872
873        /* if modification is not expected, grab a checksum */
874        uLong adler = 0;
875        if (!modOkay) {
876            adler = adler32(0L, Z_NULL, 0);
877            adler = adler32(adler, (const Bytef*)buf, len);
878            *(uLong*)newBuf = adler;
879        }
880
881        GuardedCopy* pExtra = reinterpret_cast<GuardedCopy*>(newBuf);
882        pExtra->magic = kGuardMagic;
883        pExtra->adler = adler;
884        pExtra->originalPtr = buf;
885        pExtra->originalLen = len;
886
887        return newBuf + kGuardLen / 2;
888    }
889
890    /*
891     * Free up the guard buffer, scrub it, and return the original pointer.
892     */
893    static void* destroy(void* dataBuf) {
894        const GuardedCopy* pExtra = GuardedCopy::fromData(dataBuf);
895        void* originalPtr = (void*) pExtra->originalPtr;
896        size_t len = pExtra->originalLen;
897        debugFree(dataBuf, len);
898        return originalPtr;
899    }
900
901    /*
902     * Verify the guard area and, if "modOkay" is false, that the data itself
903     * has not been altered.
904     *
905     * The caller has already checked that "dataBuf" is non-NULL.
906     */
907    static bool check(const void* dataBuf, bool modOkay) {
908        static const u4 kMagicCmp = kGuardMagic;
909        const u1* fullBuf = actualBuffer(dataBuf);
910        const GuardedCopy* pExtra = GuardedCopy::fromData(dataBuf);
911
912        /*
913         * Before we do anything with "pExtra", check the magic number.  We
914         * do the check with memcmp rather than "==" in case the pointer is
915         * unaligned.  If it points to completely bogus memory we're going
916         * to crash, but there's no easy way around that.
917         */
918        if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
919            u1 buf[4];
920            memcpy(buf, &pExtra->magic, 4);
921            LOGE("JNI: guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
922                    buf[3], buf[2], buf[1], buf[0], dataBuf); /* assume little endian */
923            return false;
924        }
925
926        size_t len = pExtra->originalLen;
927
928        /* check bottom half of guard; skip over optional checksum storage */
929        const u2* pat = (u2*) fullBuf;
930        for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) {
931            if (pat[i] != kGuardPattern) {
932                LOGE("JNI: guard pattern(1) disturbed at %p + %d", fullBuf, i*2);
933                return false;
934            }
935        }
936
937        int offset = kGuardLen / 2 + len;
938        if (offset & 0x01) {
939            /* odd byte; expected value depends on endian-ness of host */
940            const u2 patSample = kGuardPattern;
941            if (fullBuf[offset] != ((const u1*) &patSample)[1]) {
942                LOGE("JNI: guard pattern disturbed in odd byte after %p (+%d) 0x%02x 0x%02x",
943                        fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]);
944                return false;
945            }
946            offset++;
947        }
948
949        /* check top half of guard */
950        pat = (u2*) (fullBuf + offset);
951        for (size_t i = 0; i < kGuardLen / 4; i++) {
952            if (pat[i] != kGuardPattern) {
953                LOGE("JNI: guard pattern(2) disturbed at %p + %d", fullBuf, offset + i*2);
954                return false;
955            }
956        }
957
958        /*
959         * If modification is not expected, verify checksum.  Strictly speaking
960         * this is wrong: if we told the client that we made a copy, there's no
961         * reason they can't alter the buffer.
962         */
963        if (!modOkay) {
964            uLong adler = adler32(0L, Z_NULL, 0);
965            adler = adler32(adler, (const Bytef*)dataBuf, len);
966            if (pExtra->adler != adler) {
967                LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p",
968                        pExtra->adler, adler, dataBuf);
969                return false;
970            }
971        }
972
973        return true;
974    }
975
976private:
977    static u1* debugAlloc(size_t len) {
978        void* result = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
979        if (result == MAP_FAILED) {
980            LOGE("GuardedCopy::create mmap(%d) failed: %s", len, strerror(errno));
981            dvmAbort();
982        }
983        return reinterpret_cast<u1*>(result);
984    }
985
986    static void debugFree(void* dataBuf, size_t len) {
987        u1* fullBuf = actualBuffer(dataBuf);
988        size_t totalByteCount = actualLength(len);
989        // TODO: we could mprotect instead, and keep the allocation around for a while.
990        // This would be even more expensive, but it might catch more errors.
991        // if (mprotect(fullBuf, totalByteCount, PROT_NONE) != 0) {
992        //     LOGW("mprotect(PROT_NONE) failed: %s", strerror(errno));
993        // }
994        if (munmap(fullBuf, totalByteCount) != 0) {
995            LOGW("munmap failed: %s", strerror(errno));
996            dvmAbort();
997        }
998    }
999
1000    static const u1* actualBuffer(const void* dataBuf) {
1001        return reinterpret_cast<const u1*>(dataBuf) - kGuardLen / 2;
1002    }
1003
1004    static u1* actualBuffer(void* dataBuf) {
1005        return reinterpret_cast<u1*>(dataBuf) - kGuardLen / 2;
1006    }
1007
1008    // Underlying length of a user allocation of 'length' bytes.
1009    static size_t actualLength(size_t length) {
1010        return (length + kGuardLen + 1) & ~0x01;
1011    }
1012};
1013
1014/*
1015 * Return the width, in bytes, of a primitive type.
1016 */
1017static int dvmPrimitiveTypeWidth(PrimitiveType primType) {
1018    switch (primType) {
1019        case PRIM_BOOLEAN: return 1;
1020        case PRIM_BYTE:    return 1;
1021        case PRIM_SHORT:   return 2;
1022        case PRIM_CHAR:    return 2;
1023        case PRIM_INT:     return 4;
1024        case PRIM_LONG:    return 8;
1025        case PRIM_FLOAT:   return 4;
1026        case PRIM_DOUBLE:  return 8;
1027        case PRIM_VOID:
1028        default: {
1029            assert(false);
1030            return -1;
1031        }
1032    }
1033}
1034
1035/*
1036 * Create a guarded copy of a primitive array.  Modifications to the copied
1037 * data are allowed.  Returns a pointer to the copied data.
1038 */
1039static void* createGuardedPACopy(JNIEnv* env, const jarray jarr, jboolean* isCopy) {
1040    ScopedJniThreadState ts(env);
1041
1042    ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1043    PrimitiveType primType = arrObj->clazz->elementClass->primitiveType;
1044    int len = arrObj->length * dvmPrimitiveTypeWidth(primType);
1045    void* result = GuardedCopy::create(arrObj->contents, len, true);
1046    if (isCopy != NULL) {
1047        *isCopy = JNI_TRUE;
1048    }
1049    return result;
1050}
1051
1052/*
1053 * Perform the array "release" operation, which may or may not copy data
1054 * back into the VM, and may or may not release the underlying storage.
1055 */
1056static void* releaseGuardedPACopy(JNIEnv* env, jarray jarr, void* dataBuf, int mode) {
1057    ScopedJniThreadState ts(env);
1058    ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1059
1060    if (!GuardedCopy::check(dataBuf, true)) {
1061        LOGE("JNI: failed guarded copy check in releaseGuardedPACopy");
1062        abortMaybe();
1063        return NULL;
1064    }
1065
1066    if (mode != JNI_ABORT) {
1067        size_t len = GuardedCopy::fromData(dataBuf)->originalLen;
1068        memcpy(arrObj->contents, dataBuf, len);
1069    }
1070
1071    u1* result = NULL;
1072    if (mode != JNI_COMMIT) {
1073        result = (u1*) GuardedCopy::destroy(dataBuf);
1074    } else {
1075        result = (u1*) (void*) GuardedCopy::fromData(dataBuf)->originalPtr;
1076    }
1077
1078    /* pointer is to the array contents; back up to the array object */
1079    result -= OFFSETOF_MEMBER(ArrayObject, contents);
1080    return result;
1081}
1082
1083
1084/*
1085 * ===========================================================================
1086 *      JNI functions
1087 * ===========================================================================
1088 */
1089
1090static jint Check_GetVersion(JNIEnv* env) {
1091    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1092    return baseEnv(env)->GetVersion(env);
1093}
1094
1095static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader,
1096    const jbyte* buf, jsize bufLen)
1097{
1098    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1099    sc.checkObject(loader);
1100    sc.checkUtfString(name, "name");
1101    sc.checkClassName(name);
1102    return baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1103}
1104
1105static jclass Check_FindClass(JNIEnv* env, const char* name) {
1106    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1107    sc.checkUtfString(name, "name");
1108    sc.checkClassName(name);
1109    return baseEnv(env)->FindClass(env, name);
1110}
1111
1112static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz) {
1113    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1114    sc.checkClass(clazz);
1115    return baseEnv(env)->GetSuperclass(env, clazz);
1116}
1117
1118static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1, jclass clazz2) {
1119    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1120    sc.checkClass(clazz1);
1121    sc.checkClass(clazz2);
1122    return baseEnv(env)->IsAssignableFrom(env, clazz1, clazz2);
1123}
1124
1125static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method) {
1126    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1127    sc.checkObject(method);
1128    return baseEnv(env)->FromReflectedMethod(env, method);
1129}
1130
1131static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field) {
1132    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1133    sc.checkObject(field);
1134    return baseEnv(env)->FromReflectedField(env, field);
1135}
1136
1137static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls,
1138        jmethodID methodID, jboolean isStatic)
1139{
1140    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1141    sc.checkClass(cls);
1142    return baseEnv(env)->ToReflectedMethod(env, cls, methodID, isStatic);
1143}
1144
1145static jobject Check_ToReflectedField(JNIEnv* env, jclass cls,
1146        jfieldID fieldID, jboolean isStatic)
1147{
1148    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1149    sc.checkClass(cls);
1150    return baseEnv(env)->ToReflectedField(env, cls, fieldID, isStatic);
1151}
1152
1153static jint Check_Throw(JNIEnv* env, jthrowable obj) {
1154    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1155    sc.checkObject(obj);
1156    /* TODO: verify that "obj" is an instance of Throwable */
1157    return baseEnv(env)->Throw(env, obj);
1158}
1159
1160static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message) {
1161    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1162    sc.checkClass(clazz);
1163    sc.checkUtfString(message, NULL);
1164    return baseEnv(env)->ThrowNew(env, clazz, message);
1165}
1166
1167static jthrowable Check_ExceptionOccurred(JNIEnv* env) {
1168    ScopedCheck sc(env, kFlag_ExcepOkay, __FUNCTION__);
1169    return baseEnv(env)->ExceptionOccurred(env);
1170}
1171
1172static void Check_ExceptionDescribe(JNIEnv* env) {
1173    ScopedCheck sc(env, kFlag_ExcepOkay, __FUNCTION__);
1174    baseEnv(env)->ExceptionDescribe(env);
1175}
1176
1177static void Check_ExceptionClear(JNIEnv* env) {
1178    ScopedCheck sc(env, kFlag_ExcepOkay, __FUNCTION__);
1179    baseEnv(env)->ExceptionClear(env);
1180}
1181
1182static void Check_FatalError(JNIEnv* env, const char* msg) {
1183    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1184    sc.checkUtfString(msg, NULL);
1185    baseEnv(env)->FatalError(env, msg);
1186}
1187
1188static jint Check_PushLocalFrame(JNIEnv* env, jint capacity) {
1189    ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
1190    return baseEnv(env)->PushLocalFrame(env, capacity);
1191}
1192
1193static jobject Check_PopLocalFrame(JNIEnv* env, jobject res) {
1194    ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
1195    sc.checkObject(res);
1196    return baseEnv(env)->PopLocalFrame(env, res);
1197}
1198
1199static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj) {
1200    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1201    sc.checkObject(obj);
1202    return baseEnv(env)->NewGlobalRef(env, obj);
1203}
1204
1205static void Check_DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
1206    ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
1207    sc.checkObject(globalRef);
1208    if (globalRef != NULL && dvmGetJNIRefType(env, globalRef) != JNIGlobalRefType) {
1209        LOGW("JNI WARNING: DeleteGlobalRef on non-global %p (type=%d)",
1210            globalRef, dvmGetJNIRefType(env, globalRef));
1211        abortMaybe();
1212    } else {
1213        baseEnv(env)->DeleteGlobalRef(env, globalRef);
1214    }
1215}
1216
1217static jobject Check_NewLocalRef(JNIEnv* env, jobject ref) {
1218    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1219    sc.checkObject(ref);
1220    return baseEnv(env)->NewLocalRef(env, ref);
1221}
1222
1223static void Check_DeleteLocalRef(JNIEnv* env, jobject localRef) {
1224    ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
1225    sc.checkObject(localRef);
1226    if (localRef != NULL && dvmGetJNIRefType(env, localRef) != JNILocalRefType) {
1227        LOGW("JNI WARNING: DeleteLocalRef on non-local %p (type=%d)",
1228            localRef, dvmGetJNIRefType(env, localRef));
1229        abortMaybe();
1230    } else {
1231        baseEnv(env)->DeleteLocalRef(env, localRef);
1232    }
1233}
1234
1235static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1236    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1237    return baseEnv(env)->EnsureLocalCapacity(env, capacity);
1238}
1239
1240static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1241    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1242    sc.checkObject(ref1);
1243    sc.checkObject(ref2);
1244    return baseEnv(env)->IsSameObject(env, ref1, ref2);
1245}
1246
1247static jobject Check_AllocObject(JNIEnv* env, jclass clazz) {
1248    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1249    sc.checkClass(clazz);
1250    return baseEnv(env)->AllocObject(env, clazz);
1251}
1252
1253static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1254    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1255    sc.checkClass(clazz);
1256    va_list args;
1257
1258    va_start(args, methodID);
1259    jobject result = baseEnv(env)->NewObjectV(env, clazz, methodID, args);
1260    va_end(args);
1261
1262    return result;
1263}
1264
1265static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args) {
1266    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1267    sc.checkClass(clazz);
1268    return baseEnv(env)->NewObjectV(env, clazz, methodID, args);
1269}
1270
1271static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue* args) {
1272    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1273    sc.checkClass(clazz);
1274    return baseEnv(env)->NewObjectA(env, clazz, methodID, args);
1275}
1276
1277static jclass Check_GetObjectClass(JNIEnv* env, jobject obj) {
1278    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1279    sc.checkObject(obj);
1280    return baseEnv(env)->GetObjectClass(env, obj);
1281}
1282
1283static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz) {
1284    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1285    sc.checkObject(obj);
1286    sc.checkClass(clazz);
1287    return baseEnv(env)->IsInstanceOf(env, obj, clazz);
1288}
1289
1290static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
1291    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1292    sc.checkClass(clazz);
1293    sc.checkUtfString(name, "name");
1294    sc.checkUtfString(sig, "sig");
1295    return baseEnv(env)->GetMethodID(env, clazz, name, sig);
1296}
1297
1298static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
1299    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1300    sc.checkClass(clazz);
1301    sc.checkUtfString(name, "name");
1302    sc.checkUtfString(sig, "sig");
1303    return baseEnv(env)->GetFieldID(env, clazz, name, sig);
1304}
1305
1306static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz,
1307        const char* name, const char* sig)
1308{
1309    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1310    sc.checkClass(clazz);
1311    sc.checkUtfString(name, "name");
1312    sc.checkUtfString(sig, "sig");
1313    return baseEnv(env)->GetStaticMethodID(env, clazz, name, sig);
1314}
1315
1316static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz,
1317        const char* name, const char* sig)
1318{
1319    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1320    sc.checkClass(clazz);
1321    sc.checkUtfString(name, "name");
1322    sc.checkUtfString(sig, "sig");
1323    return baseEnv(env)->GetStaticFieldID(env, clazz, name, sig);
1324}
1325
1326#define GET_STATIC_TYPE_FIELD(_ctype, _jname) \
1327    static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, jfieldID fieldID) \
1328    { \
1329        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1330        sc.checkClass(clazz); \
1331        sc.checkStaticFieldID(clazz, fieldID); \
1332        return baseEnv(env)->GetStatic##_jname##Field(env, clazz, fieldID); \
1333    }
1334GET_STATIC_TYPE_FIELD(jobject, Object);
1335GET_STATIC_TYPE_FIELD(jboolean, Boolean);
1336GET_STATIC_TYPE_FIELD(jbyte, Byte);
1337GET_STATIC_TYPE_FIELD(jchar, Char);
1338GET_STATIC_TYPE_FIELD(jshort, Short);
1339GET_STATIC_TYPE_FIELD(jint, Int);
1340GET_STATIC_TYPE_FIELD(jlong, Long);
1341GET_STATIC_TYPE_FIELD(jfloat, Float);
1342GET_STATIC_TYPE_FIELD(jdouble, Double);
1343
1344#define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype) \
1345    static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1346        jfieldID fieldID, _ctype value) { \
1347        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1348        sc.checkClass(clazz); \
1349        sc.checkStaticFieldID(clazz, fieldID); \
1350        /* "value" arg only used when type == ref */ \
1351        sc.checkFieldType((jobject)(u4)value, fieldID, _ftype, true); \
1352        baseEnv(env)->SetStatic##_jname##Field(env, clazz, fieldID, value); \
1353    }
1354SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT);
1355SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1356SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1357SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1358SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1359SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT);
1360SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG);
1361SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1362SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1363
1364#define GET_TYPE_FIELD(_ctype, _jname)                                      \
1365    static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj, jfieldID fieldID) { \
1366        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1367        sc.checkObject(obj); \
1368        sc.checkInstanceFieldID(obj, fieldID); \
1369        return baseEnv(env)->Get##_jname##Field(env, obj, fieldID);      \
1370    }
1371GET_TYPE_FIELD(jobject, Object);
1372GET_TYPE_FIELD(jboolean, Boolean);
1373GET_TYPE_FIELD(jbyte, Byte);
1374GET_TYPE_FIELD(jchar, Char);
1375GET_TYPE_FIELD(jshort, Short);
1376GET_TYPE_FIELD(jint, Int);
1377GET_TYPE_FIELD(jlong, Long);
1378GET_TYPE_FIELD(jfloat, Float);
1379GET_TYPE_FIELD(jdouble, Double);
1380
1381#define SET_TYPE_FIELD(_ctype, _jname, _ftype) \
1382    static void Check_Set##_jname##Field(JNIEnv* env, jobject obj, jfieldID fieldID, _ctype value) \
1383    { \
1384        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1385        sc.checkObject(obj); \
1386        sc.checkInstanceFieldID(obj, fieldID); \
1387        /* "value" arg only used when type == ref */ \
1388        sc.checkFieldType((jobject)(u4) value, fieldID, _ftype, false); \
1389        baseEnv(env)->Set##_jname##Field(env, obj, fieldID, value); \
1390    }
1391SET_TYPE_FIELD(jobject, Object, PRIM_NOT);
1392SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1393SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1394SET_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1395SET_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1396SET_TYPE_FIELD(jint, Int, PRIM_INT);
1397SET_TYPE_FIELD(jlong, Long, PRIM_LONG);
1398SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1399SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1400
1401#define CALL_VIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig)   \
1402    static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj,      \
1403        jmethodID methodID, ...)                                            \
1404    {                                                                       \
1405        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1406        sc.checkObject(obj); \
1407        sc.checkSig(methodID, _retsig, false); \
1408        sc.checkVirtualMethod(obj, methodID); \
1409        _retdecl;                                                           \
1410        va_list args;                                                       \
1411        va_start(args, methodID);                                           \
1412        _retasgn baseEnv(env)->Call##_jname##MethodV(env, obj, methodID,   \
1413            args);                                                          \
1414        va_end(args);                                                       \
1415        return _retok;                                                      \
1416    }                                                                       \
1417    static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj,     \
1418        jmethodID methodID, va_list args)                                   \
1419    {                                                                       \
1420        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1421        sc.checkObject(obj); \
1422        sc.checkSig(methodID, _retsig, false); \
1423        sc.checkVirtualMethod(obj, methodID); \
1424        _retdecl;                                                           \
1425        _retasgn baseEnv(env)->Call##_jname##MethodV(env, obj, methodID,   \
1426            args);                                                          \
1427        return _retok;                                                      \
1428    }                                                                       \
1429    static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj,     \
1430        jmethodID methodID, jvalue* args)                                   \
1431    {                                                                       \
1432        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1433        sc.checkObject(obj); \
1434        sc.checkSig(methodID, _retsig, false); \
1435        sc.checkVirtualMethod(obj, methodID); \
1436        _retdecl;                                                           \
1437        _retasgn baseEnv(env)->Call##_jname##MethodA(env, obj, methodID,   \
1438            args);                                                          \
1439        return _retok;                                                      \
1440    }
1441CALL_VIRTUAL(jobject, Object, Object* result, result=(Object*), (jobject) result, 'L');
1442CALL_VIRTUAL(jboolean, Boolean, jboolean result, result=, (jboolean) result, 'Z');
1443CALL_VIRTUAL(jbyte, Byte, jbyte result, result=, (jbyte) result, 'B');
1444CALL_VIRTUAL(jchar, Char, jchar result, result=, (jchar) result, 'C');
1445CALL_VIRTUAL(jshort, Short, jshort result, result=, (jshort) result, 'S');
1446CALL_VIRTUAL(jint, Int, jint result, result=, (jint) result, 'I');
1447CALL_VIRTUAL(jlong, Long, jlong result, result=, (jlong) result, 'J');
1448CALL_VIRTUAL(jfloat, Float, jfloat result, result=, (jfloat) result, 'F');
1449CALL_VIRTUAL(jdouble, Double, jdouble result, result=, (jdouble) result, 'D');
1450CALL_VIRTUAL(void, Void, , , , 'V');
1451
1452#define CALL_NONVIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok,         \
1453        _retsig)                                                            \
1454    static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env,         \
1455        jobject obj, jclass clazz, jmethodID methodID, ...)                 \
1456    {                                                                       \
1457        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1458        sc.checkClass(clazz); \
1459        sc.checkObject(obj); \
1460        sc.checkSig(methodID, _retsig, false); \
1461        sc.checkVirtualMethod(obj, methodID); \
1462        _retdecl;                                                           \
1463        va_list args;                                                       \
1464        va_start(args, methodID);                                           \
1465        _retasgn baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj,   \
1466            clazz, methodID, args);                                         \
1467        va_end(args);                                                       \
1468        return _retok;                                                      \
1469    }                                                                       \
1470    static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env,        \
1471        jobject obj, jclass clazz, jmethodID methodID, va_list args)        \
1472    {                                                                       \
1473        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1474        sc.checkClass(clazz); \
1475        sc.checkObject(obj); \
1476        sc.checkSig(methodID, _retsig, false); \
1477        sc.checkVirtualMethod(obj, methodID); \
1478        _retdecl;                                                           \
1479        _retasgn baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj,   \
1480            clazz, methodID, args);                                         \
1481        return _retok;                                                      \
1482    }                                                                       \
1483    static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env,        \
1484        jobject obj, jclass clazz, jmethodID methodID, jvalue* args)        \
1485    {                                                                       \
1486        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1487        sc.checkClass(clazz); \
1488        sc.checkObject(obj); \
1489        sc.checkSig(methodID, _retsig, false); \
1490        sc.checkVirtualMethod(obj, methodID); \
1491        _retdecl;                                                           \
1492        _retasgn baseEnv(env)->CallNonvirtual##_jname##MethodA(env, obj,   \
1493            clazz, methodID, args);                                         \
1494        return _retok;                                                      \
1495    }
1496CALL_NONVIRTUAL(jobject, Object, Object* result, result=(Object*), (jobject) result, 'L');
1497CALL_NONVIRTUAL(jboolean, Boolean, jboolean result, result=, (jboolean) result, 'Z');
1498CALL_NONVIRTUAL(jbyte, Byte, jbyte result, result=, (jbyte) result, 'B');
1499CALL_NONVIRTUAL(jchar, Char, jchar result, result=, (jchar) result, 'C');
1500CALL_NONVIRTUAL(jshort, Short, jshort result, result=, (jshort) result, 'S');
1501CALL_NONVIRTUAL(jint, Int, jint result, result=, (jint) result, 'I');
1502CALL_NONVIRTUAL(jlong, Long, jlong result, result=, (jlong) result, 'J');
1503CALL_NONVIRTUAL(jfloat, Float, jfloat result, result=, (jfloat) result, 'F');
1504CALL_NONVIRTUAL(jdouble, Double, jdouble result, result=, (jdouble) result, 'D');
1505CALL_NONVIRTUAL(void, Void, , , , 'V');
1506
1507
1508#define CALL_STATIC(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig)    \
1509    static _ctype Check_CallStatic##_jname##Method(JNIEnv* env,             \
1510        jclass clazz, jmethodID methodID, ...)                              \
1511    {                                                                       \
1512        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1513        sc.checkClass(clazz); \
1514        sc.checkSig(methodID, _retsig, true); \
1515        sc.checkStaticMethod(clazz, methodID); \
1516        _retdecl;                                                           \
1517        va_list args;                                                       \
1518        va_start(args, methodID);                                           \
1519        _retasgn baseEnv(env)->CallStatic##_jname##MethodV(env, clazz,     \
1520            methodID, args);                                                \
1521        va_end(args);                                                       \
1522        return _retok;                                                      \
1523    }                                                                       \
1524    static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env,            \
1525        jclass clazz, jmethodID methodID, va_list args)                     \
1526    {                                                                       \
1527        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1528        sc.checkClass(clazz); \
1529        sc.checkSig(methodID, _retsig, true); \
1530        sc.checkStaticMethod(clazz, methodID); \
1531        _retdecl;                                                           \
1532        _retasgn baseEnv(env)->CallStatic##_jname##MethodV(env, clazz,     \
1533            methodID, args);                                                \
1534        return _retok;                                                      \
1535    }                                                                       \
1536    static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env,            \
1537        jclass clazz, jmethodID methodID, jvalue* args)                     \
1538    {                                                                       \
1539        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1540        sc.checkClass(clazz); \
1541        sc.checkSig(methodID, _retsig, true); \
1542        sc.checkStaticMethod(clazz, methodID); \
1543        _retdecl;                                                           \
1544        _retasgn baseEnv(env)->CallStatic##_jname##MethodA(env, clazz,     \
1545            methodID, args);                                                \
1546        return _retok;                                                      \
1547    }
1548CALL_STATIC(jobject, Object, Object* result, result=(Object*), (jobject) result, 'L');
1549CALL_STATIC(jboolean, Boolean, jboolean result, result=, (jboolean) result, 'Z');
1550CALL_STATIC(jbyte, Byte, jbyte result, result=, (jbyte) result, 'B');
1551CALL_STATIC(jchar, Char, jchar result, result=, (jchar) result, 'C');
1552CALL_STATIC(jshort, Short, jshort result, result=, (jshort) result, 'S');
1553CALL_STATIC(jint, Int, jint result, result=, (jint) result, 'I');
1554CALL_STATIC(jlong, Long, jlong result, result=, (jlong) result, 'J');
1555CALL_STATIC(jfloat, Float, jfloat result, result=, (jfloat) result, 'F');
1556CALL_STATIC(jdouble, Double, jdouble result, result=, (jdouble) result, 'D');
1557CALL_STATIC(void, Void, , , , 'V');
1558
1559static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
1560    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1561    return baseEnv(env)->NewString(env, unicodeChars, len);
1562}
1563
1564static jsize Check_GetStringLength(JNIEnv* env, jstring string) {
1565    ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
1566    sc.checkString(string);
1567    return baseEnv(env)->GetStringLength(env, string);
1568}
1569
1570static const jchar* Check_GetStringChars(JNIEnv* env, jstring string, jboolean* isCopy) {
1571    ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
1572    sc.checkString(string);
1573    const jchar* result = baseEnv(env)->GetStringChars(env, string, isCopy);
1574    if (gDvmJni.forceCopy && result != NULL) {
1575        ScopedJniThreadState ts(env);
1576        StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, string);
1577        int byteCount = strObj->length() * 2;
1578        result = (const jchar*) GuardedCopy::create(result, byteCount, false);
1579        if (isCopy != NULL) {
1580            *isCopy = JNI_TRUE;
1581        }
1582    }
1583    return result;
1584}
1585
1586static void Check_ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
1587    ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
1588    sc.checkString(string);
1589    sc.checkNonNull(chars);
1590    if (gDvmJni.forceCopy) {
1591        if (!GuardedCopy::check(chars, false)) {
1592            LOGE("JNI: failed guarded copy check in ReleaseStringChars");
1593            abortMaybe();
1594            return;
1595        }
1596        chars = (const jchar*) GuardedCopy::destroy((jchar*)chars);
1597    }
1598    baseEnv(env)->ReleaseStringChars(env, string, chars);
1599}
1600
1601static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes) {
1602    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1603    sc.checkUtfString(bytes, NULL);
1604    return baseEnv(env)->NewStringUTF(env, bytes);
1605}
1606
1607static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string) {
1608    ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
1609    sc.checkString(string);
1610    return baseEnv(env)->GetStringUTFLength(env, string);
1611}
1612
1613static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) {
1614    ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
1615    sc.checkString(string);
1616    const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy);
1617    if (gDvmJni.forceCopy && result != NULL) {
1618        result = (const char*) GuardedCopy::create(result, strlen(result) + 1, false);
1619        if (isCopy != NULL) {
1620            *isCopy = JNI_TRUE;
1621        }
1622    }
1623    return result;
1624}
1625
1626static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
1627    ScopedCheck sc(env, kFlag_ExcepOkay, __FUNCTION__);
1628    sc.checkString(string);
1629    sc.checkNonNull(utf);
1630    if (gDvmJni.forceCopy) {
1631        if (!GuardedCopy::check(utf, false)) {
1632            LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars");
1633            abortMaybe();
1634            return;
1635        }
1636        utf = (const char*) GuardedCopy::destroy((char*)utf);
1637    }
1638    baseEnv(env)->ReleaseStringUTFChars(env, string, utf);
1639}
1640
1641static jsize Check_GetArrayLength(JNIEnv* env, jarray array) {
1642    ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
1643    sc.checkArray(array);
1644    return baseEnv(env)->GetArrayLength(env, array);
1645}
1646
1647static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length,
1648    jclass elementClass, jobject initialElement)
1649{
1650    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1651    sc.checkClass(elementClass);
1652    sc.checkObject(initialElement);
1653    sc.checkLengthPositive(length);
1654    return baseEnv(env)->NewObjectArray(env, length, elementClass, initialElement);
1655}
1656
1657static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
1658    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1659    sc.checkArray(array);
1660    return baseEnv(env)->GetObjectArrayElement(env, array, index);
1661}
1662
1663static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value)
1664{
1665    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1666    sc.checkArray(array);
1667    baseEnv(env)->SetObjectArrayElement(env, array, index, value);
1668}
1669
1670#define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
1671    static _artype Check_New##_jname##Array(JNIEnv* env, jsize length) { \
1672        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1673        sc.checkLengthPositive(length); \
1674        return baseEnv(env)->New##_jname##Array(env, length); \
1675    }
1676NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1677NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1678NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1679NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1680NEW_PRIMITIVE_ARRAY(jintArray, Int);
1681NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1682NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1683NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1684
1685
1686/*
1687 * Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
1688 * The code deliberately uses an invalid sequence of operations, so we
1689 * need to pass it through unmodified.  Review that code before making
1690 * any changes here.
1691 */
1692#define kNoCopyMagic    0xd5aab57f
1693
1694#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)                        \
1695    static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env,            \
1696        _ctype##Array array, jboolean* isCopy)                              \
1697    {                                                                       \
1698        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1699        sc.checkArray(array); \
1700        u4 noCopy = 0;                                                      \
1701        if (gDvmJni.forceCopy && isCopy != NULL) { \
1702            /* capture this before the base call tramples on it */          \
1703            noCopy = *(u4*) isCopy;                                         \
1704        }                                                                   \
1705        _ctype* result = baseEnv(env)->Get##_jname##ArrayElements(env, array, isCopy); \
1706        if (gDvmJni.forceCopy && result != NULL) { \
1707            if (noCopy == kNoCopyMagic) {                                   \
1708                LOGV("FC: not copying %p %x", array, noCopy); \
1709            } else {                                                        \
1710                result = (_ctype*) createGuardedPACopy(env, array, isCopy); \
1711            }                                                               \
1712        }                                                                   \
1713        return result;                                                      \
1714    }
1715
1716#define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)                    \
1717    static void Check_Release##_jname##ArrayElements(JNIEnv* env,           \
1718        _ctype##Array array, _ctype* elems, jint mode)                      \
1719    {                                                                       \
1720        ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__); \
1721        sc.checkArray(array);                                            \
1722        sc.checkNonNull(elems); \
1723        sc.checkReleaseMode(mode); \
1724        if (gDvmJni.forceCopy) { \
1725            if ((uintptr_t)elems == kNoCopyMagic) {                         \
1726                LOGV("FC: not freeing %p", array); \
1727                elems = NULL;   /* base JNI call doesn't currently need */  \
1728            } else {                                                        \
1729                elems = (_ctype*) releaseGuardedPACopy(env, array, elems,   \
1730                        mode);                                              \
1731            }                                                               \
1732        }                                                                   \
1733        baseEnv(env)->Release##_jname##ArrayElements(env, array, elems, mode); \
1734    }
1735
1736#define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1737    static void Check_Get##_jname##ArrayRegion(JNIEnv* env, \
1738        _ctype##Array array, jsize start, jsize len, _ctype* buf) { \
1739        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1740        sc.checkArray(array); \
1741        baseEnv(env)->Get##_jname##ArrayRegion(env, array, start, len, buf); \
1742    }
1743
1744#define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1745    static void Check_Set##_jname##ArrayRegion(JNIEnv* env, \
1746        _ctype##Array array, jsize start, jsize len, const _ctype* buf) { \
1747        ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
1748        sc.checkArray(array); \
1749        baseEnv(env)->Set##_jname##ArrayRegion(env, array, start, len, buf); \
1750    }
1751
1752#define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar)                \
1753    GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname);                           \
1754    RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname);                       \
1755    GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);                             \
1756    SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1757
1758/* TODO: verify primitive array type matches call type */
1759PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1760PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1761PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1762PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1763PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1764PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1765PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1766PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1767
1768static jint Check_RegisterNatives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods,
1769        jint nMethods)
1770{
1771    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1772    sc.checkClass(clazz);
1773    return baseEnv(env)->RegisterNatives(env, clazz, methods, nMethods);
1774}
1775
1776static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz) {
1777    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1778    sc.checkClass(clazz);
1779    return baseEnv(env)->UnregisterNatives(env, clazz);
1780}
1781
1782static jint Check_MonitorEnter(JNIEnv* env, jobject obj) {
1783    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1784    sc.checkObject(obj);
1785    return baseEnv(env)->MonitorEnter(env, obj);
1786}
1787
1788static jint Check_MonitorExit(JNIEnv* env, jobject obj) {
1789    ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
1790    sc.checkObject(obj);
1791    return baseEnv(env)->MonitorExit(env, obj);
1792}
1793
1794static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm) {
1795    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1796    return baseEnv(env)->GetJavaVM(env, vm);
1797}
1798
1799static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) {
1800    ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
1801    sc.checkString(str);
1802    baseEnv(env)->GetStringRegion(env, str, start, len, buf);
1803}
1804
1805static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) {
1806    ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
1807    sc.checkString(str);
1808    baseEnv(env)->GetStringUTFRegion(env, str, start, len, buf);
1809}
1810
1811static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) {
1812    ScopedCheck sc(env, kFlag_CritGet, __FUNCTION__);
1813    sc.checkArray(array);
1814    void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy);
1815    if (gDvmJni.forceCopy && result != NULL) {
1816        result = createGuardedPACopy(env, array, isCopy);
1817    }
1818    return result;
1819}
1820
1821static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode)
1822{
1823    ScopedCheck sc(env, kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
1824    sc.checkArray(array);
1825    sc.checkNonNull(carray);
1826    sc.checkReleaseMode(mode);
1827    if (gDvmJni.forceCopy) {
1828        carray = releaseGuardedPACopy(env, array, carray, mode);
1829    }
1830    baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1831}
1832
1833static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string, jboolean* isCopy) {
1834    ScopedCheck sc(env, kFlag_CritGet, __FUNCTION__);
1835    sc.checkString(string);
1836    const jchar* result = baseEnv(env)->GetStringCritical(env, string, isCopy);
1837    if (gDvmJni.forceCopy && result != NULL) {
1838        ScopedJniThreadState ts(env);
1839        StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, string);
1840        int byteCount = strObj->length() * 2;
1841        result = (const jchar*) GuardedCopy::create(result, byteCount, false);
1842        if (isCopy != NULL) {
1843            *isCopy = JNI_TRUE;
1844        }
1845    }
1846    return result;
1847}
1848
1849static void Check_ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* carray) {
1850    ScopedCheck sc(env, kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
1851    sc.checkString(string);
1852    sc.checkNonNull(carray);
1853    if (gDvmJni.forceCopy) {
1854        if (!GuardedCopy::check(carray, false)) {
1855            LOGE("JNI: failed guarded copy check in ReleaseStringCritical");
1856            abortMaybe();
1857            return;
1858        }
1859        carray = (const jchar*) GuardedCopy::destroy((jchar*)carray);
1860    }
1861    baseEnv(env)->ReleaseStringCritical(env, string, carray);
1862}
1863
1864static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj) {
1865    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1866    sc.checkObject(obj);
1867    return baseEnv(env)->NewWeakGlobalRef(env, obj);
1868}
1869
1870static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1871    ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
1872    sc.checkObject(obj);
1873    baseEnv(env)->DeleteWeakGlobalRef(env, obj);
1874}
1875
1876static jboolean Check_ExceptionCheck(JNIEnv* env) {
1877    ScopedCheck sc(env, kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1878    return baseEnv(env)->ExceptionCheck(env);
1879}
1880
1881static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj) {
1882    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1883    sc.checkObject(obj);
1884    return baseEnv(env)->GetObjectRefType(env, obj);
1885}
1886
1887static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
1888    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1889    if (address == NULL || capacity < 0) {
1890        LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)",
1891            address, (long) capacity);
1892        abortMaybe();
1893        return NULL;
1894    }
1895    return baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
1896}
1897
1898static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf) {
1899    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1900    sc.checkObject(buf);
1901    return baseEnv(env)->GetDirectBufferAddress(env, buf);
1902}
1903
1904static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
1905    ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
1906    sc.checkObject(buf);
1907    /* TODO: verify "buf" is an instance of java.nio.Buffer */
1908    return baseEnv(env)->GetDirectBufferCapacity(env, buf);
1909}
1910
1911
1912/*
1913 * ===========================================================================
1914 *      JNI invocation functions
1915 * ===========================================================================
1916 */
1917
1918static jint Check_DestroyJavaVM(JavaVM* vm) {
1919    ScopedVmCheck svc(false, __FUNCTION__);
1920    return baseVm(vm)->DestroyJavaVM(vm);
1921}
1922
1923static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
1924    ScopedVmCheck svc(false, __FUNCTION__);
1925    return baseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
1926}
1927
1928static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
1929    ScopedVmCheck svc(false, __FUNCTION__);
1930    return baseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
1931}
1932
1933static jint Check_DetachCurrentThread(JavaVM* vm) {
1934    ScopedVmCheck svc(true, __FUNCTION__);
1935    return baseVm(vm)->DetachCurrentThread(vm);
1936}
1937
1938static jint Check_GetEnv(JavaVM* vm, void** env, jint version) {
1939    ScopedVmCheck svc(true, __FUNCTION__);
1940    return baseVm(vm)->GetEnv(vm, env, version);
1941}
1942
1943
1944/*
1945 * ===========================================================================
1946 *      Function tables
1947 * ===========================================================================
1948 */
1949
1950static const struct JNINativeInterface gCheckNativeInterface = {
1951    NULL,
1952    NULL,
1953    NULL,
1954    NULL,
1955
1956    Check_GetVersion,
1957
1958    Check_DefineClass,
1959    Check_FindClass,
1960
1961    Check_FromReflectedMethod,
1962    Check_FromReflectedField,
1963    Check_ToReflectedMethod,
1964
1965    Check_GetSuperclass,
1966    Check_IsAssignableFrom,
1967
1968    Check_ToReflectedField,
1969
1970    Check_Throw,
1971    Check_ThrowNew,
1972    Check_ExceptionOccurred,
1973    Check_ExceptionDescribe,
1974    Check_ExceptionClear,
1975    Check_FatalError,
1976
1977    Check_PushLocalFrame,
1978    Check_PopLocalFrame,
1979
1980    Check_NewGlobalRef,
1981    Check_DeleteGlobalRef,
1982    Check_DeleteLocalRef,
1983    Check_IsSameObject,
1984    Check_NewLocalRef,
1985    Check_EnsureLocalCapacity,
1986
1987    Check_AllocObject,
1988    Check_NewObject,
1989    Check_NewObjectV,
1990    Check_NewObjectA,
1991
1992    Check_GetObjectClass,
1993    Check_IsInstanceOf,
1994
1995    Check_GetMethodID,
1996
1997    Check_CallObjectMethod,
1998    Check_CallObjectMethodV,
1999    Check_CallObjectMethodA,
2000    Check_CallBooleanMethod,
2001    Check_CallBooleanMethodV,
2002    Check_CallBooleanMethodA,
2003    Check_CallByteMethod,
2004    Check_CallByteMethodV,
2005    Check_CallByteMethodA,
2006    Check_CallCharMethod,
2007    Check_CallCharMethodV,
2008    Check_CallCharMethodA,
2009    Check_CallShortMethod,
2010    Check_CallShortMethodV,
2011    Check_CallShortMethodA,
2012    Check_CallIntMethod,
2013    Check_CallIntMethodV,
2014    Check_CallIntMethodA,
2015    Check_CallLongMethod,
2016    Check_CallLongMethodV,
2017    Check_CallLongMethodA,
2018    Check_CallFloatMethod,
2019    Check_CallFloatMethodV,
2020    Check_CallFloatMethodA,
2021    Check_CallDoubleMethod,
2022    Check_CallDoubleMethodV,
2023    Check_CallDoubleMethodA,
2024    Check_CallVoidMethod,
2025    Check_CallVoidMethodV,
2026    Check_CallVoidMethodA,
2027
2028    Check_CallNonvirtualObjectMethod,
2029    Check_CallNonvirtualObjectMethodV,
2030    Check_CallNonvirtualObjectMethodA,
2031    Check_CallNonvirtualBooleanMethod,
2032    Check_CallNonvirtualBooleanMethodV,
2033    Check_CallNonvirtualBooleanMethodA,
2034    Check_CallNonvirtualByteMethod,
2035    Check_CallNonvirtualByteMethodV,
2036    Check_CallNonvirtualByteMethodA,
2037    Check_CallNonvirtualCharMethod,
2038    Check_CallNonvirtualCharMethodV,
2039    Check_CallNonvirtualCharMethodA,
2040    Check_CallNonvirtualShortMethod,
2041    Check_CallNonvirtualShortMethodV,
2042    Check_CallNonvirtualShortMethodA,
2043    Check_CallNonvirtualIntMethod,
2044    Check_CallNonvirtualIntMethodV,
2045    Check_CallNonvirtualIntMethodA,
2046    Check_CallNonvirtualLongMethod,
2047    Check_CallNonvirtualLongMethodV,
2048    Check_CallNonvirtualLongMethodA,
2049    Check_CallNonvirtualFloatMethod,
2050    Check_CallNonvirtualFloatMethodV,
2051    Check_CallNonvirtualFloatMethodA,
2052    Check_CallNonvirtualDoubleMethod,
2053    Check_CallNonvirtualDoubleMethodV,
2054    Check_CallNonvirtualDoubleMethodA,
2055    Check_CallNonvirtualVoidMethod,
2056    Check_CallNonvirtualVoidMethodV,
2057    Check_CallNonvirtualVoidMethodA,
2058
2059    Check_GetFieldID,
2060
2061    Check_GetObjectField,
2062    Check_GetBooleanField,
2063    Check_GetByteField,
2064    Check_GetCharField,
2065    Check_GetShortField,
2066    Check_GetIntField,
2067    Check_GetLongField,
2068    Check_GetFloatField,
2069    Check_GetDoubleField,
2070    Check_SetObjectField,
2071    Check_SetBooleanField,
2072    Check_SetByteField,
2073    Check_SetCharField,
2074    Check_SetShortField,
2075    Check_SetIntField,
2076    Check_SetLongField,
2077    Check_SetFloatField,
2078    Check_SetDoubleField,
2079
2080    Check_GetStaticMethodID,
2081
2082    Check_CallStaticObjectMethod,
2083    Check_CallStaticObjectMethodV,
2084    Check_CallStaticObjectMethodA,
2085    Check_CallStaticBooleanMethod,
2086    Check_CallStaticBooleanMethodV,
2087    Check_CallStaticBooleanMethodA,
2088    Check_CallStaticByteMethod,
2089    Check_CallStaticByteMethodV,
2090    Check_CallStaticByteMethodA,
2091    Check_CallStaticCharMethod,
2092    Check_CallStaticCharMethodV,
2093    Check_CallStaticCharMethodA,
2094    Check_CallStaticShortMethod,
2095    Check_CallStaticShortMethodV,
2096    Check_CallStaticShortMethodA,
2097    Check_CallStaticIntMethod,
2098    Check_CallStaticIntMethodV,
2099    Check_CallStaticIntMethodA,
2100    Check_CallStaticLongMethod,
2101    Check_CallStaticLongMethodV,
2102    Check_CallStaticLongMethodA,
2103    Check_CallStaticFloatMethod,
2104    Check_CallStaticFloatMethodV,
2105    Check_CallStaticFloatMethodA,
2106    Check_CallStaticDoubleMethod,
2107    Check_CallStaticDoubleMethodV,
2108    Check_CallStaticDoubleMethodA,
2109    Check_CallStaticVoidMethod,
2110    Check_CallStaticVoidMethodV,
2111    Check_CallStaticVoidMethodA,
2112
2113    Check_GetStaticFieldID,
2114
2115    Check_GetStaticObjectField,
2116    Check_GetStaticBooleanField,
2117    Check_GetStaticByteField,
2118    Check_GetStaticCharField,
2119    Check_GetStaticShortField,
2120    Check_GetStaticIntField,
2121    Check_GetStaticLongField,
2122    Check_GetStaticFloatField,
2123    Check_GetStaticDoubleField,
2124
2125    Check_SetStaticObjectField,
2126    Check_SetStaticBooleanField,
2127    Check_SetStaticByteField,
2128    Check_SetStaticCharField,
2129    Check_SetStaticShortField,
2130    Check_SetStaticIntField,
2131    Check_SetStaticLongField,
2132    Check_SetStaticFloatField,
2133    Check_SetStaticDoubleField,
2134
2135    Check_NewString,
2136
2137    Check_GetStringLength,
2138    Check_GetStringChars,
2139    Check_ReleaseStringChars,
2140
2141    Check_NewStringUTF,
2142    Check_GetStringUTFLength,
2143    Check_GetStringUTFChars,
2144    Check_ReleaseStringUTFChars,
2145
2146    Check_GetArrayLength,
2147    Check_NewObjectArray,
2148    Check_GetObjectArrayElement,
2149    Check_SetObjectArrayElement,
2150
2151    Check_NewBooleanArray,
2152    Check_NewByteArray,
2153    Check_NewCharArray,
2154    Check_NewShortArray,
2155    Check_NewIntArray,
2156    Check_NewLongArray,
2157    Check_NewFloatArray,
2158    Check_NewDoubleArray,
2159
2160    Check_GetBooleanArrayElements,
2161    Check_GetByteArrayElements,
2162    Check_GetCharArrayElements,
2163    Check_GetShortArrayElements,
2164    Check_GetIntArrayElements,
2165    Check_GetLongArrayElements,
2166    Check_GetFloatArrayElements,
2167    Check_GetDoubleArrayElements,
2168
2169    Check_ReleaseBooleanArrayElements,
2170    Check_ReleaseByteArrayElements,
2171    Check_ReleaseCharArrayElements,
2172    Check_ReleaseShortArrayElements,
2173    Check_ReleaseIntArrayElements,
2174    Check_ReleaseLongArrayElements,
2175    Check_ReleaseFloatArrayElements,
2176    Check_ReleaseDoubleArrayElements,
2177
2178    Check_GetBooleanArrayRegion,
2179    Check_GetByteArrayRegion,
2180    Check_GetCharArrayRegion,
2181    Check_GetShortArrayRegion,
2182    Check_GetIntArrayRegion,
2183    Check_GetLongArrayRegion,
2184    Check_GetFloatArrayRegion,
2185    Check_GetDoubleArrayRegion,
2186    Check_SetBooleanArrayRegion,
2187    Check_SetByteArrayRegion,
2188    Check_SetCharArrayRegion,
2189    Check_SetShortArrayRegion,
2190    Check_SetIntArrayRegion,
2191    Check_SetLongArrayRegion,
2192    Check_SetFloatArrayRegion,
2193    Check_SetDoubleArrayRegion,
2194
2195    Check_RegisterNatives,
2196    Check_UnregisterNatives,
2197
2198    Check_MonitorEnter,
2199    Check_MonitorExit,
2200
2201    Check_GetJavaVM,
2202
2203    Check_GetStringRegion,
2204    Check_GetStringUTFRegion,
2205
2206    Check_GetPrimitiveArrayCritical,
2207    Check_ReleasePrimitiveArrayCritical,
2208
2209    Check_GetStringCritical,
2210    Check_ReleaseStringCritical,
2211
2212    Check_NewWeakGlobalRef,
2213    Check_DeleteWeakGlobalRef,
2214
2215    Check_ExceptionCheck,
2216
2217    Check_NewDirectByteBuffer,
2218    Check_GetDirectBufferAddress,
2219    Check_GetDirectBufferCapacity,
2220
2221    Check_GetObjectRefType
2222};
2223
2224static const struct JNIInvokeInterface gCheckInvokeInterface = {
2225    NULL,
2226    NULL,
2227    NULL,
2228
2229    Check_DestroyJavaVM,
2230    Check_AttachCurrentThread,
2231    Check_DetachCurrentThread,
2232
2233    Check_GetEnv,
2234
2235    Check_AttachCurrentThreadAsDaemon,
2236};
2237
2238/*
2239 * Replace the normal table with the checked table.
2240 */
2241void dvmUseCheckedJniEnv(JNIEnvExt* pEnv) {
2242    assert(pEnv->funcTable != &gCheckNativeInterface);
2243    pEnv->baseFuncTable = pEnv->funcTable;
2244    pEnv->funcTable = &gCheckNativeInterface;
2245}
2246
2247/*
2248 * Replace the normal table with the checked table.
2249 */
2250void dvmUseCheckedJniVm(JavaVMExt* pVm) {
2251    assert(pVm->funcTable != &gCheckInvokeInterface);
2252    pVm->baseFuncTable = pVm->funcTable;
2253    pVm->funcTable = &gCheckInvokeInterface;
2254}
2255