json: fix raw json string decoding crash when expected key is missing (#7206)

pull/7226/head
Seven Du 2020-12-10 03:10:41 +08:00 committed by GitHub
parent 032ea0f4f8
commit 4a35a75b64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 2 deletions

View File

@ -111,6 +111,22 @@ pub fn tos3(s charptr) string {
} }
} }
// Same as `tos2`, but returns empty string on nil ptr
pub fn tos4(s byteptr) string {
if s == 0 {
return ""
}
return tos2(s)
}
// Same as `tos4`, but for char*, to avoid warnings
pub fn tos5(s charptr) string {
if s == 0 {
return ""
}
return tos3(s)
}
[deprecated] [deprecated]
pub fn tos_lit(s charptr) string { pub fn tos_lit(s charptr) string {
eprintln('warning: `tos_lit` has been deprecated, use `_SLIT` instead') eprintln('warning: `tos_lit` has been deprecated, use `_SLIT` instead')

View File

@ -111,6 +111,15 @@ fn test_raw_json_field() {
assert color.space == 'YCbCr' assert color.space == 'YCbCr'
} }
fn test_bad_raw_json_field() {
color := json.decode(Color, '{"space": "YCbCr"}') or {
println('text')
return
}
assert color.point == ''
assert color.space == 'YCbCr'
}
struct City { struct City {
name string name string
} }
@ -310,3 +319,35 @@ fn test_encode_alias_struct() {
out := json.encode(msg) out := json.encode(msg)
assert out == expected assert out == expected
} }
struct List {
id int
items []string
}
fn test_list() {
list := json.decode(List, '{"id": 1, "items": ["1", "2"]}') or {
println('error')
return
}
assert list.id == 1
assert list.items == ["1", "2"]
}
fn test_list_no_id() {
list := json.decode(List, '{"items": ["1", "2"]}') or {
println('error')
return
}
assert list.id == 0
assert list.items == ["1", "2"]
}
fn test_list_no_items() {
list := json.decode(List, '{"id": 1}') or {
println('error')
return
}
assert list.id == 1
assert list.items == []
}

View File

@ -127,7 +127,7 @@ fn (mut g Gen) gen_struct_enc_dec(type_info table.TypeInfo, styp string, mut enc
field_type := g.typ(field.typ) field_type := g.typ(field.typ)
field_sym := g.table.get_type_symbol(field.typ) field_sym := g.table.get_type_symbol(field.typ)
if field.attrs.contains('raw') { if field.attrs.contains('raw') {
dec.writeln('\tres.${c_name(field.name)} = tos2(cJSON_PrintUnformatted(' + 'js_get(root, "$name")));') dec.writeln('\tres.${c_name(field.name)} = tos4(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
// need to do it here so that these functions are generated first // need to do it here so that these functions are generated first
@ -211,7 +211,7 @@ fn (mut g Gen) decode_array(value_type table.Type) string {
' '
} }
return ' return '
if(!cJSON_IsArray(root)) { if(root && !cJSON_IsArray(root)) {
Option err = v_error( string_add(_SLIT("Json element is not an array: "), tos2(cJSON_PrintUnformatted(root))) ); Option err = v_error( string_add(_SLIT("Json element is not an array: "), tos2(cJSON_PrintUnformatted(root))) );
return *(Option_array_$styp *)&err; return *(Option_array_$styp *)&err;
} }