diff --git a/releasenotes.md b/releasenotes.md index a8011a854..c4baad27a 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -4,6 +4,7 @@ ### Changes / improvements - Removed support for LLVM 17, 18. +- Detect large temporaries when creating slices on the stack #2665 ### Stdlib changes - Add contract on `any_to_enum_ordinal` and `any_to_int` to improve error when passed an empty any. #2977 diff --git a/src/compiler/sema_initializers.c b/src/compiler/sema_initializers.c index 272e90504..8d48940ac 100644 --- a/src/compiler/sema_initializers.c +++ b/src/compiler/sema_initializers.c @@ -843,7 +843,6 @@ ConstInitializer *sema_merge_bitstruct_const_initializers(ConstInitializer *lhs, bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *expr, bool *no_match_ref) { - if (!to) to = type_untypedlist; ASSERT(to); Type *flattened = type_flatten(to); @@ -881,6 +880,16 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex // Resolve this as an inferred array. Type *type = type_get_inferred_array(flattened->array.base); if (!sema_expr_analyse_initializer(context, type, type, expr, no_match_ref)) return false; + if (context->call_env.kind == CALL_ENV_FUNCTION && type_size(expr->type) > compiler.build.max_stack_object_size * 1024) + { + size_t size = type_size(expr->type); + RETURN_SEMA_ERROR( + expr, "The size of this stack allocated expression (%s%d Kb) exceeds the maximum allowed stack object size (%d Kb), " + "you can increase this limit with --max-stack-object-size, but be aware that too large objects " + "allocated on the stack may lead to the stack running out of memory.", size % 1024 == 0 ? "" : "over ", + size / 1024, + compiler.build.max_stack_object_size); + } if (expr_is_const_initializer(expr)) { ConstInitializer *init = expr->const_expr.initializer; @@ -931,6 +940,7 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex NO_MATCH: *no_match_ref = true; return false; + } void const_init_rewrite_to_value(ConstInitializer *const_init, Expr *value) diff --git a/test/test_suite/slices/huge_temp_slice.c3 b/test/test_suite/slices/huge_temp_slice.c3 new file mode 100644 index 000000000..4468c0a73 --- /dev/null +++ b/test/test_suite/slices/huge_temp_slice.c3 @@ -0,0 +1,10 @@ +module main; + +char[] one_mb2 = { [0..(1024*1024)-1] = 0xA5 }; +fn int main() +{ + char[] one_mb; + one_mb = { [0..(1024*1024)-1] = 0xA5 }; // #error: The size of this stack allocated expression + one_mb2 = { [0..(1024*1024)-1] = 0xA5 }; // #error: The size of this stack allocated expression + return 0; +} \ No newline at end of file