aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2018-06-09 17:56:29 -0700
committerPaul Eggert2018-06-09 17:57:29 -0700
commit3e3e23fb88fdc19e859c0aa2ab51b86afd323c71 (patch)
treeb579820537e9996b2c7f35bac95eff2f1700c178 /src
parentd12924cacb86c53a0547f73af35169db8e44d628 (diff)
downloademacs-3e3e23fb88fdc19e859c0aa2ab51b86afd323c71.tar.gz
emacs-3e3e23fb88fdc19e859c0aa2ab51b86afd323c71.zip
Fix pointer misuse in JSON parser
* src/json.c (lisp_to_json_toplevel_1): Fix pointer misuse not caught by C type checking (json_t ** converted to void * where the program expected json_t *). Bug caught on Fedora 28 x86-64 via './configure CFLAGS="-g3 -O2 -fsanitize=address" CANNOT_DUMP=yes'. Avoid similar problems in the future by rewriting to use json_t * instead of json_t **.
Diffstat (limited to 'src')
-rw-r--r--src/json.c60
1 files changed, 28 insertions, 32 deletions
diff --git a/src/json.c b/src/json.c
index afb81587a47..c28e14d63c6 100644
--- a/src/json.c
+++ b/src/json.c
@@ -327,36 +327,35 @@ json_check_utf8 (Lisp_Object string)
327 327
328static json_t *lisp_to_json (Lisp_Object); 328static json_t *lisp_to_json (Lisp_Object);
329 329
330/* Convert a Lisp object to a toplevel JSON object (array or object). 330/* Convert a Lisp object to a toplevel JSON object (array or object). */
331 This returns Lisp_Object so we can use unbind_to. The return value
332 is always nil. */
333 331
334static _GL_ARG_NONNULL ((2)) Lisp_Object 332static json_t *
335lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json) 333lisp_to_json_toplevel_1 (Lisp_Object lisp)
336{ 334{
335 json_t *json;
336 ptrdiff_t count;
337
337 if (VECTORP (lisp)) 338 if (VECTORP (lisp))
338 { 339 {
339 ptrdiff_t size = ASIZE (lisp); 340 ptrdiff_t size = ASIZE (lisp);
340 *json = json_check (json_array ()); 341 json = json_check (json_array ());
341 ptrdiff_t count = SPECPDL_INDEX (); 342 count = SPECPDL_INDEX ();
342 record_unwind_protect_ptr (json_release_object, json); 343 record_unwind_protect_ptr (json_release_object, json);
343 for (ptrdiff_t i = 0; i < size; ++i) 344 for (ptrdiff_t i = 0; i < size; ++i)
344 { 345 {
345 int status 346 int status
346 = json_array_append_new (*json, lisp_to_json (AREF (lisp, i))); 347 = json_array_append_new (json, lisp_to_json (AREF (lisp, i)));
347 if (status == -1) 348 if (status == -1)
348 json_out_of_memory (); 349 json_out_of_memory ();
349 } 350 }
350 eassert (json_array_size (*json) == size); 351 eassert (json_array_size (json) == size);
351 clear_unwind_protect (count);
352 return unbind_to (count, Qnil);
353 } 352 }
354 else if (HASH_TABLE_P (lisp)) 353 else if (HASH_TABLE_P (lisp))
355 { 354 {
356 struct Lisp_Hash_Table *h = XHASH_TABLE (lisp); 355 struct Lisp_Hash_Table *h = XHASH_TABLE (lisp);
357 *json = json_check (json_object ()); 356 json = json_check (json_object ());
358 ptrdiff_t count = SPECPDL_INDEX (); 357 count = SPECPDL_INDEX ();
359 record_unwind_protect_ptr (json_release_object, *json); 358 record_unwind_protect_ptr (json_release_object, json);
360 for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) 359 for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
361 if (!NILP (HASH_HASH (h, i))) 360 if (!NILP (HASH_HASH (h, i)))
362 { 361 {
@@ -367,9 +366,9 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json)
367 const char *key_str = SSDATA (key); 366 const char *key_str = SSDATA (key);
368 /* Reject duplicate keys. These are possible if the hash 367 /* Reject duplicate keys. These are possible if the hash
369 table test is not `equal'. */ 368 table test is not `equal'. */
370 if (json_object_get (*json, key_str) != NULL) 369 if (json_object_get (json, key_str) != NULL)
371 wrong_type_argument (Qjson_value_p, lisp); 370 wrong_type_argument (Qjson_value_p, lisp);
372 int status = json_object_set_new (*json, key_str, 371 int status = json_object_set_new (json, key_str,
373 lisp_to_json (HASH_VALUE (h, i))); 372 lisp_to_json (HASH_VALUE (h, i)));
374 if (status == -1) 373 if (status == -1)
375 { 374 {
@@ -379,20 +378,15 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json)
379 json_out_of_memory (); 378 json_out_of_memory ();
380 } 379 }
381 } 380 }
382 clear_unwind_protect (count);
383 return unbind_to (count, Qnil);
384 } 381 }
385 else if (NILP (lisp)) 382 else if (NILP (lisp))
386 { 383 return json_check (json_object ());
387 *json = json_check (json_object ());
388 return Qnil;
389 }
390 else if (CONSP (lisp)) 384 else if (CONSP (lisp))
391 { 385 {
392 Lisp_Object tail = lisp; 386 Lisp_Object tail = lisp;
393 *json = json_check (json_object ()); 387 json = json_check (json_object ());
394 ptrdiff_t count = SPECPDL_INDEX (); 388 count = SPECPDL_INDEX ();
395 record_unwind_protect_ptr (json_release_object, *json); 389 record_unwind_protect_ptr (json_release_object, json);
396 bool is_plist = !CONSP (XCAR (tail)); 390 bool is_plist = !CONSP (XCAR (tail));
397 FOR_EACH_TAIL (tail) 391 FOR_EACH_TAIL (tail)
398 { 392 {
@@ -427,19 +421,22 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json)
427 key_str = &key_str[1]; 421 key_str = &key_str[1];
428 } 422 }
429 /* Only add element if key is not already present. */ 423 /* Only add element if key is not already present. */
430 if (json_object_get (*json, key_str) == NULL) 424 if (json_object_get (json, key_str) == NULL)
431 { 425 {
432 int status 426 int status
433 = json_object_set_new (*json, key_str, lisp_to_json (value)); 427 = json_object_set_new (json, key_str, lisp_to_json (value));
434 if (status == -1) 428 if (status == -1)
435 json_out_of_memory (); 429 json_out_of_memory ();
436 } 430 }
437 } 431 }
438 CHECK_LIST_END (tail, lisp); 432 CHECK_LIST_END (tail, lisp);
439 clear_unwind_protect (count);
440 return unbind_to (count, Qnil);
441 } 433 }
442 wrong_type_argument (Qjson_value_p, lisp); 434 else
435 wrong_type_argument (Qjson_value_p, lisp);
436
437 clear_unwind_protect (count);
438 unbind_to (count, Qnil);
439 return json;
443} 440}
444 441
445/* Convert LISP to a toplevel JSON object (array or object). Signal 442/* Convert LISP to a toplevel JSON object (array or object). Signal
@@ -451,8 +448,7 @@ lisp_to_json_toplevel (Lisp_Object lisp)
451{ 448{
452 if (++lisp_eval_depth > max_lisp_eval_depth) 449 if (++lisp_eval_depth > max_lisp_eval_depth)
453 xsignal0 (Qjson_object_too_deep); 450 xsignal0 (Qjson_object_too_deep);
454 json_t *json; 451 json_t *json = lisp_to_json_toplevel_1 (lisp);
455 lisp_to_json_toplevel_1 (lisp, &json);
456 --lisp_eval_depth; 452 --lisp_eval_depth;
457 return json; 453 return json;
458} 454}