Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

match null crashes GDScript compiler #87932

Closed
dalexeev opened this issue Feb 4, 2024 · 1 comment · Fixed by #88020
Closed

match null crashes GDScript compiler #87932

dalexeev opened this issue Feb 4, 2024 · 1 comment · Fixed by #88020

Comments

@dalexeev
Copy link
Member

dalexeev commented Feb 4, 2024

Tested versions

  • Reproducible in: 4.2.1, 4.3 dev

System information

Kubuntu 23.10

Issue description

extends Node

func _ready() -> void:
    match null:
        _:
            pass
#0  0x0000555558ce1bab in CowData<GDScriptByteCodeGenerator::StackSlot>::get (this=0x55557aebe148, p_index=4) at ./core/templates/cowdata.h:184
#1  0x0000555558cdcdcf in Vector<GDScriptByteCodeGenerator::StackSlot>::operator[] (this=0x55557aebe140, p_index=4) at ./core/templates/vector.h:97
#2  0x0000555558cd65b6 in GDScriptByteCodeGenerator::write_call_utility (this=0x55557aebe0c0, p_target=..., p_function=..., p_arguments=...) at modules/gdscript/gdscript_byte_codegen.cpp:1098
#3  0x0000555558b654b8 in GDScriptCompiler::_parse_block (this=0x7fffffff9ab0, codegen=..., p_block=0x55557db37b00, p_add_locals=true, p_reset_locals=false) at modules/gdscript/gdscript_compiler.cpp:1904
#4  0x0000555558b67d69 in GDScriptCompiler::_parse_function (this=0x7fffffff9ab0, r_error=@0x7fffffff97a0: OK, p_script=0x55557ae6da00, p_class=0x55557d9f5d40, p_func=0x55557d273640, p_for_ready=false, p_for_lambda=false) at modules/gdscript/gdscript_compiler.cpp:2356
#5  0x0000555558b6b32e in GDScriptCompiler::_compile_class (this=0x7fffffff9ab0, p_script=0x55557ae6da00, p_class=0x55557d9f5d40, p_keep_state=true) at modules/gdscript/gdscript_compiler.cpp:2874
#6  0x0000555558b6cde3 in GDScriptCompiler::compile (this=0x7fffffff9ab0, p_parser=0x7fffffff9b40, p_script=0x55557ae6da00, p_keep_state=true) at modules/gdscript/gdscript_compiler.cpp:3198

GDScriptDataType typeof_type;
typeof_type.has_type = true;
typeof_type.kind = GDScriptDataType::BUILTIN;
typeof_type.builtin_type = Variant::INT;
GDScriptCodeGenerator::Address type = codegen.add_local("@match_type", typeof_type);
Vector<GDScriptCodeGenerator::Address> typeof_args;
typeof_args.push_back(value);
gen->write_call_utility(type, "typeof", typeof_args);

if (is_validated) {
Variant::Type result_type = Variant::has_utility_function_return_value(p_function) ? Variant::get_utility_function_return_type(p_function) : Variant::NIL;
CallTarget ct = get_call_target(p_target, result_type);
Variant::Type temp_type = temporaries[ct.target.address].type;
if (result_type != temp_type) {
write_type_adjust(ct.target, result_type);
}

Steps to reproduce

Save the script above.

Minimal reproduction project (MRP)

N/A

@emre0altan
Copy link
Contributor

emre0altan commented Feb 6, 2024

I am not sure about the logic with the if statement at line 1095 but it crashes when is_validated is true because temporaries won't be populated and it will give index crash. And is_validated will only gonna be true if IS_BUILTIN_TYPE() at line 1086 returns true.

for (int i = 0; i < p_arguments.size(); i++) {
if (!IS_BUILTIN_TYPE(p_arguments[i], Variant::get_utility_function_argument_type(p_function, i))) {
all_types_exact = false;
break;
}
}
is_validated = all_types_exact;
}
if (is_validated) {
Variant::Type result_type = Variant::has_utility_function_return_value(p_function) ? Variant::get_utility_function_return_type(p_function) : Variant::NIL;

In IS_BUILTIN_TYPE(), last check returns false for non-null values because m_type is always Variant.NIL which comes from Variant::get_utility_function_argument_type() function. And this function checks the argument type for a function by looking if it's registered or not, I didn't see any call to register 'typeof' function. So it always returns NIL by default and then it gives different result for null or non-null values which are the argument here.

#define IS_BUILTIN_TYPE(m_var, m_type) \
(m_var.type.has_type && m_var.type.kind == GDScriptDataType::BUILTIN && m_var.type.builtin_type == m_type)
void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Variant::Type p_new_type) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants