mirror of
https://github.com/janet-lang/janet
synced 2025-02-08 04:50:02 +00:00
Address issue #1539 - infinite loop in peg split
Other looping rules ensure forward progress by terminating if an iteration is at the same location as the previous iteration. Do the same for split.
This commit is contained in:
parent
f252933f62
commit
60d9f97750
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Calvin Rose
|
||||
* Copyright (c) 2025 Calvin Rose
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
@ -549,36 +549,39 @@ tail:
|
||||
const uint32_t *rule_separator = s->bytecode + rule[1];
|
||||
const uint32_t *rule_subpattern = s->bytecode + rule[2];
|
||||
|
||||
const uint8_t *separator_end = NULL;
|
||||
do {
|
||||
const uint8_t *text_start = text;
|
||||
const uint8_t *chunk_start = text;
|
||||
const uint8_t *chunk_end = NULL;
|
||||
|
||||
while (text <= saved_end) {
|
||||
/* Find next split (or end of text) */
|
||||
CapState cs = cap_save(s);
|
||||
down1(s);
|
||||
while (text <= s->text_end) {
|
||||
separator_end = peg_rule(s, rule_separator, text);
|
||||
while (text <= saved_end) {
|
||||
chunk_end = text;
|
||||
const uint8_t *check = peg_rule(s, rule_separator, text);
|
||||
cap_load(s, cs);
|
||||
if (separator_end) {
|
||||
if (check) {
|
||||
text = check;
|
||||
break;
|
||||
}
|
||||
text++;
|
||||
}
|
||||
up1(s);
|
||||
|
||||
if (separator_end) {
|
||||
s->text_end = text;
|
||||
text = separator_end;
|
||||
}
|
||||
|
||||
/* Match between splits */
|
||||
s->text_end = chunk_end;
|
||||
down1(s);
|
||||
const uint8_t *subpattern_end = peg_rule(s, rule_subpattern, text_start);
|
||||
const uint8_t *subpattern_end = peg_rule(s, rule_subpattern, chunk_start);
|
||||
up1(s);
|
||||
s->text_end = saved_end;
|
||||
if (!subpattern_end) return NULL; /* Don't match anything */
|
||||
|
||||
if (!subpattern_end) {
|
||||
return NULL;
|
||||
/* Ensure forward progress */
|
||||
if (text == chunk_start) return NULL;
|
||||
chunk_start = text;
|
||||
}
|
||||
} while (separator_end);
|
||||
|
||||
s->text_end = saved_end;
|
||||
return s->text_end;
|
||||
}
|
||||
|
||||
|
@ -772,5 +772,16 @@
|
||||
"5:apple6:banana6:cherry"
|
||||
@["apple" "banana" "cherry"])
|
||||
|
||||
# Issue #1539 - make sure split with "" doesn't infinite loop/oom
|
||||
(test "issue 1539"
|
||||
~(split "" (capture (to -1)))
|
||||
"hello there friends"
|
||||
nil)
|
||||
|
||||
(test "issue 1539 pt. 2"
|
||||
~(split "," (capture 0))
|
||||
"abc123,,,,"
|
||||
@["" "" "" "" ""])
|
||||
|
||||
(end-suite)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user