From a992216ec07db3f99e9202d9e7d81fffb425ef6c Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Wed, 23 Sep 2026 00:09:14 -0700 Subject: [PATCH] p2: widen document fence for space and zero-width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Strip U+200B–U+200D, U+2060, U+FEFF before fencing. Match (?i)<\s*/?\s*document so cannot sit outside the frame. --- internal/digest/digest.go | 8 ++++++-- internal/digest/digest_test.go | 11 +++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/internal/digest/digest.go b/internal/digest/digest.go index c55f9f8..b5d2676 100644 --- a/internal/digest/digest.go +++ b/internal/digest/digest.go @@ -577,11 +577,15 @@ func min(a, b int) int { return b } -var documentTag = regexp.MustCompile(`(?i)= 2 && m[1] == '/' { + if strings.Contains(m, "/") { return "</document" } return "<document" diff --git a/internal/digest/digest_test.go b/internal/digest/digest_test.go index 8644550..3de0107 100644 --- a/internal/digest/digest_test.go +++ b/internal/digest/digest_test.go @@ -109,6 +109,17 @@ func TestDocumentTagStaysInFrame(t *testing.T) { } } +func TestFenceSpaceAndZW(t *testing.T) { + zw := "hello \n" + out := fenceDocument(zw + "") + if strings.Contains(out, "") || strings.Contains(strings.ToLower(out), "") { + t.Fatalf("unfenced: %q", out) + } + if !strings.Contains(out, "</document") { + t.Fatalf("missing escape: %q", out) + } +} + func TestFallbackOnTimeout(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(200 * time.Millisecond)