From a46f73ad241b16c6f12aede281e461a452cd53b3 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 3 Jul 2025 23:53:01 +0200 Subject: [PATCH] Const slice indexing was not bounds checked. --- releasenotes.md | 1 + src/compiler/sema_const.c | 12 +---------- src/compiler/sema_expr.c | 21 ++++++++++--------- .../defined_const_slice_out_of_range.c3 | 6 ++++++ 4 files changed, 19 insertions(+), 21 deletions(-) create mode 100644 test/test_suite/slices/defined_const_slice_out_of_range.c3 diff --git a/releasenotes.md b/releasenotes.md index b9650a0bc..d4e5e84a8 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -22,6 +22,7 @@ - `$for` ct-state not properly popped. - Inline `r / complex` for complex numbers fixed. - Const slice lengths were not always detected as constant. +- Const slice indexing was not bounds checked. ### Stdlib changes diff --git a/src/compiler/sema_const.c b/src/compiler/sema_const.c index d7e0186bf..3ed085605 100644 --- a/src/compiler/sema_const.c +++ b/src/compiler/sema_const.c @@ -12,17 +12,7 @@ ArrayIndex sema_len_from_const(Expr *expr) // We also handle the case where we have a cast from a const array. if (!sema_cast_const(expr)) { - Type *flat = type_flatten(expr->type); - switch (flat->type_kind) - { - case TYPE_ARRAY: - case TYPE_VECTOR: - return flat->array.len; - case TYPE_SLICE: - break; - default: - return -1; - } + if (type_flatten(expr->type)->type_kind != TYPE_SLICE) return -1; if (expr->expr_kind == EXPR_SLICE) { return range_const_len(&expr->slice_expr.range); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index f06f93a24..d770275ef 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -3887,24 +3887,25 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr, RETURN_SEMA_ERROR(index, "Index is out of range."); } ArraySize idx = index->const_expr.ixx.i.low; + ArrayIndex len = sema_len_from_const(current_expr); + if (idx > len || (idx == len && !start_from_end) || (idx == 0 && start_from_end)) + { + if (check_valid) goto VALID_FAIL_POISON; + RETURN_SEMA_ERROR(index, "The index (%s%llu) is out of range, the length is just %llu.", + start_from_end ? "^" : "", + (unsigned long long)idx, + (unsigned long long)len); + } if (!is_const_initializer) { // Handle bytes / String - ArraySize len = current_expr->const_expr.bytes.len; - if (idx > len || (idx == len && !start_from_end) || (idx == 0 && start_from_end)) - { - if (check_valid) goto VALID_FAIL_POISON; - RETURN_SEMA_ERROR(index, "The index (%s%llu) is out of range, the length is just %llu.", - start_from_end ? "^" : "", - (unsigned long long)idx, - (unsigned long long)current_expr->const_expr.bytes.len); - } if (start_from_end) idx = len - idx; unsigned char c = current_expr->const_expr.bytes.ptr[idx]; expr_rewrite_const_int(expr, type_char, c); expr->type = type_char; return true; } + if (sema_subscript_rewrite_index_const_list(current_expr, idx, start_from_end, expr)) return true; } } @@ -5889,7 +5890,7 @@ CHECK_DEEPER: // 9. Fix hard coded function `len` on slices and arrays if (kw == kw_len) { - ArrayIndex index = sema_len_from_const(current_parent); + ArrayIndex index = sema_len_from_expr(current_parent); if (index > -1) { expr_rewrite_const_int(expr, type_isz, index); diff --git a/test/test_suite/slices/defined_const_slice_out_of_range.c3 b/test/test_suite/slices/defined_const_slice_out_of_range.c3 new file mode 100644 index 000000000..bb7675cf7 --- /dev/null +++ b/test/test_suite/slices/defined_const_slice_out_of_range.c3 @@ -0,0 +1,6 @@ +fn int main() +{ + const char[] ARR = { 1, 2, 3, 4, 5 }; + $echo $defined(ARR[5]); + return 0; +} \ No newline at end of file