From 990e9685d295883a2d3450990abe01c98f2f8f0f Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 16 Feb 2026 00:39:14 +0100 Subject: [PATCH] - Adding the incorrect sized vector to a pointer vector would cause a crash. --- releasenotes.md | 1 + src/compiler/llvm_codegen_internal.h | 2 +- src/compiler/llvm_codegen_internal_impl.h | 2 +- src/compiler/llvm_codegen_stmt.c | 7 +++---- src/compiler/sema_casts.c | 16 +--------------- src/compiler/sema_decls.c | 2 +- src/compiler/sema_expr.c | 8 ++------ .../vector/vector_pointer_not_same_size.c3 | 8 ++++++++ 8 files changed, 18 insertions(+), 28 deletions(-) create mode 100644 test/test_suite/vector/vector_pointer_not_same_size.c3 diff --git a/releasenotes.md b/releasenotes.md index e783b45b5..0f7bf88d6 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -43,6 +43,7 @@ - Fix std::io::Formatter integer issue for large uint128 decimal values. - `--safe=no` disabled compile-time errors on compile-time known runtime @require checks #2936 - On assert known false, the message was not show for no-args. +- Adding the incorrect sized vector to a pointer vector would cause a crash. ## 0.7.9 Change list diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 8d51c6601..6f973323d 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -539,7 +539,7 @@ void llvm_emit_panic_on_true(GenContext *c, LLVMValueRef value, const char *pani const char *fmt, BEValue *value_1, BEValue *value_2); void llvm_emit_panic_if_true(GenContext *c, BEValue *value, const char *panic_name, SourceSpan loc, const char *fmt, BEValue *value_1, BEValue *value_2); -void llvm_emit_panic(GenContext *c, const char *message, SourceSpan loc, const char *fmt, BEValue *args); +void llvm_emit_panic(GenContext *c, const char *message, SourceSpan loc, const char *fmt, BEValue *varargs); void llvm_emit_unreachable(GenContext *c); void llvm_emit_assume_true(GenContext *c, BEValue *assume_true); LLVMValueRef llvm_emit_expect_raw(GenContext *c, LLVMValueRef expect_true); diff --git a/src/compiler/llvm_codegen_internal_impl.h b/src/compiler/llvm_codegen_internal_impl.h index b68520596..d7484b423 100644 --- a/src/compiler/llvm_codegen_internal_impl.h +++ b/src/compiler/llvm_codegen_internal_impl.h @@ -1,5 +1,5 @@ -INLINE LLVMValueRef llvm_emit_insert_value(GenContext *c, LLVMValueRef agg, LLVMValueRef new_value, ArraySize index) +INLINE LLVMValueRef llvm_emit_insert_value(GenContext *c, LLVMValueRef agg, LLVMValueRef new_value, ArraySize index) // NOLINT { if (LLVMGetTypeKind(LLVMTypeOf(agg)) == LLVMVectorTypeKind) { diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index 97c973034..e796e6dd0 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -1022,13 +1022,12 @@ static void llvm_emit_switch_body(GenContext *c, BEValue *switch_value, Ast *swi LLVMBasicBlockRef block = case_stmt->case_stmt.backend_block; if (case_stmt != default_case) { - LLVMValueRef case_value; BEValue be_value; Expr *from = exprptr(case_stmt->case_stmt.expr); ASSERT(expr_is_const(from)); llvm_emit_expr(c, &be_value, from); llvm_value_rvalue(c, &be_value); - case_value = be_value.value; + LLVMValueRef case_value = be_value.value; LLVMAddCase(switch_stmt, case_value, block); Expr *to_expr = exprptrzero(case_stmt->case_stmt.to_expr); if (to_expr) @@ -1495,9 +1494,9 @@ LLVMValueRef llvm_emit_zstring_named(GenContext *c, const char *str, const char { FOREACH(ReusableConstant, constant, c->reusable_constants) { - if (str_eq(str, constant.string) && str_eq(extname, constant.name)) + if (str_eq(str, constant.string) && str_eq(extname, constant.name)) // NOLINT { - return constant.value; + return constant.value; // NOLINT } } diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index cd1065632..3980c3bcd 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -1656,21 +1656,7 @@ static bool rule_enum_to_value(CastContext *cc, bool is_explicit, bool is_silent return cast_is_allowed(cc, is_explicit, is_silent); } - // First handle const enums, they behave much like distinct types - if (enum_decl->decl_kind == DECL_CONST_ENUM) - { - if (!is_explicit || !enum_decl->is_substruct) - { - return sema_cast_error(cc, false, is_silent); - } - // Use the inner type. - Type *inner = enum_decl->enums.type_info->type; - if (is_explicit) - { - return rule_from_explicit_flattened(cc, is_silent); - } - return cast_is_allowed(cc, is_explicit, is_silent); - } + ASSERT(enum_decl->decl_kind != DECL_CONST_ENUM); Type *inner = enum_decl->enums.type_info->type; if (!type_is_integer_or_bool_kind(type_flatten(cc->to))) diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 96085110f..2cf62f02c 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -5297,7 +5297,7 @@ FOUND:; copy_begin(); contracts = astid(copy_ast_macro(astptr(contracts))); copy_end(); - SourceSpan param_span = extend_span_with_token(params[0]->span, VECLAST(params)->span); + SourceSpan param_span = extend_span_with_token(params[0]->span, VECLAST(params)->span); // NOLINT if (!sema_analyse_generic_module_contracts(context, module, instance, contracts, param_span, invocation_span)) { decl_poison(instance); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index b554ad5e0..62ab4f8cc 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -8022,7 +8022,6 @@ INLINE bool sema_expr_analyse_ptr_add(SemaContext *context, Expr *expr, Expr *le { bool left_is_vec = type_kind_is_real_vector(left_type->type_kind); bool right_is_vec = type_kind_is_real_vector(right_type->type_kind); - ArraySize vec_len = left_is_vec ? left_type->array.len : 0; // 3a. Check that the other side is an integer of some sort. if (!type_is_integer(right_type)) @@ -8038,11 +8037,8 @@ INLINE bool sema_expr_analyse_ptr_add(SemaContext *context, Expr *expr, Expr *le // 3b. Cast it to usz or isz depending on underlying type. // Either is fine, but it looks a bit nicer if we actually do this and keep the sign. - bool success = cast_explicit(context, right, left_is_vec ? type_get_vector_from_vector(type_isz, left_type) : type_isz); - - // No need to check the cast we just ensured it was an integer. - ASSERT_SPAN(expr, success && "This should always work"); - (void) success; + // This may fail if vectors are not the same size. + if (!cast_explicit(context, right, left_is_vec ? type_get_vector_from_vector(type_isz, left_type) : type_isz)) return false; // Folding offset. if (left->expr_kind == EXPR_POINTER_OFFSET) diff --git a/test/test_suite/vector/vector_pointer_not_same_size.c3 b/test/test_suite/vector/vector_pointer_not_same_size.c3 new file mode 100644 index 000000000..df0e89fee --- /dev/null +++ b/test/test_suite/vector/vector_pointer_not_same_size.c3 @@ -0,0 +1,8 @@ +int a; + +fn void main() +{ + void*[<2>] x = { &a, &a }; + int[<1>] y = { 1 }; + x + y; // #error: It is not possible to cast 'int[<1>]' to 'isz[<2>]' (long[<2>]) +}