toml: isolate, fix and regress-test sumtype cast causing memory corruption (#12329)
parent
fa02418a55
commit
5e4594a121
|
@ -21,7 +21,11 @@ pub type Any = Null
|
|||
// string returns `Any` as a string.
|
||||
pub fn (a Any) string() string {
|
||||
match a {
|
||||
string { return a as string }
|
||||
// NOTE if `.clone()` is not used here:
|
||||
// string { return a as string }
|
||||
// ... certain call-patterns to this function will cause a memory corruption.
|
||||
// See `tests/toml_memory_corruption_test.v` for a matching regression test.
|
||||
string { return (a as string).clone() }
|
||||
time.Time { return a.format_ss_micro() }
|
||||
else { return a.str() }
|
||||
}
|
||||
|
|
|
@ -35,18 +35,13 @@ fn test_parse_compact_text() {
|
|||
assert title == toml.Any('TOML Example')
|
||||
assert title as string == 'TOML Example'
|
||||
|
||||
owner := toml_doc.value('owner') as map[string]toml.Any
|
||||
any_name := owner.value('name') or { panic(err) }
|
||||
assert any_name.string() == 'Tom Preston-Werner'
|
||||
|
||||
database := toml_doc.value('database') as map[string]toml.Any
|
||||
db_serv := database['server'] or {
|
||||
panic('could not access "server" index in "database" variable')
|
||||
}
|
||||
assert db_serv as string == '192.168.1.1'
|
||||
|
||||
// TODO BUG depending on WHAT directory the tests is run from, this one assert sometimes fail?!?!
|
||||
// assert toml_doc.value('owner.name') as string == 'Tom Preston-Werner'
|
||||
assert toml_doc.value('owner.name') as string == 'Tom Preston-Werner'
|
||||
|
||||
assert toml_doc.value('database.server') as string == '192.168.1.1'
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// This tests the `toml` module for a known memory corruption.
|
||||
// The BUG shows below if no string `.clone()` nor any garbage-collection is done...
|
||||
import os
|
||||
import toml
|
||||
|
||||
const toml_text = os.read_file(os.real_path(os.join_path(os.dir(@FILE), 'testdata', 'toml_test')) +
|
||||
'.toml') or { panic(err) }
|
||||
|
||||
fn test_toml_known_memory_corruption() {
|
||||
toml_doc := toml.parse(toml_text) or { panic(err) }
|
||||
|
||||
owner := toml_doc.value('owner') as map[string]toml.Any
|
||||
any_name := owner.value('name') or { panic(err) }
|
||||
// This assert code path will cause the corruption.
|
||||
assert any_name.string() == 'Tom Preston-Werner'
|
||||
|
||||
// This code then triggered the bug before the fix.
|
||||
// Also see note in toml/any.v in function `pub fn (a Any) string() string`
|
||||
assert toml_doc.value('owner.name') as string == 'Tom Preston-Werner'
|
||||
|
||||
// Repeat the pattern
|
||||
assert any_name.string() == 'Tom Preston-Werner'
|
||||
assert toml_doc.value('owner.name') as string == 'Tom Preston-Werner'
|
||||
}
|
|
@ -24,18 +24,13 @@ fn test_toml() {
|
|||
assert title == toml.Any('TOML Example')
|
||||
assert title as string == 'TOML Example'
|
||||
|
||||
owner := toml_doc.value('owner') as map[string]toml.Any
|
||||
any_name := owner.value('name') or { panic(err) }
|
||||
assert any_name.string() == 'Tom Preston-Werner'
|
||||
|
||||
database := toml_doc.value('database') as map[string]toml.Any
|
||||
db_serv := database['server'] or {
|
||||
panic('could not access "server" index in "database" variable')
|
||||
}
|
||||
assert db_serv as string == '192.168.1.1'
|
||||
|
||||
// TODO BUG depending on WHAT directory the tests is run from, this one assert sometimes fail?!?!
|
||||
// assert toml_doc.value('owner.name') as string == 'Tom Preston-Werner'
|
||||
assert toml_doc.value('owner.name') as string == 'Tom Preston-Werner'
|
||||
|
||||
assert toml_doc.value('database.server') as string == '192.168.1.1'
|
||||
|
||||
|
|
|
@ -92,7 +92,6 @@ pub fn (d Doc) to_json() string {
|
|||
// value queries a value from the TOML document.
|
||||
pub fn (d Doc) value(key string) Any {
|
||||
values := d.ast.table as map[string]ast.Value
|
||||
// any_values := d.ast_to_any(values) as map[string]Any
|
||||
return d.get_map_value_as_any(values, key)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue