From 4fc5e83771c1e232bfcf9a133373a89f4dce3bf8 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 20 Dec 2020 07:55:23 +0100 Subject: [PATCH] checker: never allow taking the address of map values --- vlib/v/checker/checker.v | 125 +++++++++--------- .../tests/mut_map_get_value_address_err.out | 14 +- 2 files changed, 71 insertions(+), 68 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 317eb09c40..ca81b272f1 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3003,67 +3003,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { return c.postfix_expr(mut node) } ast.PrefixExpr { - right_type := c.expr(node.right) - node.right_type = right_type - // TODO: testing ref/deref strategy - if node.op == .amp && !right_type.is_ptr() { - if node.right is ast.IntegerLiteral { - c.error('cannot take the address of an int', node.pos) - } - if node.right is ast.StringLiteral || node.right is ast.StringInterLiteral { - c.error('cannot take the address of a string', node.pos) - } - if mut node.right is ast.IndexExpr { - typ_sym := c.table.get_type_symbol(node.right.left_type) - mut is_mut := false - if mut node.right.left is ast.Ident { - ident := node.right.left - // TODO: temporary, remove this - ident_obj := ident.obj - if ident_obj is ast.Var { - is_mut = ident_obj.is_mut - } - } - if !c.inside_unsafe && is_mut { - if typ_sym.kind == .map { - c.error('cannot take the address of mutable map values outside unsafe blocks', - node.right.pos) - } - if typ_sym.kind == .array { - c.error('cannot take the address of mutable array elements outside unsafe blocks', - node.right.pos) - } - } - } - return right_type.to_ptr() - } else if node.op == .amp && node.right !is ast.CastExpr { - return right_type.to_ptr() - } - if node.op == .mul { - if right_type.is_ptr() { - return right_type.deref() - } - if !right_type.is_pointer() { - s := c.table.type_to_str(right_type) - c.error('invalid indirect of `$s`', node.pos) - } - } - if node.op == .bit_not && !right_type.is_int() && !c.pref.translated { - c.error('operator ~ only defined on int types', node.pos) - } - if node.op == .not && right_type != table.bool_type_idx && !c.pref.translated { - c.error('! operator can only be used with bool types', node.pos) - } - if node.op == .arrow { - right := c.table.get_type_symbol(right_type) - if right.kind == .chan { - c.stmts(node.or_block.stmts) - return right.chan_info().elem_type - } else { - c.error('<- operator can only be used with `chan` types', node.pos) - } - } - return right_type + return c.prefix_expr(mut node) } ast.None { return table.none_type @@ -4295,6 +4235,69 @@ pub fn (mut c Checker) postfix_expr(mut node ast.PostfixExpr) table.Type { return typ } +pub fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) table.Type { + right_type := c.expr(node.right) + node.right_type = right_type + // TODO: testing ref/deref strategy + if node.op == .amp && !right_type.is_ptr() { + if node.right is ast.IntegerLiteral { + c.error('cannot take the address of an int', node.pos) + } + if node.right is ast.StringLiteral || node.right is ast.StringInterLiteral { + c.error('cannot take the address of a string', node.pos) + } + if mut node.right is ast.IndexExpr { + typ_sym := c.table.get_type_symbol(node.right.left_type) + mut is_mut := false + if mut node.right.left is ast.Ident { + ident := node.right.left + // TODO: temporary, remove this + ident_obj := ident.obj + if ident_obj is ast.Var { + is_mut = ident_obj.is_mut + } + } + if typ_sym.kind == .map { + c.error('cannot take the address of map values', node.right.pos) + } + if !c.inside_unsafe { + if typ_sym.kind == .array && is_mut { + c.error('cannot take the address of mutable array elements outside unsafe blocks', + node.right.pos) + } + } + } + return right_type.to_ptr() + } else if node.op == .amp && node.right !is ast.CastExpr { + return right_type.to_ptr() + } + if node.op == .mul { + if right_type.is_ptr() { + return right_type.deref() + } + if !right_type.is_pointer() { + s := c.table.type_to_str(right_type) + c.error('invalid indirect of `$s`', node.pos) + } + } + if node.op == .bit_not && !right_type.is_int() && !c.pref.translated { + c.error('operator ~ only defined on int types', node.pos) + } + if node.op == .not && right_type != table.bool_type_idx && !c.pref.translated { + c.error('! operator can only be used with bool types', node.pos) + } + if node.op == .arrow { + right := c.table.get_type_symbol(right_type) + if right.kind == .chan { + c.stmts(node.or_block.stmts) + return right.chan_info().elem_type + } else { + c.error('<- operator can only be used with `chan` types', node.pos) + } + } + return right_type +} + fn (mut c Checker) check_index_type(typ_sym &table.TypeSymbol, index_type table.Type, pos token.Position) { index_type_sym := c.table.get_type_symbol(index_type) // println('index expr left=$typ_sym.name $node.pos.line_nr') diff --git a/vlib/v/checker/tests/mut_map_get_value_address_err.out b/vlib/v/checker/tests/mut_map_get_value_address_err.out index d33844e164..0a8983ffa9 100644 --- a/vlib/v/checker/tests/mut_map_get_value_address_err.out +++ b/vlib/v/checker/tests/mut_map_get_value_address_err.out @@ -1,7 +1,7 @@ -vlib/v/checker/tests/mut_map_get_value_address_err.vv:3:12: error: cannot take the address of mutable map values outside unsafe blocks - 1 | fn main() { - 2 | mut m := {'key' : 3} - 3 | a := &m['key'] - | ~~~~~~~ - 4 | println(a) - 5 | } +vlib/v/checker/tests/mut_map_get_value_address_err.vv:3:12: error: cannot take the address of map values + 1 | fn main() { + 2 | mut m := {'key' : 3} + 3 | a := &m['key'] + | ~~~~~~~ + 4 | println(a) + 5 | }