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