json: fix memory leak on result messages (checked with json_option_raw_test.v, compiled with -fsanitize=address,pointer-compare,pointer-subtract) (#23172)

This commit is contained in:
Felipe Pena 2024-12-15 11:43:43 -03:00 committed by GitHub
parent c9542a2553
commit fc8cd58782
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 12 additions and 13 deletions

View file

@ -252,6 +252,9 @@ fn json_parse(s string) &C.cJSON {
@[markused] @[markused]
fn json_print(data &C.cJSON) string { fn json_print(data &C.cJSON) string {
s := C.cJSON_PrintUnformatted(data) s := C.cJSON_PrintUnformatted(data)
if s == unsafe { nil } {
return ''
}
r := unsafe { tos_clone(&u8(s)) } r := unsafe { tos_clone(&u8(s)) }
C.cJSON_free(s) C.cJSON_free(s)
return r return r
@ -260,6 +263,9 @@ fn json_print(data &C.cJSON) string {
@[markused] @[markused]
fn json_print_pretty(data &C.cJSON) string { fn json_print_pretty(data &C.cJSON) string {
s := C.cJSON_Print(data) s := C.cJSON_Print(data)
if s == unsafe { nil } {
return ''
}
r := unsafe { tos_clone(&u8(s)) } r := unsafe { tos_clone(&u8(s)) }
C.cJSON_free(s) C.cJSON_free(s)
return r return r

View file

@ -214,11 +214,6 @@ ${enc_fn_dec} {
// cJSON_delete // cJSON_delete
dec.writeln('\t${result_name}_${ret_styp} ret;') dec.writeln('\t${result_name}_${ret_styp} ret;')
dec.writeln('\t_result_ok(&res, (${result_name}*)&ret, sizeof(res));') dec.writeln('\t_result_ok(&res, (${result_name}*)&ret, sizeof(res));')
if utyp.has_flag(.option) {
dec.writeln('\tif (res.state != 2) {')
dec.writeln('\t\t_option_ok(&res.data, (${option_name}*)&ret.data, sizeof(${g.base_type(utyp)}));')
dec.writeln('\t}')
}
dec.writeln('\treturn ret;\n}') dec.writeln('\treturn ret;\n}')
enc.writeln('\treturn o;\n}') enc.writeln('\treturn o;\n}')
g.gowrappers.writeln(dec.str()) g.gowrappers.writeln(dec.str())
@ -646,7 +641,7 @@ fn (mut g Gen) gen_prim_type_validation(name string, typ ast.Type, tmp string, r
return return
} }
dec.writeln('if (!(${type_check})) {') dec.writeln('if (!(${type_check})) {')
dec.writeln('\treturn (${ret_styp}){ .is_error = true, .err = _v_error(string__plus(_SLIT("type mismatch for field \'${name}\', expecting `${g.table.type_to_str(typ)}` type, got: "), tos5(cJSON_PrintUnformatted(jsonroot_${tmp})))), .data = {0} };') dec.writeln('\treturn (${ret_styp}){ .is_error = true, .err = _v_error(string__plus(_SLIT("type mismatch for field \'${name}\', expecting `${g.table.type_to_str(typ)}` type, got: "), json__json_print(jsonroot_${tmp}))), .data = {0} };')
dec.writeln('}') dec.writeln('}')
} }
@ -712,11 +707,9 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
} }
dec.writeln('\t\t_option_none(&(${base_typ}[]) { ${default_init} }, (${option_name}*)&${prefix}${op}${c_name(field.name)}, sizeof(${base_typ}));') dec.writeln('\t\t_option_none(&(${base_typ}[]) { ${default_init} }, (${option_name}*)&${prefix}${op}${c_name(field.name)}, sizeof(${base_typ}));')
dec.writeln('\telse') dec.writeln('\telse')
dec.writeln('\t\t_option_ok(&(${base_typ}[]) { tos5(cJSON_PrintUnformatted(js_get(root, "${name}"))) }, (${option_name}*)&${prefix}${op}${c_name(field.name)}, sizeof(${base_typ}));') dec.writeln('\t\t_option_ok(&(${base_typ}[]) { json__json_print(js_get(root, "${name}")) }, (${option_name}*)&${prefix}${op}${c_name(field.name)}, sizeof(${base_typ}));')
} else { } else {
dec.writeln( dec.writeln('\t${prefix}${op}${c_name(field.name)} = json__json_print(js_get(root, "${name}"));')
'\t${prefix}${op}${c_name(field.name)} = tos5(cJSON_PrintUnformatted(' +
'js_get(root, "${name}")));')
} }
} else { } else {
// Now generate decoders for all field types in this struct // Now generate decoders for all field types in this struct
@ -1076,7 +1069,7 @@ fn (mut g Gen) decode_array(utyp ast.Type, value_type ast.Type, fixed_array_size
return ' return '
if(root && !cJSON_IsArray(root) && !cJSON_IsNull(root)) { if(root && !cJSON_IsArray(root) && !cJSON_IsNull(root)) {
return (${result_name}_${ret_styp}){.is_error = true, .err = _v_error(string__plus(_SLIT("Json element is not an array: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}}; return (${result_name}_${ret_styp}){.is_error = true, .err = _v_error(string__plus(_SLIT("Json element is not an array: "), json__json_print(root))), .data = {0}};
} }
${res_str} ${res_str}
const cJSON *jsval = NULL; const cJSON *jsval = NULL;
@ -1145,7 +1138,7 @@ fn (mut g Gen) decode_map(utyp ast.Type, key_type ast.Type, value_type ast.Type,
if utyp.has_flag(.option) { if utyp.has_flag(.option) {
return ' return '
if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) { if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) {
return (${result_name}_${ustyp}){ .is_error = true, .err = _v_error(string__plus(_SLIT("Json element is not an object: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}}; return (${result_name}_${ustyp}){ .is_error = true, .err = _v_error(string__plus(_SLIT("Json element is not an object: "), json__json_print(root))), .data = {0}};
} }
_option_ok(&(${g.base_type(utyp)}[]) { new_map(sizeof(${styp}), sizeof(${styp_v}), ${hash_fn}, ${key_eq_fn}, ${clone_fn}, ${free_fn}) }, (${option_name}*)&res, sizeof(${g.base_type(utyp)})); _option_ok(&(${g.base_type(utyp)}[]) { new_map(sizeof(${styp}), sizeof(${styp_v}), ${hash_fn}, ${key_eq_fn}, ${clone_fn}, ${free_fn}) }, (${option_name}*)&res, sizeof(${g.base_type(utyp)}));
cJSON *jsval = NULL; cJSON *jsval = NULL;
@ -1159,7 +1152,7 @@ fn (mut g Gen) decode_map(utyp ast.Type, key_type ast.Type, value_type ast.Type,
} else { } else {
return ' return '
if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) { if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) {
return (${result_name}_${ustyp}){ .is_error = true, .err = _v_error(string__plus(_SLIT("Json element is not an object: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}}; return (${result_name}_${ustyp}){ .is_error = true, .err = _v_error(string__plus(_SLIT("Json element is not an object: "), json__json_print(root))), .data = {0}};
} }
res = new_map(sizeof(${styp}), sizeof(${styp_v}), ${hash_fn}, ${key_eq_fn}, ${clone_fn}, ${free_fn}); res = new_map(sizeof(${styp}), sizeof(${styp_v}), ${hash_fn}, ${key_eq_fn}, ${clone_fn}, ${free_fn});
cJSON *jsval = NULL; cJSON *jsval = NULL;