about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2023-09-08 22:31:48 +0200
committerbptato <nincsnevem662@gmail.com>2023-09-08 22:31:48 +0200
commit3ff3b01f1b93510ef97b9f8b74f1f05595d4fd4f (patch)
tree2a004429361c95972de40a5d6c265bce8debf977
parent7093bf3badd4777529379ce735894236f4416676 (diff)
downloadchawan-3ff3b01f1b93510ef97b9f8b74f1f05595d4fd4f.tar.gz
regex: avoid infinite loop
A capture size of 0 (e.g. |) no longer sends the regex matcher into an
infinite loop.
-rw-r--r--src/js/regex.nim8
1 files changed, 7 insertions, 1 deletions
diff --git a/src/js/regex.nim b/src/js/regex.nim
index 157e1fbc..81b73700 100644
--- a/src/js/regex.nim
+++ b/src/js/regex.nim
@@ -1,4 +1,5 @@
 # Interface for QuickJS libregexp.
+import unicode
 
 import bindings/libregexp
 import bindings/quickjs
@@ -149,7 +150,7 @@ proc exec*(regex: Regex, str: string, start = 0, length = -1, nocaps = false): R
   assert 0 <= start and start <= length, "Start: " & $start & ", length: " & $length & " str: " & $str
 
   let captureCount = lre_get_capture_count(regex.bytecode)
-  var capture: ptr UncheckedArray[int]= nil
+  var capture: ptr UncheckedArray[int] = nil
   if captureCount > 0:
     let size = sizeof(ptr uint8) * captureCount * 2
     capture = cast[ptr UncheckedArray[int]](alloc0(size))
@@ -165,6 +166,7 @@ proc exec*(regex: Regex, str: string, start = 0, length = -1, nocaps = false): R
     if captureCount == 0 or nocaps:
       break
     let cstrAddress = cast[int](cstr)
+    let ps = start
     start = capture[1] - cstrAddress
     for i in 0 ..< captureCount:
       let s = capture[i * 2] - cstrAddress
@@ -172,6 +174,10 @@ proc exec*(regex: Regex, str: string, start = 0, length = -1, nocaps = false): R
       result.captures.add((s, e))
     if (flags and LRE_FLAG_GLOBAL) != 1:
       break
+    if start >= str.len:
+      break
+    if ps == start:
+      start += runeLenAt(str, i)
   if captureCount > 0:
     dealloc(capture)