From e51f0be6db5807b4e4ea03634d05c824c3fb7ab5 Mon Sep 17 00:00:00 2001 From: yuyi Date: Tue, 13 Sep 2022 15:04:21 +0800 Subject: [PATCH] checker: check taking the address of map field outside unsafe block (#15737) --- vlib/toml/parser/parser.v | 4 ++- vlib/v/checker/checker.v | 6 +++++ .../tests/struct_field_map_address_err.out | 7 +++++ .../tests/struct_field_map_address_err.vv | 27 +++++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 vlib/v/checker/tests/struct_field_map_address_err.out create mode 100644 vlib/v/checker/tests/struct_field_map_address_err.vv diff --git a/vlib/toml/parser/parser.v b/vlib/toml/parser/parser.v index 38c95f9b3d..8bd8f0af8b 100644 --- a/vlib/toml/parser/parser.v +++ b/vlib/toml/parser/parser.v @@ -561,7 +561,9 @@ pub fn (mut p Parser) root_table() ? { if p.tok.kind == .lsbr { // Parse `[[table]]` - p.array_of_tables(mut &p.root_map)? + unsafe { + p.array_of_tables(mut &p.root_map)? + } p.skip_next = true // skip calling p.next() in coming iteration util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'leaving double bracket at "$p.tok.kind" "$p.tok.lit". NEXT is "$p.peek_tok.kind "$p.peek_tok.lit"') } else if peek_tok.kind == .period { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4ecf8388c1..6acd3fb63f 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3328,6 +3328,12 @@ pub fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) ast.Type { c.warn('cannot take an address of const outside `unsafe`', node.right.pos) } } + if node.right is ast.SelectorExpr { + typ_sym := c.table.sym(right_type) + if typ_sym.kind == .map && !c.inside_unsafe { + c.error('cannot take the address of map values outside `unsafe`', node.pos) + } + } if mut node.right is ast.IndexExpr { typ_sym := c.table.sym(node.right.left_type) mut is_mut := false diff --git a/vlib/v/checker/tests/struct_field_map_address_err.out b/vlib/v/checker/tests/struct_field_map_address_err.out new file mode 100644 index 0000000000..44047f2119 --- /dev/null +++ b/vlib/v/checker/tests/struct_field_map_address_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/struct_field_map_address_err.vv:12:26: error: cannot take the address of map values outside `unsafe` + 10 | mut s := &StructWithMap{} + 11 | s.m['abc'] = StructWithMap{'abc', {}} + 12 | pointer_to_map_value := &s.m['abc'].m['xyz'].m + | ^ + 13 | dump(ptr_str(pointer_to_map_value)) + 14 | return s, pointer_to_map_value diff --git a/vlib/v/checker/tests/struct_field_map_address_err.vv b/vlib/v/checker/tests/struct_field_map_address_err.vv new file mode 100644 index 0000000000..7756931539 --- /dev/null +++ b/vlib/v/checker/tests/struct_field_map_address_err.vv @@ -0,0 +1,27 @@ +import os + +struct StructWithMap { +mut: + name string + m map[string]StructWithMap +} + +fn abc() (&StructWithMap, &map[string]StructWithMap) { + mut s := &StructWithMap{} + s.m['abc'] = StructWithMap{'abc', {}} + pointer_to_map_value := &s.m['abc'].m['xyz'].m + dump(ptr_str(pointer_to_map_value)) + return s, pointer_to_map_value +} + +fn main() { + mut s, p := abc() + n := os.args[1] or { '2' }.int() + dump(n) + for i in 0 .. n { + s.m['$i'] = StructWithMap{} + } + dump(s.m['abc']) + dump(p) + eprintln('-----------------------------------------------------') +}