mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-06-14 04:21:24 +00:00
Fix unlikely json.c size overflow calculations
* src/json.c (json_out_grow_buf) (json_make_object_workspace_for_slow_path) (json_byte_workspace_put_slow_path): Use xpalloc rather than doing it by hand. * src/json.c (json_out_grow_buf): Change arg from needed bytes to minimum increment of bytes. Caller changed.
This commit is contained in:
parent
5fd1e0bbef
commit
4d85084509
1 changed files with 29 additions and 57 deletions
86
src/json.c
86
src/json.c
|
|
@ -244,13 +244,10 @@ symset_add (json_out_t *jo, symset_t *ss, Lisp_Object sym)
|
|||
}
|
||||
|
||||
static NO_INLINE void
|
||||
json_out_grow_buf (json_out_t *jo, ptrdiff_t bytes)
|
||||
json_out_grow_buf (json_out_t *jo, ptrdiff_t incr_min)
|
||||
{
|
||||
ptrdiff_t need = jo->size + bytes;
|
||||
ptrdiff_t new_size = max (jo->capacity, 512);
|
||||
while (new_size < need)
|
||||
new_size <<= 1;
|
||||
jo->buf = xrealloc (jo->buf, new_size);
|
||||
ptrdiff_t new_size = jo->capacity;
|
||||
jo->buf = xpalloc (jo->buf, &new_size, incr_min, -1, 1);
|
||||
jo->capacity = new_size;
|
||||
}
|
||||
|
||||
|
|
@ -267,8 +264,9 @@ cleanup_json_out (void *arg)
|
|||
static void
|
||||
json_make_room (json_out_t *jo, ptrdiff_t bytes)
|
||||
{
|
||||
if (bytes > jo->capacity - jo->size)
|
||||
json_out_grow_buf (jo, bytes);
|
||||
ptrdiff_t avail = jo->capacity - jo->size;
|
||||
if (avail < bytes)
|
||||
json_out_grow_buf (jo, bytes - avail);
|
||||
}
|
||||
|
||||
#define JSON_OUT_STR(jo, str) (json_out_str (jo, str, sizeof (str) - 1))
|
||||
|
|
@ -803,36 +801,20 @@ json_parser_done (void *parser)
|
|||
Lisp_Objects */
|
||||
NO_INLINE static void
|
||||
json_make_object_workspace_for_slow_path (struct json_parser *parser,
|
||||
size_t size)
|
||||
ptrdiff_t size)
|
||||
{
|
||||
size_t needed_workspace_size
|
||||
= (parser->object_workspace_current + size);
|
||||
size_t new_workspace_size = parser->object_workspace_size;
|
||||
while (new_workspace_size < needed_workspace_size)
|
||||
{
|
||||
if (ckd_mul (&new_workspace_size, new_workspace_size, 2))
|
||||
{
|
||||
json_signal_error (parser, Qjson_out_of_memory);
|
||||
}
|
||||
}
|
||||
|
||||
Lisp_Object *new_workspace_ptr;
|
||||
if (parser->object_workspace_size
|
||||
== JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE)
|
||||
{
|
||||
new_workspace_ptr
|
||||
= xnmalloc (new_workspace_size, sizeof (Lisp_Object));
|
||||
memcpy (new_workspace_ptr, parser->object_workspace,
|
||||
(sizeof (Lisp_Object)
|
||||
* parser->object_workspace_current));
|
||||
}
|
||||
else
|
||||
{
|
||||
new_workspace_ptr
|
||||
= xnrealloc (parser->object_workspace, new_workspace_size,
|
||||
sizeof (Lisp_Object));
|
||||
}
|
||||
|
||||
bool internal = (parser->object_workspace_size
|
||||
== JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE);
|
||||
ptrdiff_t new_workspace_size = parser->object_workspace_size;
|
||||
Lisp_Object *new_workspace_ptr
|
||||
= xpalloc (internal ? NULL : parser->object_workspace,
|
||||
&new_workspace_size,
|
||||
size - (parser->object_workspace_size
|
||||
- parser->object_workspace_current),
|
||||
-1, sizeof (Lisp_Object));
|
||||
if (internal)
|
||||
memcpy (new_workspace_ptr, parser->object_workspace,
|
||||
sizeof (Lisp_Object) * parser->object_workspace_current);
|
||||
parser->object_workspace = new_workspace_ptr;
|
||||
parser->object_workspace_size = new_workspace_size;
|
||||
}
|
||||
|
|
@ -854,33 +836,23 @@ json_byte_workspace_reset (struct json_parser *parser)
|
|||
parser->byte_workspace_current = parser->byte_workspace;
|
||||
}
|
||||
|
||||
/* Puts 'value' into the byte_workspace. If there is no space
|
||||
available, it allocates space */
|
||||
/* Put VALUE into the byte_workspace, allocating space. */
|
||||
NO_INLINE static void
|
||||
json_byte_workspace_put_slow_path (struct json_parser *parser,
|
||||
unsigned char value)
|
||||
{
|
||||
size_t new_workspace_size
|
||||
ptrdiff_t new_workspace_size
|
||||
= parser->byte_workspace_end - parser->byte_workspace;
|
||||
if (ckd_mul (&new_workspace_size, new_workspace_size, 2))
|
||||
{
|
||||
json_signal_error (parser, Qjson_out_of_memory);
|
||||
}
|
||||
|
||||
size_t offset
|
||||
ptrdiff_t offset
|
||||
= parser->byte_workspace_current - parser->byte_workspace;
|
||||
|
||||
if (parser->byte_workspace == parser->internal_byte_workspace)
|
||||
{
|
||||
parser->byte_workspace = xmalloc (new_workspace_size);
|
||||
memcpy (parser->byte_workspace, parser->internal_byte_workspace,
|
||||
offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
parser->byte_workspace
|
||||
= xrealloc (parser->byte_workspace, new_workspace_size);
|
||||
}
|
||||
bool internal = parser->byte_workspace == parser->internal_byte_workspace;
|
||||
unsigned char *new
|
||||
= xpalloc (internal ? NULL : parser->byte_workspace,
|
||||
&new_workspace_size, 1, -1, 1);
|
||||
if (internal)
|
||||
memcpy (new, parser->byte_workspace, offset);
|
||||
parser->byte_workspace = new;
|
||||
parser->byte_workspace_end
|
||||
= parser->byte_workspace + new_workspace_size;
|
||||
parser->byte_workspace_current = parser->byte_workspace + offset;
|
||||
|
|
|
|||
Loading…
Reference in a new issue