harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 1d0a77647a7a165215ee915e0857efa4d620f574
parent 131d90a4171e3ad38303c3a8d769233dde585802
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Fri, 13 Aug 2021 11:10:59 +0000

gen: fix off-by-one in slice/delete bounds check

foo[len(foo)..] is valid

Signed-off-by: Eyal Sawady <ecs@d2evs.net>

Diffstat:
Msrc/gen.c | 4++--
Mtests/08-slices.ha | 5++++-
Mtests/22-delete.ha | 2++
3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -1531,7 +1531,7 @@ gen_expr_delete(struct gen_context *ctx, const struct expression *expr) struct qbe_value start_oob = mkqtmp(ctx, &qbe_word, ".%d"); struct qbe_value end_oob = mkqtmp(ctx, &qbe_word, ".%d"); struct qbe_value valid = mkqtmp(ctx, &qbe_word, ".%d"); - pushi(ctx->current, &start_oob, Q_CULTL, &qstart, &qlen, NULL); + pushi(ctx->current, &start_oob, Q_CULEL, &qstart, &qlen, NULL); pushi(ctx->current, &end_oob, Q_CULEL, &qend, &qlen, NULL); pushi(ctx->current, &valid, Q_AND, &start_oob, &end_oob, NULL); @@ -2360,7 +2360,7 @@ gen_expr_slice_at(struct gen_context *ctx, struct qbe_value start_oob = mkqtmp(ctx, &qbe_word, ".%d"); struct qbe_value end_oob = mkqtmp(ctx, &qbe_word, ".%d"); struct qbe_value valid = mkqtmp(ctx, &qbe_word, ".%d"); - pushi(ctx->current, &start_oob, Q_CULTL, &qstart, &qlength, NULL); + pushi(ctx->current, &start_oob, Q_CULEL, &qstart, &qlength, NULL); pushi(ctx->current, &end_oob, Q_CULEL, &qend, &qlength, NULL); pushi(ctx->current, &valid, Q_AND, &start_oob, &end_oob, NULL); diff --git a/tests/08-slices.ha b/tests/08-slices.ha @@ -108,19 +108,22 @@ fn slicing() void = { assert_slice_eq(a[..3], [1, 2, 3]); assert_slice_eq(a[1..3], [2, 3]); assert_slice_eq(a[1..], [2, 3, 4, 5]); + assert_slice_eq(a[5..], []); let b: []int = [1, 2, 3, 4, 5]; assert_slice_eq(b[..], [1, 2, 3, 4, 5]); assert_slice_eq(b[..3], [1, 2, 3]); assert_slice_eq(b[1..3], [2, 3]); assert_slice_eq(b[1..], [2, 3, 4, 5]); + assert_slice_eq(b[5..], []); let p = &a; assert_slice_eq(p[..], [1, 2, 3, 4, 5]); assert_slice_eq(p[..3], [1, 2, 3]); assert_slice_eq(p[1..3], [2, 3]); assert_slice_eq(p[1..], [2, 3, 4, 5]); - + assert_slice_eq(p[5..], []); + assert(rt::compile( "fn test() void = { let x = \"test\"; x[1..3]; };" ) != 0, "slicing non-array, non-slice object"); diff --git a/tests/22-delete.ha b/tests/22-delete.ha @@ -25,6 +25,8 @@ fn slice() void = { assert(len(x) == 2); assert(x[0] == 4 && x[1] == 5); + delete(x[len(x)..]); + static delete(y[..]); assert(len(x) == 0); assert(s.capacity < 5);