Skip to content

Commit

Permalink
checker: fix missing check for stack pointer return (fix #22726) (#22756
Browse files Browse the repository at this point in the history
)

* fix

* test

* fix
  • Loading branch information
felipensp authored Nov 5, 2024
1 parent 2f8b2c5 commit bd6005e
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 3 deletions.
9 changes: 6 additions & 3 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -5310,11 +5310,14 @@ fn (mut c Checker) fail_if_stack_struct_action_outside_unsafe(mut ident ast.Iden
}
if obj.is_stack_obj && !c.inside_unsafe {
sym := c.table.sym(obj.typ.set_nr_muls(0))
if !sym.is_heap() && !c.pref.translated && !c.file.is_translated {
suggestion := if sym.kind == .struct {
is_heap := sym.is_heap()
if (!is_heap || !obj.typ.is_ptr()) && !c.pref.translated && !c.file.is_translated {
suggestion := if !is_heap && sym.kind == .struct {
'declaring `${sym.name}` as `@[heap]`'
} else {
} else if !is_heap {
'wrapping the `${sym.name}` object in a `struct` declared as `@[heap]`'
} else { // e.g. var from `for a in heap_object {`
'declaring `${ident.name}` mutable'
}
c.error('`${ident.name}` cannot be ${failed_action} outside `unsafe` blocks as it might refer to an object stored on stack. Consider ${suggestion}.',
ident.pos)
Expand Down
5 changes: 5 additions & 0 deletions vlib/v/checker/return.v
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,11 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
mut r_expr := &node.exprs[expr_idxs[i]]
if mut r_expr is ast.Ident {
c.fail_if_stack_struct_action_outside_unsafe(mut r_expr, 'returned')
} else if mut r_expr is ast.PrefixExpr && r_expr.op == .amp {
// &var
if mut r_expr.right is ast.Ident {
c.fail_if_stack_struct_action_outside_unsafe(mut r_expr.right, 'returned')
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions vlib/v/checker/tests/return_stack_var_err.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
vlib/v/checker/tests/return_stack_var_err.vv:26:12: error: `s` cannot be returned outside `unsafe` blocks as it might refer to an object stored on stack. Consider declaring `s` mutable.
24 | for s in students {
25 | if s.name == 'Amy' {
26 | return &s
| ^
27 | }
28 | }
30 changes: 30 additions & 0 deletions vlib/v/checker/tests/return_stack_var_err.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module main

@[heap]
struct Student {
name string
age int
}

fn main() {
mut students := []Student{}
students << Student{
name: 'Mike'
age: 16
}
students << Student{
name: 'Amy'
age: 15
}

_ := get_amy(students) or { unsafe { nil } }
}

fn get_amy(students []Student) ?&Student {
for s in students {
if s.name == 'Amy' {
return &s
}
}
return none
}

0 comments on commit bd6005e

Please sign in to comment.