Merge pull request #48793 from vnen/gdscript-fix-temp-type-adjust

GDScript: Fix crash caused by uninitialized temp stack slots
This commit is contained in:
Rémi Verschelde 2021-05-17 17:34:19 +02:00 committed by GitHub
commit 2fcfc83da9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 7 deletions

View file

@ -129,12 +129,6 @@ uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type
int idx = temporaries.size();
pool.push_back(idx);
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();
pool.pop_front();
@ -189,8 +183,12 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
append(GDScriptFunction::OPCODE_END, 0);
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++) {
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;
}
}

View file

@ -497,6 +497,8 @@ private:
Vector<GDScriptDataType> argument_types;
GDScriptDataType return_type;
Map<int, Variant::Type> temporary_slots;
#ifdef TOOLS_ENABLED
Vector<StringName> arg_names;
Vector<Variant> default_arg_values;

View file

@ -152,6 +152,44 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
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__)
#define OPCODES_TABLE \
static const void *switch_table_ops[] = { \
@ -492,6 +530,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
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;
#ifdef DEBUG_ENABLED