Fix constant bounds checking for slicing

This commit is contained in:
Ginger Bill
2017-04-22 09:40:32 +01:00
parent 91ed51ff5c
commit 0ea815db49
5 changed files with 22 additions and 26 deletions
+1
View File
@@ -350,6 +350,7 @@ __slice_expr_error :: proc(file: string, line, column: int, low, high, max: int)
file, line, column, low, high, max); file, line, column, low, high, max);
__debug_trap(); __debug_trap();
} }
__substring_expr_error :: proc(file: string, line, column: int, low, high: int) { __substring_expr_error :: proc(file: string, line, column: int, low, high: int) {
if 0 <= low && low <= high { if 0 <= low && low <= high {
return; return;
+4 -4
View File
@@ -21,12 +21,12 @@ parse_bool :: proc(s: string) -> (result: bool, ok: bool) {
_digit_value :: proc(r: rune) -> (int) { _digit_value :: proc(r: rune) -> (int) {
ri := cast(int)r; ri := cast(int)r;
v: int = 16; v: int = 16;
match { match r {
case '0' <= r && r <= '9': case '0'..'9':
v = ri - '0'; v = ri - '0';
case 'a' <= r && r <= 'z': case 'a'..'z':
v = ri - 'a' + 10; v = ri - 'a' + 10;
case 'A' <= r && r <= 'Z': case 'A'..'Z':
v = ri - 'A' + 10; v = ri - 'A' + 10;
} }
return v; return v;
+3 -3
View File
@@ -39,12 +39,12 @@ encode :: proc(d: []u16, s: []rune) {
n = 0; n = 0;
for r in s { for r in s {
match { match r {
case 0 <= r && r < _surr1, _surr3 <= r && r < _surr_self: case 0..<_surr1, _surr3..<_surr_self:
d[n] = cast(u16)r; d[n] = cast(u16)r;
n++; n++;
case _surr_self <= r && r <= MAX_RUNE: case _surr_self..MAX_RUNE:
r1, r2 := encode_surrogate_pair(r); r1, r2 := encode_surrogate_pair(r);
d[n] = cast(u16)r1; d[n] = cast(u16)r1;
d[n+1] = cast(u16)r2; d[n+1] = cast(u16)r2;
+12 -6
View File
@@ -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); 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}; Operand operand = {Addressing_Invalid};
check_expr(c, &operand, index_value); check_expr(c, &operand, index_value);
if (operand.mode == Addressing_Invalid) { 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 (max_count >= 0) { // NOTE(bill): Do array bound checking
if (value) *value = i; 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); 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); error_node(operand.expr, "Index `%s` is out of bounds range 0..<%lld", expr_str, max_count);
gb_string_free(expr_str); 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; isize size_count = 0;
for (isize i = 1; i < arg_count; i++) { for (isize i = 1; i < arg_count; i++) {
i64 val = 0; 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) { if (ok && val >= 0) {
GB_ASSERT(size_count < gb_count_of(sizes)); GB_ASSERT(size_count < gb_count_of(sizes));
sizes[size_count++] = val; sizes[size_count++] = val;
@@ -4129,7 +4135,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
isize size_count = 0; isize size_count = 0;
for (isize i = 1; i < arg_count; i++) { for (isize i = 1; i < arg_count; i++) {
i64 val = 0; 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) { if (ok && val >= 0) {
GB_ASSERT(size_count < gb_count_of(sizes)); GB_ASSERT(size_count < gb_count_of(sizes));
sizes[size_count++] = val; sizes[size_count++] = val;
@@ -5664,7 +5670,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
} }
i64 index = 0; 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; case_end;
@@ -5767,7 +5773,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
capacity = max_count; capacity = max_count;
} }
i64 j = 0; 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; index = j;
} }
} else if (i == 0) { } else if (i == 0) {
+2 -13
View File
@@ -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->high != NULL) high = ir_build_expr(proc, se->high);
if (se->max != NULL) max = ir_build_expr(proc, se->max); 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) { 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) { if (max != NULL && se->interval1.kind == Token_Ellipsis) {
GB_ASSERT(se->interval0.kind == se->interval1.kind); max = ir_emit_arith(proc, Token_Add, max, v_one, t_int);
add_one_to_cap = true;
} }
irValue *addr = ir_build_addr(proc, se->expr).addr; 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 *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 *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
irValue *cap = ir_emit_arith(proc, Token_Sub, max, 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); irValue *slice = ir_add_local_generated(proc, slice_type);
ir_fill_slice(proc, slice, elem, len, cap); 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 *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 *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
irValue *cap = ir_emit_arith(proc, Token_Sub, max, 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); irValue *slice = ir_add_local_generated(proc, slice_type);
ir_fill_slice(proc, slice, elem, len, cap); 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 *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 *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
irValue *cap = ir_emit_arith(proc, Token_Sub, max, 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); irValue *slice = ir_add_local_generated(proc, slice_type);
ir_fill_slice(proc, slice, elem, len, cap); 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 *elem = ir_emit_ptr_offset(proc, ir_string_elem(proc, base), low);
irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); 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); irValue *str = ir_add_local_generated(proc, t_string);
ir_fill_string(proc, str, elem, len); ir_fill_string(proc, str, elem, len);