From 63557d0d0237ad00f5d65e7f5a748d2b0652058f Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Mon, 7 Dec 2020 20:43:38 +0000 Subject: [PATCH] checker: disallow op= and infix on a voidptr (#7175) --- .github/workflows/ci.yml | 4 +-- cmd/tools/bench/wyhash.v | 2 +- vlib/term/ui/input_nix.c.v | 2 +- vlib/term/ui/termios_nix.c.v | 2 +- vlib/v/checker/checker.v | 14 ++++++---- vlib/v/checker/tests/pointer_ops.out | 42 ++++++++++++++++++++++++++++ vlib/v/checker/tests/pointer_ops.vv | 12 ++++++++ 7 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 vlib/v/checker/tests/pointer_ops.out create mode 100644 vlib/v/checker/tests/pointer_ops.vv diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac7bcb0eb3..03a907b42e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -167,7 +167,7 @@ jobs: - name: Fixed tests run: VJOBS=1 ./v -silent test-fixed - name: Build examples - run: ./v -silent build-examples + run: ./v build-examples - name: Build examples with -autofree run: | ./v -autofree -o tetris examples/tetris/tetris.v @@ -231,7 +231,7 @@ jobs: - name: Fixed tests (-prod) run: ./v -o vprod -prod cmd/v && ./vprod -silent test-fixed - name: Build examples - run: ./v -silent build-examples + run: ./v build-examples - name: Build examples with -autofree run: | ./v -autofree -experimental -o tetris examples/tetris/tetris.v diff --git a/cmd/tools/bench/wyhash.v b/cmd/tools/bench/wyhash.v index d4ee8ac394..5bdbcdd7c0 100644 --- a/cmd/tools/bench/wyhash.v +++ b/cmd/tools/bench/wyhash.v @@ -30,7 +30,7 @@ fn main() { checksum = 0 for len in str_lens { end_pos := start_pos + len - checksum ^= wyhash.wyhash_c(unsafe { bytepile.data + start_pos }, u64(len), 1) + checksum ^= wyhash.wyhash_c(unsafe { byteptr(bytepile.data) + start_pos }, u64(len), 1) start_pos = end_pos } bhashing_1.measure('wyhash.wyhash_c | checksum: ${checksum:22}') diff --git a/vlib/term/ui/input_nix.c.v b/vlib/term/ui/input_nix.c.v index 5559acd86d..363a1920f8 100644 --- a/vlib/term/ui/input_nix.c.v +++ b/vlib/term/ui/input_nix.c.v @@ -46,7 +46,7 @@ pub fn (mut ctx Context) run() ? { // TODO: remove fn (mut ctx Context) shift(len int) { unsafe { - C.memmove(ctx.read_buf.data, ctx.read_buf.data + len, ctx.read_buf.cap - len) + C.memmove(ctx.read_buf.data, byteptr(ctx.read_buf.data) + len, ctx.read_buf.cap - len) ctx.resize_arr(ctx.read_buf.len - len) } } diff --git a/vlib/term/ui/termios_nix.c.v b/vlib/term/ui/termios_nix.c.v index cc12f21131..226876d737 100644 --- a/vlib/term/ui/termios_nix.c.v +++ b/vlib/term/ui/termios_nix.c.v @@ -221,7 +221,7 @@ fn (mut ctx Context) termios_loop() { sw.restart() if ctx.cfg.event_fn != voidptr(0) { unsafe { - len := C.read(C.STDIN_FILENO, ctx.read_buf.data + ctx.read_buf.len, ctx.read_buf.cap - ctx.read_buf.len) + len := C.read(C.STDIN_FILENO, byteptr(ctx.read_buf.data) + ctx.read_buf.len, ctx.read_buf.cap - ctx.read_buf.len) ctx.resize_arr(ctx.read_buf.len + len) } if ctx.read_buf.len > 0 { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index c7bcdaca96..d99b586967 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -627,9 +627,13 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { mut left := c.table.get_type_symbol(left_type) left_pos := infix_expr.left.position() right_pos := infix_expr.right.position() - if (left_type.is_ptr() || left.is_pointer()) && - infix_expr.op in [.plus, .minus] && !c.inside_unsafe { - c.warn('pointer arithmetic is only allowed in `unsafe` blocks', left_pos) + if (left_type.is_ptr() || left.is_pointer()) && infix_expr.op in [.plus, .minus] { + if !c.inside_unsafe { + c.warn('pointer arithmetic is only allowed in `unsafe` blocks', left_pos) + } + if left_type == table.voidptr_type { + c.error('`$infix_expr.op` cannot be used with `voidptr`', left_pos) + } } mut return_type := left_type if infix_expr.op != .key_is { @@ -2228,10 +2232,10 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { c.error('invalid right operand: $left_sym.name $assign_stmt.op $right_sym.name', right.position()) } - } else if !left_sym.is_number() && !left_sym.is_pointer() { + } else if !left_sym.is_number() && left_sym.kind !in [.byteptr, .charptr] { c.error('operator `$assign_stmt.op` not defined on left operand type `$left_sym.name`', left.position()) - } else if !right_sym.is_number() && !right_sym.is_pointer() { + } else if !right_sym.is_number() && left_sym.kind !in [.byteptr, .charptr] { c.error('invalid right operand: $left_sym.name $assign_stmt.op $right_sym.name', right.position()) } else if right is ast.IntegerLiteral { diff --git a/vlib/v/checker/tests/pointer_ops.out b/vlib/v/checker/tests/pointer_ops.out new file mode 100644 index 0000000000..b896053605 --- /dev/null +++ b/vlib/v/checker/tests/pointer_ops.out @@ -0,0 +1,42 @@ +vlib/v/checker/tests/pointer_ops.vv:5:7: error: `+` cannot be used with `voidptr` + 3 | unsafe { + 4 | mut p := voidptr(0) + 5 | _ = p + 1 + | ^ + 6 | p++ + 7 | p += 3 +vlib/v/checker/tests/pointer_ops.vv:6:4: error: invalid operation: ++ (non-numeric type `voidptr`) + 4 | mut p := voidptr(0) + 5 | _ = p + 1 + 6 | p++ + | ~~ + 7 | p += 3 + 8 | _ = p - 1 +vlib/v/checker/tests/pointer_ops.vv:7:3: error: operator `+=` not defined on left operand type `voidptr` + 5 | _ = p + 1 + 6 | p++ + 7 | p += 3 + | ^ + 8 | _ = p - 1 + 9 | p-- +vlib/v/checker/tests/pointer_ops.vv:8:7: error: `-` cannot be used with `voidptr` + 6 | p++ + 7 | p += 3 + 8 | _ = p - 1 + | ^ + 9 | p-- + 10 | p -= 3 +vlib/v/checker/tests/pointer_ops.vv:9:4: error: invalid operation: -- (non-numeric type `voidptr`) + 7 | p += 3 + 8 | _ = p - 1 + 9 | p-- + | ~~ + 10 | p -= 3 + 11 | } +vlib/v/checker/tests/pointer_ops.vv:10:3: error: operator `-=` not defined on left operand type `voidptr` + 8 | _ = p - 1 + 9 | p-- + 10 | p -= 3 + | ^ + 11 | } + 12 | } diff --git a/vlib/v/checker/tests/pointer_ops.vv b/vlib/v/checker/tests/pointer_ops.vv new file mode 100644 index 0000000000..238e3e32c3 --- /dev/null +++ b/vlib/v/checker/tests/pointer_ops.vv @@ -0,0 +1,12 @@ +// void* arithmetic is not allowed in MSVC, so ban it +fn test_voidptr() { + unsafe { + mut p := voidptr(0) + _ = p + 1 + p++ + p += 3 + _ = p - 1 + p-- + p -= 3 + } +}