small fixes and oob checks, stop infinite loops on empty matches

This commit is contained in:
skytrias
2022-12-18 23:11:23 +01:00
parent eb5523d5d3
commit 0ae1812f90
+15 -4
View File
@@ -23,6 +23,7 @@ Error :: enum {
Unfinished_Capture, Unfinished_Capture,
Malformed_Pattern, Malformed_Pattern,
Rune_Error, Rune_Error,
Match_Invalid,
} }
L_ESC :: '%' L_ESC :: '%'
@@ -183,17 +184,21 @@ classend :: proc(ms: ^MatchState, p: int) -> (step: int, err: Error) {
case '[': { case '[': {
// fine with step by 1 // fine with step by 1
if ms.pattern[step] == '^' { if step + 1 < len(ms.pattern) && ms.pattern[step] == '^' {
step += 1 step += 1
} }
// run till end is reached // run till end is reached
for ms.pattern[step] != ']' { for {
if step == len(ms.pattern) { if step == len(ms.pattern) {
err = .Malformed_Pattern err = .Malformed_Pattern
return return
} }
if ms.pattern[step] == ']' {
break
}
// dont care about utf8 here // dont care about utf8 here
step += 1 step += 1
@@ -417,7 +422,7 @@ match :: proc(ms: ^MatchState, s, p: int) -> (unused: int, err: Error) {
char, _ := utf8_peek(ms.pattern[p:]) or_return char, _ := utf8_peek(ms.pattern[p:]) or_return
switch char { switch char {
case '(': { case '(': {
if ms.pattern[p + 1] == ')' { if p + 1 < len(ms.pattern) && ms.pattern[p + 1] == ')' {
s = start_capture(ms, s, p + 2, CAP_POSITION) or_return s = start_capture(ms, s, p + 2, CAP_POSITION) or_return
} else { } else {
s = start_capture(ms, s, p + 1, CAP_UNFINISHED) or_return s = start_capture(ms, s, p + 1, CAP_UNFINISHED) or_return
@@ -582,7 +587,7 @@ push_onecapture :: proc(
} }
case CAP_POSITION: { case CAP_POSITION: {
matches[i] = { init - 1, init - 1 } matches[i] = { init, init + 1 }
} }
case: { case: {
@@ -697,8 +702,14 @@ find_aux :: proc(
res := match(&ms, s, p) or_return res := match(&ms, s, p) or_return
if res != INVALID { if res != INVALID {
// disallow non advancing match
if s == res {
err = .Match_Invalid
}
// NOTE(Skytrias): first result is reserved for a full match // NOTE(Skytrias): first result is reserved for a full match
matches[0] = { s, res } matches[0] = { s, res }
// rest are the actual captures // rest are the actual captures
captures = push_captures(&ms, -1, -1, matches[1:]) or_return captures = push_captures(&ms, -1, -1, matches[1:]) or_return
captures += 1 captures += 1