Subject: Re: bug#77325: Crash in Fjson_parse_buffer: ZV changes underneath it?

From: Pip Cet <[email-masked]>
Date: Fri, 28 Mar 2025 02:43:36 +0000

"Daniel Colascione" <[email-masked]> writes:

> Somehow, the buffer changes underneath json_parse.  We pass an

Do we know that the buffer changed after we entered json-parse-buffer?
It looks to me like the buffer was narrowed to nothing before we called
json-parse-buffer, like this:

(with-temp-buffer
  (insert "3")
  (narrow-to-region (point-min) (point-min))
  (message "%S" (json-parse-buffer)))

json.c proceeds to read past ZV, all the way to Z, then hits the
assertion just as it did for you, so this code currently causes a crash.

Do you still see the crash if you change json-parse-buffer to honor
buffer narrowing, like this?

>From 073c00135e6f0e213fc8671fc0a52a67ee5b56ce Mon Sep 17 00:00:00 2001
From: Pip Cet <[email-masked]>
Subject: [PATCH] Respect narrowed buffers when parsing JSON (bug#77325)

* src/json.c (Fjson_parse_buffer): Only read to ZV, not all the way to
Z.
---
 src/json.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/json.c b/src/json.c
index f438d191bde..a0480718ca8 100644
--- a/src/json.c
+++ b/src/json.c
@@ -1757,12 +1757,16 @@ DEFUN ("json-parse-buffer", Fjson_parse_buffer, Sjson_parse_buffer,
   unsigned char *end = GPT_ADDR;
   unsigned char *secondary_begin = NULL;
   unsigned char *secondary_end = NULL;
-  if (GPT_ADDR < Z_ADDR)
+  if (GPT_ADDR < ZV_ADDR)
     {
       secondary_begin = GAP_END_ADDR;
       if (secondary_begin < PT_ADDR)
 	secondary_begin = PT_ADDR;
-      secondary_end = Z_ADDR;
+      secondary_end = ZV_ADDR;
+    }
+  else if (ZV_ADDR < GPT_ADDR)
+    {
+      end = ZV_ADDR;
     }
 
   json_parser_init (&p, conf, begin, end, secondary_begin,
-- 
2.48.1

> input_begin = 0x0000000130096b57 "\n     6 pass\n     620 skip\n [...]
> input_current = 0x0000000130096b5e " pass\n     620 skip\n
>
> The actual JSON we're parsing appears to be mangled somehow --- raw
> newlines embedded in the output instead of being encapsulated inside
> a string --- but that's a separate bug.

Certainly doesn't look like JSON, but maybe that's why it's outside the
accessible region?

Pip