Skip to content

Commit be1edd2

Browse files
committed
FIX: dealing with index past tail scenarios
resolves: Oldes/Rebol-issues#2542 resolves: Oldes/Rebol-issues#2543
1 parent b47bbde commit be1edd2

File tree

4 files changed

+125
-1
lines changed

4 files changed

+125
-1
lines changed

src/core/n-data.c

+1
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,7 @@ static int Do_Ordinal(REBVAL *ds, REBINT n)
894894
action = Value_Dispatch[VAL_TYPE(val)];
895895
if (ANY_SERIES(val)) {
896896
t = VAL_TAIL(val);
897+
if (VAL_INDEX(val) >= t) return R_NONE;
897898
VAL_INDEX(val) = 0;
898899
}
899900
else if (IS_TUPLE(val)) t = VAL_TUPLE_LEN(val);

src/core/t-block.c

+3
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,8 @@ static struct {
635635
index = VAL_INDEX(value);
636636
tail = VAL_TAIL(value);
637637
ser = VAL_SERIES(value);
638+
if (index > tail)
639+
VAL_INDEX(value) = index = tail;
638640

639641
// Check must be in this order (to avoid checking a non-series value);
640642
if (action >= A_TAKE && action <= A_SORT && IS_PROTECT_SERIES(ser))
@@ -710,6 +712,7 @@ static struct {
710712

711713
index = VAL_INDEX(value); // /part can change index
712714
// take/last:
715+
if (tail <= index) goto is_none;
713716
if (D_REF(ARG_TAKE_LAST)) index = tail - len;
714717
if (index >= tail) {
715718
if (!D_REF(ARG_TAKE_PART)) goto is_none;

src/core/t-string.c

+3
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,8 @@ static struct {
584584
if (action != A_MAKE && action != A_TO) {
585585
index = (REBINT)VAL_INDEX(value);
586586
tail = (REBINT)VAL_TAIL(value);
587+
if (index > tail)
588+
VAL_INDEX(value) = index = tail;
587589
}
588590

589591
// Check must be in this order (to avoid checking a non-series value);
@@ -717,6 +719,7 @@ static struct {
717719
index = VAL_INDEX(value); // /part can change index
718720

719721
// take/last:
722+
if (tail <= index) goto is_none;
720723
if (D_REF(5)) index = tail - len;
721724
if (index < 0 || index >= tail) {
722725
if (!D_REF(2)) goto is_none;

src/tests/units/series-test.r3

+118-1
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,31 @@ Rebol [
599599
--assert "34" = take/part skip s 2 -5 ;@@ https://github.com/Oldes/Rebol-issues/issues/373
600600
--assert "56" = take/part s 10
601601

602+
--test-- "take/part string! with negative part"
603+
;@@ https://github.com/red/red/issues/4078
604+
s: "123" --assert "" == take/part s -1
605+
s: "123" --assert "1" == take/part skip s 1 -1
606+
s: "123" --assert "2" == take/part skip s 2 -1
607+
s: "123" --assert "3" == take/part skip s 3 -1
608+
s: "123" --assert "1" == take/part skip s 1 -2
609+
s: "123" --assert "12" == take/part skip s 2 -2
610+
s: "123" --assert "23" == take/part skip s 3 -2
611+
s: "123" --assert "1" == take/part skip s 1 -3
612+
s: "123" --assert "12" == take/part skip s 2 -3
613+
s: "123" --assert "123" == take/part skip s 3 -3
614+
s: "123" --assert "1" == take/part s skip s 1
615+
s: "123" --assert "1" == take/part skip s 1 s
616+
s: "123" --assert "2" == take/part skip s 1 skip s 2
617+
s: "123" --assert "2" == take/part skip s 2 skip s 1
618+
s: "123" --assert "3" == take/part skip s 2 skip s 3
619+
s: "123" --assert "3" == take/part skip s 3 skip s 2
620+
s: "123" --assert "12" == take/part s skip s 2
621+
s: "123" --assert "12" == take/part skip s 2 s
622+
s: "123" --assert "23" == take/part skip s 1 skip s 3
623+
s: "123" --assert "23" == take/part skip s 3 skip s 1
624+
s: "123" --assert "123" == take/part s skip s 3
625+
s: "123" --assert "123" == take/part skip s 3 s
626+
602627
--test-- "take/part any-block!"
603628
--assert [1 2] = take/part [1 2 3 4] 2
604629
;@@ https://github.com/Oldes/Rebol-issues/issues/2174
@@ -608,12 +633,44 @@ Rebol [
608633
--assert ":a/b" = mold take/part quote :a/b/c 2
609634
--assert "a/b:" = mold take/part quote a/b/c: 2
610635

636+
--test-- "take/part block! with negative part"
637+
;@@ https://github.com/red/red/issues/4078
638+
s: [1 2 3] --assert [ ] == take/part s -1
639+
s: [1 2 3] --assert [1] == take/part skip s 1 -1
640+
s: [1 2 3] --assert [2] == take/part skip s 2 -1
641+
s: [1 2 3] --assert [3] == take/part skip s 3 -1
642+
s: [1 2 3] --assert [1] == take/part skip s 1 -2
643+
s: [1 2 3] --assert [1 2] == take/part skip s 2 -2
644+
s: [1 2 3] --assert [2 3] == take/part skip s 3 -2
645+
s: [1 2 3] --assert [1] == take/part skip s 1 -3
646+
s: [1 2 3] --assert [1 2] == take/part skip s 2 -3
647+
s: [1 2 3] --assert [1 2 3] == take/part skip s 3 -3
648+
s: [1 2 3] --assert [1] == take/part s skip s 1
649+
s: [1 2 3] --assert [1] == take/part skip s 1 s
650+
s: [1 2 3] --assert [2] == take/part skip s 1 skip s 2
651+
s: [1 2 3] --assert [2] == take/part skip s 2 skip s 1
652+
s: [1 2 3] --assert [3] == take/part skip s 2 skip s 3
653+
s: [1 2 3] --assert [3] == take/part skip s 3 skip s 2
654+
s: [1 2 3] --assert [1 2] == take/part s skip s 2
655+
s: [1 2 3] --assert [1 2] == take/part skip s 2 s
656+
s: [1 2 3] --assert [2 3] == take/part skip s 1 skip s 3
657+
s: [1 2 3] --assert [2 3] == take/part skip s 3 skip s 1
658+
s: [1 2 3] --assert [1 2 3] == take/part s skip s 3
659+
s: [1 2 3] --assert [1 2 3] == take/part skip s 3 s
660+
611661
--test-- "take/last"
612662
;@@ https://github.com/Oldes/Rebol-issues/issues/177
613663
--assert #"c" = take/last str: "abc"
614664
--assert "ab" = str
615665
--assert 3 = take/last blk: [1 2 3]
616666
--assert [1 2] = blk
667+
;@@ https://github.com/Oldes/Rebol-issues/issues/2542
668+
--assert none? take/last tail "123"
669+
--assert none? take/last tail [1 2 3]
670+
--assert "123" = take/last/part tail "123" -3
671+
--assert "" = take/last/part tail "123" 3
672+
--assert [1 2 3] = take/last/part tail [1 2 3] -3
673+
--assert [] = take/last/part tail [1 2 3] 3
617674

618675
;@@ https://github.com/Oldes/Rebol-issues/issues/171
619676
--test-- "take/deep block!"
@@ -1242,6 +1299,66 @@ Rebol [
12421299

12431300
===end-group===
12441301

1302+
1303+
===start-group=== "Series with index past its tail"
1304+
;@@ https://github.com/Oldes/Rebol-issues/issues/2543
1305+
--test-- "any-string"
1306+
src: %ABC
1307+
dir: tail src
1308+
--assert 4 = index? dir
1309+
--assert %ABC = copy/part dir -3
1310+
--assert empty? clear src
1311+
--assert 4 = index? dir
1312+
--assert %"" = copy/part dir -3
1313+
--test-- "any-block"
1314+
src: [A B C]
1315+
dir: tail src
1316+
--assert 4 = index? dir
1317+
--assert [A B C] = copy/part dir -3
1318+
--assert empty? clear src
1319+
--assert 4 = index? dir
1320+
--assert [] = copy/part dir -3
1321+
1322+
--test-- "Red's test (strings)"
1323+
;@@ https://github.com/red/red/issues/3369
1324+
test: does [a: copy "12345678" b: skip a 2 c: skip a 6 remove/part a 4]
1325+
test
1326+
--assert all [a = "5678" b = "78" c = ""]
1327+
test change c 1
1328+
--assert all [a = "56781" b = "781" c = ""]
1329+
test clear c
1330+
--assert all [a = "5678" b = "78" c = ""]
1331+
test remove c
1332+
--assert all [a = "5678" b = "78" c = ""]
1333+
test change/part c 99 -1
1334+
--assert all [a = "56799" b = "799" c = ""]
1335+
test insert c 1
1336+
--assert all [a = "56781" b = "781" c = ""]
1337+
test
1338+
--assert none? last c
1339+
--assert none? take/last c
1340+
--test-- "Red's test (blocks)"
1341+
;@@ https://github.com/red/red/issues/3369
1342+
test: does [a: copy [1 2 3 4 5 6 7 8] b: skip a 2 c: skip a 6 remove/part a 4]
1343+
test
1344+
--assert all [a = [5 6 7 8] b = [7 8] c = []]
1345+
test change c 1
1346+
--assert all [a = [5 6 7 8 1] b = [7 8 1] c = []]
1347+
test clear c
1348+
--assert all [a = [5 6 7 8] b = [7 8] c = []]
1349+
test remove c
1350+
--assert all [a = [5 6 7 8] b = [7 8] c = []]
1351+
test change/part c 99 -1
1352+
--assert all [a = [5 6 7 99] b = [7 99] c = []]
1353+
test insert c 1
1354+
--assert all [a = [5 6 7 8 1] b = [7 8 1] c = []]
1355+
test
1356+
--assert none? last c
1357+
--assert none? take/last c
1358+
1359+
===end-group===
1360+
1361+
12451362
===start-group=== "ANY-OF & ALL-OF"
12461363
;@@ https://github.com/Oldes/Rebol-issues/issues/637
12471364
--test-- "any-of"
@@ -1279,7 +1396,7 @@ Rebol [
12791396
--assert not past? b
12801397
===end-group===
12811398

1282-
===start-group=== "SNGLE?"
1399+
===start-group=== "SINGLE?"
12831400
--test-- "single? block"
12841401
;@@ https://github.com/Oldes/Rebol-issues/issues/875
12851402
--assert single? [a]

0 commit comments

Comments
 (0)