You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-14 13:41:12 +00:00
Merge pull request #110452 from limbonaut/prevent-jni-variant-conv-stack-overflow
Prevent JNI Variant conversion stack overflow
This commit is contained in:
@@ -86,9 +86,15 @@ String charsequence_to_string(JNIEnv *p_env, jobject p_charsequence) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_arg, bool force_jobject) {
|
jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_arg, bool force_jobject, int p_depth) {
|
||||||
jvalret v;
|
jvalret v;
|
||||||
|
|
||||||
|
if (p_depth > Variant::MAX_RECURSION_DEPTH) {
|
||||||
|
ERR_PRINT("Variant is too deep! Bailing.");
|
||||||
|
v.val.i = 0;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
switch (p_type) {
|
switch (p_type) {
|
||||||
case Variant::BOOL: {
|
case Variant::BOOL: {
|
||||||
if (force_jobject) {
|
if (force_jobject) {
|
||||||
@@ -185,7 +191,7 @@ jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_a
|
|||||||
|
|
||||||
for (int j = 0; j < keys.size(); j++) {
|
for (int j = 0; j < keys.size(); j++) {
|
||||||
Variant var = dict[keys[j]];
|
Variant var = dict[keys[j]];
|
||||||
jvalret valret = _variant_to_jvalue(env, var.get_type(), &var, true);
|
jvalret valret = _variant_to_jvalue(env, var.get_type(), &var, true, p_depth + 1);
|
||||||
env->SetObjectArrayElement(jvalues, j, valret.val.l);
|
env->SetObjectArrayElement(jvalues, j, valret.val.l);
|
||||||
if (valret.obj) {
|
if (valret.obj) {
|
||||||
env->DeleteLocalRef(valret.obj);
|
env->DeleteLocalRef(valret.obj);
|
||||||
@@ -208,7 +214,7 @@ jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_a
|
|||||||
|
|
||||||
for (int j = 0; j < array.size(); j++) {
|
for (int j = 0; j < array.size(); j++) {
|
||||||
Variant var = array[j];
|
Variant var = array[j];
|
||||||
jvalret valret = _variant_to_jvalue(env, var.get_type(), &var, true);
|
jvalret valret = _variant_to_jvalue(env, var.get_type(), &var, true, p_depth + 1);
|
||||||
env->SetObjectArrayElement(arr, j, valret.val.l);
|
env->SetObjectArrayElement(arr, j, valret.val.l);
|
||||||
if (valret.obj) {
|
if (valret.obj) {
|
||||||
env->DeleteLocalRef(valret.obj);
|
env->DeleteLocalRef(valret.obj);
|
||||||
@@ -297,7 +303,9 @@ String _get_class_name(JNIEnv *env, jclass cls, bool *array) {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant _jobject_to_variant(JNIEnv *env, jobject obj) {
|
Variant _jobject_to_variant(JNIEnv *env, jobject obj, int p_depth) {
|
||||||
|
ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, Variant(), "Variant is too deep! Bailing.");
|
||||||
|
|
||||||
if (obj == nullptr) {
|
if (obj == nullptr) {
|
||||||
return Variant();
|
return Variant();
|
||||||
}
|
}
|
||||||
@@ -434,7 +442,7 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) {
|
|||||||
|
|
||||||
for (int i = 0; i < objCount; i++) {
|
for (int i = 0; i < objCount; i++) {
|
||||||
jobject jobj = env->GetObjectArrayElement(arr, i);
|
jobject jobj = env->GetObjectArrayElement(arr, i);
|
||||||
Variant v = _jobject_to_variant(env, jobj);
|
Variant v = _jobject_to_variant(env, jobj, p_depth + 1);
|
||||||
varr.push_back(v);
|
varr.push_back(v);
|
||||||
env->DeleteLocalRef(jobj);
|
env->DeleteLocalRef(jobj);
|
||||||
}
|
}
|
||||||
@@ -448,13 +456,13 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) {
|
|||||||
jmethodID get_keys = env->GetMethodID(oclass, "get_keys", "()[Ljava/lang/String;");
|
jmethodID get_keys = env->GetMethodID(oclass, "get_keys", "()[Ljava/lang/String;");
|
||||||
jobjectArray arr = (jobjectArray)env->CallObjectMethod(obj, get_keys);
|
jobjectArray arr = (jobjectArray)env->CallObjectMethod(obj, get_keys);
|
||||||
|
|
||||||
PackedStringArray keys = _jobject_to_variant(env, arr);
|
PackedStringArray keys = _jobject_to_variant(env, arr, p_depth + 1);
|
||||||
env->DeleteLocalRef(arr);
|
env->DeleteLocalRef(arr);
|
||||||
|
|
||||||
jmethodID get_values = env->GetMethodID(oclass, "get_values", "()[Ljava/lang/Object;");
|
jmethodID get_values = env->GetMethodID(oclass, "get_values", "()[Ljava/lang/Object;");
|
||||||
arr = (jobjectArray)env->CallObjectMethod(obj, get_values);
|
arr = (jobjectArray)env->CallObjectMethod(obj, get_values);
|
||||||
|
|
||||||
Array vals = _jobject_to_variant(env, arr);
|
Array vals = _jobject_to_variant(env, arr, p_depth + 1);
|
||||||
env->DeleteLocalRef(arr);
|
env->DeleteLocalRef(arr);
|
||||||
|
|
||||||
for (int i = 0; i < keys.size(); i++) {
|
for (int i = 0; i < keys.size(); i++) {
|
||||||
|
|||||||
@@ -44,11 +44,11 @@ struct jvalret {
|
|||||||
jvalret() { obj = nullptr; }
|
jvalret() { obj = nullptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_arg, bool force_jobject = false);
|
jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_arg, bool force_jobject = false, int p_depth = 0);
|
||||||
|
|
||||||
String _get_class_name(JNIEnv *env, jclass cls, bool *array);
|
String _get_class_name(JNIEnv *env, jclass cls, bool *array);
|
||||||
|
|
||||||
Variant _jobject_to_variant(JNIEnv *env, jobject obj);
|
Variant _jobject_to_variant(JNIEnv *env, jobject obj, int p_depth = 0);
|
||||||
|
|
||||||
Variant::Type get_jni_type(const String &p_type);
|
Variant::Type get_jni_type(const String &p_type);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user