From 5cf51fbfdd8d5b82635e3e39cc29951a84cc0612 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 26 Mar 2026 00:03:51 +0300 Subject: [PATCH] cgen: fix possible memory allocation issue (fixes #26758) --- vlib/v/gen/c/cgen.v | 25 ++++++++++++++ vlib/v/tests/builtin_arrays/array_cast_test.v | 34 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index fcd367766..d1990e6a2 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -6110,6 +6110,9 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { } } } else { + if g.write_array_data_ptr_cast(node, node_typ) { + return + } styp := g.styp(node_typ) if (g.pref.translated || g.file.is_translated) && sym.kind == .function { // TODO: handle the type in fn casts, not just exprs @@ -6201,6 +6204,28 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { } } +fn (mut g Gen) write_array_data_ptr_cast(node ast.CastExpr, node_typ ast.Type) bool { + if !node_typ.is_ptr() || node_typ.is_voidptr() || node.expr !is ast.PrefixExpr { + return false + } + prefix := node.expr as ast.PrefixExpr + if prefix.op != .amp { + return false + } + final_node_sym := g.table.final_sym(node_typ) + if final_node_sym.kind == .array || node_typ.deref().idx() == ast.array_type_idx + || final_node_sym.name == 'array' { + return false + } + if g.table.final_sym(prefix.right_type).kind != .array { + return false + } + g.write('(${g.styp(node_typ)})((') + g.expr(prefix.right) + g.write(').data)') + return true +} + fn (mut g Gen) concat_expr(node ast.ConcatExpr) { mut typ := node.return_type.clear_option_and_result() if g.inside_return { diff --git a/vlib/v/tests/builtin_arrays/array_cast_test.v b/vlib/v/tests/builtin_arrays/array_cast_test.v index 072e6a532..6d4596069 100644 --- a/vlib/v/tests/builtin_arrays/array_cast_test.v +++ b/vlib/v/tests/builtin_arrays/array_cast_test.v @@ -17,3 +17,37 @@ fn test_int() { assert *p == arr } } + +fn test_ref_array_cast_to_elem_ptr_uses_array_data() { + mut buf := []u8{len: 4} + p := unsafe { &u8(&buf) } + unsafe { + p[0] = `A` + p[1] = `B` + } + assert buf[0] == `A` + assert buf[1] == `B` +} + +struct Header { +mut: + first u8 + second u8 +} + +fn test_ref_array_cast_to_struct_ptr_uses_array_data() { + mut buf := []u8{len: int(sizeof(Header))} + header := unsafe { &Header(&buf) } + unsafe { + header.first = `x` + header.second = `y` + } + assert buf[0] == `x` + assert buf[1] == `y` +} + +fn test_ref_array_cast_to_array_header_keeps_header_address() { + mut arr := [1, 2] + header := unsafe { &array(&arr) } + assert unsafe { header.len } == 2 +} -- 2.39.5