From: Jay Freeman (saurik) Date: Sun, 3 Jan 2016 09:44:02 +0000 (-0800) Subject: Improve accuracy of JNI local references tracking. X-Git-Tag: v0.9.590~87 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/4e2cc9d31bca82d99377b34371535f2ec9ee5c33?ds=sidebyside Improve accuracy of JNI local references tracking. --- diff --git a/Java/Cycript.java b/Java/Cycript.java index cf1cc8e..79ebe8e 100644 --- a/Java/Cycript.java +++ b/Java/Cycript.java @@ -62,6 +62,18 @@ public static class Wrapper return protect_; } + public Object call(String property, Object[] arguments) { + try { + return handle(protect_, property, arguments); + } catch (Throwable throwable) { + return new RuntimeException(throwable); + } + } + + public String toString() { + return call("toString", null).toString(); + } + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { diff --git a/Java/Execute.cpp b/Java/Execute.cpp index bca2e98..688de68 100644 --- a/Java/Execute.cpp +++ b/Java/Execute.cpp @@ -126,6 +126,7 @@ struct CYJavaRef { return {jni_, static_cast(value_)}; } + // XXX: this should be tied into CYJavaFrame Value_ leak() { Value_ value(value_); value_ = NULL; @@ -142,9 +143,14 @@ struct CYJavaDelete : { } - ~CYJavaDelete() { + void clear() { if (this->value_ != NULL) (this->jni_->*Delete_)(this->value_); + this->value_ = NULL; + } + + ~CYJavaDelete() { + clear(); } }; @@ -199,15 +205,24 @@ struct CYJavaLocal : { } - CYJavaLocal(CYJavaLocal &&value) : - CYJavaLocal(value.jni_, value.value_) + template + CYJavaLocal(CYJavaRef &&other) : + CYJavaLocal(other.jni_, other.value_) + { + other.value_ = NULL; + } + + CYJavaLocal(CYJavaLocal &&other) : + CYJavaLocal(static_cast &&>(other)) { - value.value_ = NULL; } - CYJavaLocal &operator =(CYJavaLocal &&other) { - std::swap(this->jni_, other.jni_); - std::swap(this->value_, other.value_); + template + CYJavaLocal &operator =(CYJavaLocal &&other) { + this->clear(); + this->jni_ = other.jni_; + this->value_ = other.value_; + other.value_ = NULL; return *this; } }; @@ -292,6 +307,10 @@ struct CYJavaFrame { operator ()(NULL); } + operator JNIEnv *() const { + return jni_; + } + jobject operator ()(jobject object) { JNIEnv *jni(jni_); jni_ = NULL; @@ -855,7 +874,9 @@ CYJavaForEachPrimitive } } -static bool CYCastJavaArguments(const CYJavaEnv &jni, const CYJavaShorty &shorty, JSContextRef context, const JSValueRef arguments[], jvalue *array) { +static bool CYCastJavaArguments(const CYJavaFrame &frame, const CYJavaShorty &shorty, JSContextRef context, const JSValueRef arguments[], jvalue *array) { + CYJavaEnv jni(frame); + for (size_t index(0); index != shorty.size(); ++index) { JSValueRef argument(arguments[index]); JSType type(JSValueGetType(context, argument)); @@ -863,6 +884,7 @@ static bool CYCastJavaArguments(const CYJavaEnv &jni, const CYJavaShorty &shorty switch (CYJavaPrimitive primitive = shorty[index]) { case CYJavaPrimitiveObject: + // XXX: figure out a way to tie this in to the CYJavaFrame value.l = CYCastJavaObject(jni, context, argument).leak(); break; @@ -912,9 +934,9 @@ static JSValueRef JavaMethod_callAsFunction(JSContextRef context, JSObjectRef ob CYJavaSignature bound(count); for (auto overload(internal->overload_.lower_bound(bound)), e(internal->overload_.upper_bound(bound)); overload != e; ++overload) { - CYJavaFrame(jni, count + 16); + CYJavaFrame frame(jni, count + 16); jvalue array[count]; - if (!CYCastJavaArguments(jni, overload->shorty_, context, arguments, array)) + if (!CYCastJavaArguments(frame, overload->shorty_, context, arguments, array)) continue; jvalue *values(array); switch (overload->primitive_) { @@ -942,9 +964,9 @@ static JSValueRef JavaStaticMethod_callAsFunction(JSContextRef context, JSObject CYJavaSignature bound(count); for (auto overload(internal->overload_.lower_bound(bound)), e(internal->overload_.upper_bound(bound)); overload != e; ++overload) { - CYJavaFrame(jni, count + 16); + CYJavaFrame frame(jni, count + 16); jvalue array[count]; - if (!CYCastJavaArguments(jni, overload->shorty_, context, arguments, array)) + if (!CYCastJavaArguments(frame, overload->shorty_, context, arguments, array)) continue; jvalue *values(array); switch (overload->primitive_) { @@ -980,9 +1002,9 @@ static JSObjectRef JavaClass_callAsConstructor(JSContextRef context, JSObjectRef CYJavaSignature bound(count); for (auto overload(table->overload_.lower_bound(bound)), e(table->overload_.upper_bound(bound)); overload != e; ++overload) { - CYJavaFrame(jni, count + 16); + CYJavaFrame frame(jni, count + 16); jvalue array[count]; - if (!CYCastJavaArguments(jni, overload->shorty_, context, arguments, array)) + if (!CYCastJavaArguments(frame, overload->shorty_, context, arguments, array)) continue; jvalue *values(array); auto object(jni.NewObjectA(_class, overload->method_, values)); @@ -1258,11 +1280,10 @@ static jobject Cycript_handle(JNIEnv *env, jclass api, jlong jprotect, jstring p size_t count(jarguments == NULL ? 0 : jni.GetArrayLength(jarguments)); JSValueRef arguments[count]; - for (size_t index(0); index != count; ++index) { + for (size_t index(0); index != count; ++index) arguments[index] = CYCastJSValue(context, jni.GetObjectArrayElement(jarguments, index)); - } - return CYCastJavaObject(jni, context, CYCallAsFunction(context, CYCastJSObject(context, function), object, count, arguments)); + return CYCastJavaObject(jni, context, CYCallAsFunction(context, CYCastJSObject(context, function), object, count, arguments)).leak(); } CYJavaCatch(NULL) } static JNINativeMethod Cycript_[] = {