From 1c7df29bedebe72edd43e2ffc84dad91b98eb58b Mon Sep 17 00:00:00 2001 From: Swastik Baranwal Date: Wed, 12 Jul 2023 13:37:34 +0530 Subject: [PATCH] checker: disallow voidptr cast to struct (#18845) --- vlib/term/ui/README.md | 2 +- vlib/v/checker/checker.v | 6 +++--- vlib/v/checker/tests/voidptr_cast_to_struct_err.out | 7 +++++++ vlib/v/checker/tests/voidptr_cast_to_struct_err.vv | 6 ++++++ vlib/v/tests/option_generic_ptr_return_test.v | 2 +- vlib/v/tests/option_ptr_cast_test.v | 2 +- vlib/v/tests/pointers_multilevel_casts_test.v | 4 ++-- 7 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 vlib/v/checker/tests/voidptr_cast_to_struct_err.out create mode 100644 vlib/v/checker/tests/voidptr_cast_to_struct_err.vv diff --git a/vlib/term/ui/README.md b/vlib/term/ui/README.md index b72dfd6ab1..cb7d9709bc 100644 --- a/vlib/term/ui/README.md +++ b/vlib/term/ui/README.md @@ -19,7 +19,7 @@ fn event(e &tui.Event, x voidptr) { } fn frame(x voidptr) { - mut app := &App(x) + mut app := unsafe { &App(x) } app.tui.clear() app.tui.set_bg_color(r: 63, g: 81, b: 181) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 885a9d5975..a38a9b86c3 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2943,9 +2943,9 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { else {} } } - if from_type == ast.voidptr_type_idx && !c.inside_unsafe { - // TODO make this an error - c.warn('cannot cast voidptr to a struct outside `unsafe`', node.pos) + if from_type == ast.voidptr_type_idx && !c.inside_unsafe && !c.pref.translated + && !c.file.is_translated { + c.error('cannot cast voidptr to a struct outside `unsafe`', node.pos) } if !from_type.is_int() && final_from_sym.kind != .enum_ && !from_type.is_any_kind_of_pointer() { diff --git a/vlib/v/checker/tests/voidptr_cast_to_struct_err.out b/vlib/v/checker/tests/voidptr_cast_to_struct_err.out new file mode 100644 index 0000000000..22e8c872cf --- /dev/null +++ b/vlib/v/checker/tests/voidptr_cast_to_struct_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/voidptr_cast_to_struct_err.vv:4:7: error: cannot cast `voidptr` to struct + 2 | + 3 | fn main() { + 4 | a := Foo(unsafe { nil }) + | ~~~~~~~~~~~~~~~~~~~ + 5 | println(a) + 6 | } diff --git a/vlib/v/checker/tests/voidptr_cast_to_struct_err.vv b/vlib/v/checker/tests/voidptr_cast_to_struct_err.vv new file mode 100644 index 0000000000..5f3aee8fec --- /dev/null +++ b/vlib/v/checker/tests/voidptr_cast_to_struct_err.vv @@ -0,0 +1,6 @@ +struct Foo {} + +fn main() { + a := Foo(unsafe { nil }) + println(a) +} diff --git a/vlib/v/tests/option_generic_ptr_return_test.v b/vlib/v/tests/option_generic_ptr_return_test.v index c3e5f0699f..e66250de29 100644 --- a/vlib/v/tests/option_generic_ptr_return_test.v +++ b/vlib/v/tests/option_generic_ptr_return_test.v @@ -8,7 +8,7 @@ struct ABCD {} pub fn cast_object_desc[H](desc &ObjectDesc) ?H { $if H is &ABCD { if desc.typ == 12 { // desc == ABCD - return &ABCD(desc.ptr) + return unsafe { &ABCD(desc.ptr) } } } return none diff --git a/vlib/v/tests/option_ptr_cast_test.v b/vlib/v/tests/option_ptr_cast_test.v index 60a04076c3..d125982908 100644 --- a/vlib/v/tests/option_ptr_cast_test.v +++ b/vlib/v/tests/option_ptr_cast_test.v @@ -14,7 +14,7 @@ pub fn cast_object_desc[H](desc &ObjectDesc) ?H { return &ABCD(desc.ptr) }*/ if desc.typ == 12 { // desc == ABCD - return ?&ABCD(&ABCD(desc.ptr)) + return ?&ABCD(unsafe { &ABCD(desc.ptr) }) } } return none diff --git a/vlib/v/tests/pointers_multilevel_casts_test.v b/vlib/v/tests/pointers_multilevel_casts_test.v index e705f944ae..26c8ea66c1 100644 --- a/vlib/v/tests/pointers_multilevel_casts_test.v +++ b/vlib/v/tests/pointers_multilevel_casts_test.v @@ -49,10 +49,10 @@ fn test_struct_pointer_casts_with_field_selectors() { } dump(ss) pss := voidptr(ss) - if &Struct(pss).name == 'abc' { + if unsafe { &Struct(pss).name } == 'abc' { assert true } - if &Struct(pss).x == 123 { + if unsafe { &Struct(pss).x } == 123 { // &Struct cast and selecting .x assert true }