cgen: fix gen_struct_equality_fn null pointer crash (fix #25237) (#25231)

This commit is contained in:
xieke 2025-09-08 22:32:46 +08:00 committed by GitHub
parent b50327ad89
commit af87a302fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 52 additions and 12 deletions

View file

@ -15,6 +15,6 @@ fn test_main() {
assert data.str() == 'Alias(SomeStruct{ assert data.str() == 'Alias(SomeStruct{
random_field_a: Option(none) random_field_a: Option(none)
random_field_b: Option(none) random_field_b: Option(none)
empty_field: Option(none) empty_field: Option(Empty{})
})' })'
} }

View file

@ -214,21 +214,22 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
field_type := g.unwrap(field.typ) field_type := g.unwrap(field.typ)
field_name := c_name(field.name) field_name := c_name(field.name)
left_arg := g.read_field(left_type, field_name, 'a') mut left_arg := g.read_field(left_type, field_name, 'a')
right_arg := g.read_field(left_type, field_name, 'b') mut right_arg := g.read_field(left_type, field_name, 'b')
if field.typ.has_flag(.option) { if field.typ.has_flag(.option) {
fn_builder.write_string('((${left_arg}.state == ${right_arg}.state && ${right_arg}.state == 2) || ') fn_builder.write_string('((${left_arg}.state == ${right_arg}.state && ${right_arg}.state == 2) || (${left_arg}.state != 2 && ${right_arg}.state != 2 && (')
} }
if field_type.sym.kind == .string { if field_type.sym.kind == .string {
if field.typ.has_flag(.option) { if field.typ.has_flag(.option) {
left_arg_opt := g.read_opt_field(left_type, field_name, 'a', field.typ) left_arg = g.read_opt_field(left_type, field_name, 'a', field.typ)
right_arg_opt := g.read_opt_field(left_type, field_name, 'b', field.typ) right_arg = g.read_opt_field(left_type, field_name, 'b', field.typ)
fn_builder.write_string('(((${left_arg_opt}).len == (${right_arg_opt}).len && (${left_arg_opt}).len == 0) || fast_string_eq(${left_arg_opt}, ${right_arg_opt}))') }
} else if field.typ.is_ptr() {
fn_builder.write_string('((${left_arg}->len == ${right_arg}->len && ${left_arg}->len == 0) || fast_string_eq(*(${left_arg}), *(${right_arg})))') if field.typ.is_ptr() {
fn_builder.write_string('(${left_arg} == ${right_arg} || (${left_arg} != 0 && ${right_arg} != 0 && ((${left_arg})->len == (${right_arg})->len && (${left_arg})->len == 0) || fast_string_eq(*(${left_arg}), *(${right_arg}))))')
} else { } else {
fn_builder.write_string('((${left_arg}.len == ${right_arg}.len && ${left_arg}.len == 0) || fast_string_eq(${left_arg}, ${right_arg}))') fn_builder.write_string('(((${left_arg}).len == (${right_arg}).len && (${left_arg}).len == 0) || fast_string_eq(${left_arg}, ${right_arg}))')
} }
} else if field_type.sym.kind == .sum_type && !field.typ.is_ptr() { } else if field_type.sym.kind == .sum_type && !field.typ.is_ptr() {
eq_fn := g.gen_sumtype_equality_fn(field.typ) eq_fn := g.gen_sumtype_equality_fn(field.typ)
@ -260,7 +261,7 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
fn_builder.write_string('${eq_fn}_alias_eq(${left_arg}, ${right_arg})') fn_builder.write_string('${eq_fn}_alias_eq(${left_arg}, ${right_arg})')
} }
} else if field_type.sym.kind == .function && !field.typ.has_flag(.option) { } else if field_type.sym.kind == .function && !field.typ.has_flag(.option) {
fn_builder.write_string('*((voidptr*)(${left_arg})) == *((voidptr*)(${right_arg}))') fn_builder.write_string('((voidptr*)(${left_arg})) == ((voidptr*)(${right_arg}))')
} else if field_type.sym.kind == .interface } else if field_type.sym.kind == .interface
&& (!field.typ.has_flag(.option) || !field.typ.is_ptr()) { && (!field.typ.has_flag(.option) || !field.typ.is_ptr()) {
ptr := if field.typ.is_ptr() { '*'.repeat(field.typ.nr_muls()) } else { '' } ptr := if field.typ.is_ptr() { '*'.repeat(field.typ.nr_muls()) } else { '' }
@ -278,7 +279,7 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
fn_builder.write_string('${left_arg} == ${right_arg}') fn_builder.write_string('${left_arg} == ${right_arg}')
} }
if field.typ.has_flag(.option) { if field.typ.has_flag(.option) {
fn_builder.write_string(')') fn_builder.write_string(')))')
} }
} }
} else { } else {

View file

@ -119,6 +119,19 @@ ${dec_fn_dec} {
} }
} }
') ')
if utyp.has_flag(.option) {
dec.writeln('\tif (cJSON_IsNull(root)) {')
dec.writeln('\t${result_name}_${ret_styp} ret;')
dec.writeln('\t_result_ok(&res, (${result_name}*)&ret, sizeof(res));')
dec.writeln('\treturn ret;')
dec.writeln('\t}')
base_type := utyp.clear_flag(.option)
base_type_str := g.styp(base_type)
dec.writeln('\t_option_ok(&(${base_type_str}[]){ ${g.type_default(base_type)} }, (${styp}*)&res, sizeof(${base_type_str}));\n')
}
extern_str := if g.pref.parallel_cc { 'extern ' } else { '' } extern_str := if g.pref.parallel_cc { 'extern ' } else { '' }
g.json_forward_decls.writeln('${extern_str}${dec_fn_dec};') g.json_forward_decls.writeln('${extern_str}${dec_fn_dec};')
// Codegen encoder // Codegen encoder

View file

@ -0,0 +1,26 @@
pub struct SomeStruct {
pub mut:
test ?string
}
pub struct MyStruct {
pub mut:
id string
result ?SomeStruct
}
fn test_struct_with_option_fields_inequality() {
a := MyStruct{
id: 'some id'
result: none
}
b := MyStruct{
id: 'some id'
result: SomeStruct{}
}
dump(a)
dump(b)
dump(a == b)
dump(a != b)
assert a != b
}