summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/render/escape.ml8
1 files changed, 8 insertions, 0 deletions
diff --git a/lib/render/escape.ml b/lib/render/escape.ml
index 53fdd46..f506c44 100644
--- a/lib/render/escape.ml
+++ b/lib/render/escape.ml
@@ -77,6 +77,14 @@ let fold_ics line =
else begin
let cut = ref (pos + limit) in
while !cut > pos && is_cont line.[!cut] do decr cut done;
+ (* Valid UTF-8's longest continuation run is 3, so backoff finds a
+ boundary within a few bytes. But this function must stay TOTAL on
+ ARBITRARY octet strings, not only valid UTF-8: 74+ consecutive
+ continuation bytes back `cut` all the way down to `pos`, which would
+ yield a zero-length chunk and recurse on the identical position
+ forever. When backoff finds no boundary inside the window, cut hard
+ at the limit instead -- forward progress is then unconditional. *)
+ if !cut = pos then cut := pos + limit;
if not first then Buffer.add_char b ' ';
Buffer.add_string b (String.sub line pos (!cut - pos));
Buffer.add_string b "\r\n";