]> git.eshelyaron.com Git - emacs.git/commitdiff
Respect narrowed buffers when parsing JSON (bug#77325)
authorPip Cet <pipcet@protonmail.com>
Fri, 28 Mar 2025 02:33:19 +0000 (02:33 +0000)
committerEshel Yaron <me@eshelyaron.com>
Mon, 31 Mar 2025 08:54:52 +0000 (10:54 +0200)
* src/json.c (Fjson_insert): Simplify 'memcpy' argument.
(Fjson_parse_buffer): Only read to ZV, not all the way to Z.
* test/src/json-tests.el (with-all-gap-positions-in-temp-buffer):
New macro.
(json-parse-buffer/restricted): New test.

(cherry picked from commit 67e34f0ed8f6d3bbc78187a18f71010c70e10426)

src/json.c
test/src/json-tests.el

index f438d191bded2e4ca521d1595c7db1a42ac10513..5795c582ce058910e9396071860ee32fd01dedb0 100644 (file)
@@ -641,7 +641,7 @@ usage: (json-insert OBJECT &rest ARGS)  */)
   move_gap_both (PT, PT_BYTE);
   if (GAP_SIZE < jo.size)
     make_gap (jo.size - GAP_SIZE);
-  memcpy ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE, jo.buf, jo.size);
+  memcpy (GPT_ADDR, jo.buf, jo.size);
 
   /* No need to keep allocation beyond this point.  */
   unbind_to (count, Qnil);
@@ -1754,15 +1754,16 @@ usage: (json-parse-buffer &rest args) */)
 
   struct json_parser p;
   unsigned char *begin = PT_ADDR;
-  unsigned char *end = GPT_ADDR;
+  unsigned char *end = (GPT == ZV) ? GPT_ADDR : ZV_ADDR;
   unsigned char *secondary_begin = NULL;
   unsigned char *secondary_end = NULL;
-  if (GPT_ADDR < Z_ADDR)
+  if (PT == ZV)
+    begin = end = NULL;
+  else if (GPT > PT && GPT < ZV && GAP_SIZE > 0)
     {
+      end = GPT_ADDR;
       secondary_begin = GAP_END_ADDR;
-      if (secondary_begin < PT_ADDR)
-       secondary_begin = PT_ADDR;
-      secondary_end = Z_ADDR;
+      secondary_end = ZV_ADDR;
     }
 
   json_parser_init (&p, conf, begin, end, secondary_begin,
index 94b6cfcffca0fa7628b8bf9a2f8aab31d774d75c..1cb667ddeac3ad35b30677fee558308cd958c55c 100644 (file)
@@ -315,6 +315,32 @@ Test with both unibyte and multibyte strings."
     (should-not (bobp))
     (should (looking-at-p (rx " [456]" eos)))))
 
+(defmacro with-all-gap-positions-in-temp-buffer (string &rest body)
+  "Create a temporary buffer containing STRING, and evaluate BODY
+with each possible gap position.
+See also `with-temp-buffer'."
+  `(with-temp-buffer
+     (insert ,string)
+     (dotimes (i (- (point-max) (point-min)))
+       (goto-char (- (point-max) i))
+       (insert "X")
+       (delete-region (1- (point)) (point))
+       ,@body)))
+
+(ert-deftest json-parse-buffer/restricted ()
+  (with-all-gap-positions-in-temp-buffer
+   "[123] [456] [789]"
+   (pcase-dolist (`((,beg . ,end) ,result)
+                  '(((7 . 12) [456])
+                    ((1 . 6) [123])
+                    ((13 . 18) [789])))
+     (goto-char beg)
+     (narrow-to-region beg end)
+     (should (equal (json-parse-buffer) result))
+     (should (= (point) end))
+     (should-error (json-parse-buffer) :type 'json-end-of-file)
+     (widen))))
+
 (ert-deftest json-parse-with-custom-null-and-false-objects ()
   (let* ((input
           "{ \"abc\" : [9, false] , \"def\" : null }")