Respect narrowed buffers when parsing JSON (bug#77325)

* 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.
This commit is contained in:
Pip Cet 2025-03-28 02:33:19 +00:00
parent 209b7e7444
commit 67e34f0ed8
2 changed files with 33 additions and 6 deletions

View 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,

View 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 }")