You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-05 12:10:55 +00:00
GDScript: Fix crash caused by uninitialized temp stack slots
This adds initialization to every typed temporary stack slot at the beginning of the function call instead of emitting instructions, since those might be in a conditional branch and not be called.
This commit is contained in:
@@ -129,12 +129,6 @@ uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type
|
|||||||
int idx = temporaries.size();
|
int idx = temporaries.size();
|
||||||
pool.push_back(idx);
|
pool.push_back(idx);
|
||||||
temporaries.push_back(new_temp);
|
temporaries.push_back(new_temp);
|
||||||
|
|
||||||
// First time using this, so adjust to the proper type.
|
|
||||||
if (temp_type != Variant::NIL) {
|
|
||||||
Address addr(Address::TEMPORARY, idx, p_type);
|
|
||||||
write_type_adjust(addr, temp_type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
int slot = pool.front()->get();
|
int slot = pool.front()->get();
|
||||||
pool.pop_front();
|
pool.pop_front();
|
||||||
@@ -189,8 +183,12 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
|
|||||||
append(GDScriptFunction::OPCODE_END, 0);
|
append(GDScriptFunction::OPCODE_END, 0);
|
||||||
|
|
||||||
for (int i = 0; i < temporaries.size(); i++) {
|
for (int i = 0; i < temporaries.size(); i++) {
|
||||||
|
int stack_index = i + max_locals + RESERVED_STACK;
|
||||||
for (int j = 0; j < temporaries[i].bytecode_indices.size(); j++) {
|
for (int j = 0; j < temporaries[i].bytecode_indices.size(); j++) {
|
||||||
opcodes.write[temporaries[i].bytecode_indices[j]] = (i + max_locals + RESERVED_STACK) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
|
opcodes.write[temporaries[i].bytecode_indices[j]] = stack_index | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
|
||||||
|
}
|
||||||
|
if (temporaries[i].type != Variant::NIL) {
|
||||||
|
function->temporary_slots[stack_index] = temporaries[i].type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -496,6 +496,8 @@ private:
|
|||||||
Vector<GDScriptDataType> argument_types;
|
Vector<GDScriptDataType> argument_types;
|
||||||
GDScriptDataType return_type;
|
GDScriptDataType return_type;
|
||||||
|
|
||||||
|
Map<int, Variant::Type> temporary_slots;
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
Vector<StringName> arg_names;
|
Vector<StringName> arg_names;
|
||||||
Vector<Variant> default_arg_values;
|
Vector<Variant> default_arg_values;
|
||||||
|
|||||||
@@ -152,6 +152,44 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
|
|||||||
return err_text;
|
return err_text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void (*type_init_function_table[])(Variant *) = {
|
||||||
|
nullptr, // NIL (shouldn't be called).
|
||||||
|
&VariantInitializer<bool>::init, // BOOL.
|
||||||
|
&VariantInitializer<int64_t>::init, // INT.
|
||||||
|
&VariantInitializer<double>::init, // FLOAT.
|
||||||
|
&VariantInitializer<String>::init, // STRING.
|
||||||
|
&VariantInitializer<Vector2>::init, // VECTOR2.
|
||||||
|
&VariantInitializer<Vector2i>::init, // VECTOR2I.
|
||||||
|
&VariantInitializer<Rect2>::init, // RECT2.
|
||||||
|
&VariantInitializer<Rect2i>::init, // RECT2I.
|
||||||
|
&VariantInitializer<Vector3>::init, // VECTOR3.
|
||||||
|
&VariantInitializer<Vector3i>::init, // VECTOR3I.
|
||||||
|
&VariantInitializer<Transform2D>::init, // TRANSFORM2D.
|
||||||
|
&VariantInitializer<Plane>::init, // PLANE.
|
||||||
|
&VariantInitializer<Quat>::init, // QUAT.
|
||||||
|
&VariantInitializer<AABB>::init, // AABB.
|
||||||
|
&VariantInitializer<Basis>::init, // BASIS.
|
||||||
|
&VariantInitializer<Transform>::init, // TRANSFORM.
|
||||||
|
&VariantInitializer<Color>::init, // COLOR.
|
||||||
|
&VariantInitializer<StringName>::init, // STRING_NAME.
|
||||||
|
&VariantInitializer<NodePath>::init, // NODE_PATH.
|
||||||
|
&VariantInitializer<RID>::init, // RID.
|
||||||
|
&VariantTypeAdjust<Object *>::adjust, // OBJECT.
|
||||||
|
&VariantInitializer<Callable>::init, // CALLABLE.
|
||||||
|
&VariantInitializer<Signal>::init, // SIGNAL.
|
||||||
|
&VariantInitializer<Dictionary>::init, // DICTIONARY.
|
||||||
|
&VariantInitializer<Array>::init, // ARRAY.
|
||||||
|
&VariantInitializer<PackedByteArray>::init, // PACKED_BYTE_ARRAY.
|
||||||
|
&VariantInitializer<PackedInt32Array>::init, // PACKED_INT32_ARRAY.
|
||||||
|
&VariantInitializer<PackedInt64Array>::init, // PACKED_INT64_ARRAY.
|
||||||
|
&VariantInitializer<PackedFloat32Array>::init, // PACKED_FLOAT32_ARRAY.
|
||||||
|
&VariantInitializer<PackedFloat64Array>::init, // PACKED_FLOAT64_ARRAY.
|
||||||
|
&VariantInitializer<PackedStringArray>::init, // PACKED_STRING_ARRAY.
|
||||||
|
&VariantInitializer<PackedVector2Array>::init, // PACKED_VECTOR2_ARRAY.
|
||||||
|
&VariantInitializer<PackedVector3Array>::init, // PACKED_VECTOR3_ARRAY.
|
||||||
|
&VariantInitializer<PackedColorArray>::init, // PACKED_COLOR_ARRAY.
|
||||||
|
};
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
#define OPCODES_TABLE \
|
#define OPCODES_TABLE \
|
||||||
static const void *switch_table_ops[] = { \
|
static const void *switch_table_ops[] = { \
|
||||||
@@ -491,6 +529,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
|
|
||||||
memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script));
|
memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script));
|
||||||
|
|
||||||
|
for (const Map<int, Variant::Type>::Element *E = temporary_slots.front(); E; E = E->next()) {
|
||||||
|
type_init_function_table[E->get()](&stack[E->key()]);
|
||||||
|
}
|
||||||
|
|
||||||
String err_text;
|
String err_text;
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
|||||||
Reference in New Issue
Block a user