From 0ea815db498d52ffd654801cc68bb95f4fdb437e Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sat, 22 Apr 2017 09:40:32 +0100 Subject: [PATCH] Fix constant bounds checking for slicing --- core/_preload.odin | 1 + core/strconv.odin | 8 ++++---- core/utf16.odin | 6 +++--- src/check_expr.c | 18 ++++++++++++------ src/ir.c | 15 ++------------- 5 files changed, 22 insertions(+), 26 deletions(-) diff --git a/core/_preload.odin b/core/_preload.odin index 6939a8c17..3419c78d8 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -350,6 +350,7 @@ __slice_expr_error :: proc(file: string, line, column: int, low, high, max: int) file, line, column, low, high, max); __debug_trap(); } + __substring_expr_error :: proc(file: string, line, column: int, low, high: int) { if 0 <= low && low <= high { return; diff --git a/core/strconv.odin b/core/strconv.odin index 21a466871..853134499 100644 --- a/core/strconv.odin +++ b/core/strconv.odin @@ -21,12 +21,12 @@ parse_bool :: proc(s: string) -> (result: bool, ok: bool) { _digit_value :: proc(r: rune) -> (int) { ri := cast(int)r; v: int = 16; - match { - case '0' <= r && r <= '9': + match r { + case '0'..'9': v = ri - '0'; - case 'a' <= r && r <= 'z': + case 'a'..'z': v = ri - 'a' + 10; - case 'A' <= r && r <= 'Z': + case 'A'..'Z': v = ri - 'A' + 10; } return v; diff --git a/core/utf16.odin b/core/utf16.odin index a01261493..222688f1d 100644 --- a/core/utf16.odin +++ b/core/utf16.odin @@ -39,12 +39,12 @@ encode :: proc(d: []u16, s: []rune) { n = 0; for r in s { - match { - case 0 <= r && r < _surr1, _surr3 <= r && r < _surr_self: + match r { + case 0..<_surr1, _surr3..<_surr_self: d[n] = cast(u16)r; n++; - case _surr_self <= r && r <= MAX_RUNE: + case _surr_self..MAX_RUNE: r1, r2 := encode_surrogate_pair(r); d[n] = cast(u16)r1; d[n+1] = cast(u16)r2; diff --git a/src/check_expr.c b/src/check_expr.c index 75e848903..848414fb9 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -2777,7 +2777,7 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level update_expr_type(c, operand->expr, target_type, true); } -bool check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *value) { +bool check_index_value(Checker *c, bool open_range, AstNode *index_value, i64 max_count, i64 *value) { Operand operand = {Addressing_Invalid}; check_expr(c, &operand, index_value); if (operand.mode == Addressing_Invalid) { @@ -2812,7 +2812,13 @@ bool check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *val if (max_count >= 0) { // NOTE(bill): Do array bound checking if (value) *value = i; - if (i >= max_count) { + bool out_of_bounds = false; + if (open_range) { + out_of_bounds = i >= max_count; + } else { + out_of_bounds = i > max_count; + } + if (out_of_bounds) { gbString expr_str = expr_to_string(operand.expr); error_node(operand.expr, "Index `%s` is out of bounds range 0..<%lld", expr_str, max_count); gb_string_free(expr_str); @@ -3323,7 +3329,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id isize size_count = 0; for (isize i = 1; i < arg_count; i++) { i64 val = 0; - bool ok = check_index_value(c, ce->args.e[i], -1, &val); + bool ok = check_index_value(c, false, ce->args.e[i], -1, &val); if (ok && val >= 0) { GB_ASSERT(size_count < gb_count_of(sizes)); sizes[size_count++] = val; @@ -4129,7 +4135,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id isize size_count = 0; for (isize i = 1; i < arg_count; i++) { i64 val = 0; - bool ok = check_index_value(c, ce->args.e[i], -1, &val); + bool ok = check_index_value(c, false, ce->args.e[i], -1, &val); if (ok && val >= 0) { GB_ASSERT(size_count < gb_count_of(sizes)); sizes[size_count++] = val; @@ -5664,7 +5670,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t } i64 index = 0; - bool ok = check_index_value(c, ie->index, max_count, &index); + bool ok = check_index_value(c, false, ie->index, max_count, &index); case_end; @@ -5767,7 +5773,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t capacity = max_count; } i64 j = 0; - if (check_index_value(c, nodes[i], capacity, &j)) { + if (check_index_value(c, interval_kind == Token_Ellipsis, nodes[i], capacity, &j)) { index = j; } } else if (i == 0) { diff --git a/src/ir.c b/src/ir.c index 87bfe7095..c48d7f84b 100644 --- a/src/ir.c +++ b/src/ir.c @@ -4913,16 +4913,12 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { if (se->high != NULL) high = ir_build_expr(proc, se->high); if (se->max != NULL) max = ir_build_expr(proc, se->max); - bool add_one_to_len = false; - bool add_one_to_cap = false; - if (high != NULL && se->interval0.kind == Token_Ellipsis) { - add_one_to_len = true; + high = ir_emit_arith(proc, Token_Add, high, v_one, t_int); } if (max != NULL && se->interval1.kind == Token_Ellipsis) { - GB_ASSERT(se->interval0.kind == se->interval1.kind); - add_one_to_cap = true; + max = ir_emit_arith(proc, Token_Add, max, v_one, t_int); } irValue *addr = ir_build_addr(proc, se->expr).addr; @@ -4948,8 +4944,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { irValue *elem = ir_emit_ptr_offset(proc, ir_slice_elem(proc, base), low); irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int); - if (add_one_to_len) len = ir_emit_arith(proc, Token_Add, len, v_one, t_int); - if (add_one_to_cap) cap = ir_emit_arith(proc, Token_Add, cap, v_one, t_int); irValue *slice = ir_add_local_generated(proc, slice_type); ir_fill_slice(proc, slice, elem, len, cap); @@ -4968,8 +4962,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { irValue *elem = ir_emit_ptr_offset(proc, ir_dynamic_array_elem(proc, base), low); irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int); - if (add_one_to_len) len = ir_emit_arith(proc, Token_Add, len, v_one, t_int); - if (add_one_to_cap) cap = ir_emit_arith(proc, Token_Add, cap, v_one, t_int); irValue *slice = ir_add_local_generated(proc, slice_type); ir_fill_slice(proc, slice, elem, len, cap); @@ -4988,8 +4980,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { irValue *elem = ir_emit_ptr_offset(proc, ir_array_elem(proc, addr), low); irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int); - if (add_one_to_len) len = ir_emit_arith(proc, Token_Add, len, v_one, t_int); - if (add_one_to_cap) cap = ir_emit_arith(proc, Token_Add, cap, v_one, t_int); irValue *slice = ir_add_local_generated(proc, slice_type); ir_fill_slice(proc, slice, elem, len, cap); @@ -5005,7 +4995,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { irValue *elem = ir_emit_ptr_offset(proc, ir_string_elem(proc, base), low); irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); - if (add_one_to_len) len = ir_emit_arith(proc, Token_Add, len, v_one, t_int); irValue *str = ir_add_local_generated(proc, t_string); ir_fill_string(proc, str, elem, len);