mirror of
https://github.com/json-c/json-c.git
synced 2026-11-09 23:40:14 +08:00
json_object: fix double format use-after-free on strdup failure
json_c_set_serialization_double_format() freed the current format string before strdup() of its replacement. In the GLOBAL branch the freed pointer was not reset on the strdup() failure path, leaving it dangling: a later serialization read through the dangling pointer, and a subsequent set(NULL) call freed it a second time. The THREAD branch reset its pointer to NULL right after the free, so it had no dangling pointer; its only defect was that a strdup() failure silently dropped the configured thread-local format and fell back to the global format. strdup() the new format first and replace the old one only once it succeeds, so a failure leaves both the global and thread-local format exactly as they were before the call. Fixes #997.
This commit is contained in:
1 parent
7f4196213a
commit
0f8fe5dd53
1 file changed
+19
-22
+19
-22
@@ -1195,6 +1195,23 @@ int json_c_set_serialization_double_format(const char *double_format, int global
|
||||
{
|
||||
if (global_or_thread == JSON_C_OPTION_GLOBAL)
|
||||
{
|
||||
if (double_format)
|
||||
{
|
||||
char *p = strdup(double_format);
|
||||
if (p == NULL)
|
||||
{
|
||||
_json_c_set_last_err("json_c_set_serialization_double_format: "
|
||||
"out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
free(global_serialization_float_format);
|
||||
global_serialization_float_format = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(global_serialization_float_format);
|
||||
global_serialization_float_format = NULL;
|
||||
}
|
||||
#if defined(HAVE___THREAD)
|
||||
if (tls_serialization_float_format)
|
||||
{
|
||||
@@ -1202,32 +1219,10 @@ int json_c_set_serialization_double_format(const char *double_format, int global
|
||||
tls_serialization_float_format = NULL;
|
||||
}
|
||||
#endif
|
||||
if (global_serialization_float_format)
|
||||
free(global_serialization_float_format);
|
||||
if (double_format)
|
||||
{
|
||||
char *p = strdup(double_format);
|
||||
if (p == NULL)
|
||||
{
|
||||
_json_c_set_last_err("json_c_set_serialization_double_format: "
|
||||
"out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
global_serialization_float_format = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
global_serialization_float_format = NULL;
|
||||
}
|
||||
}
|
||||
else if (global_or_thread == JSON_C_OPTION_THREAD)
|
||||
{
|
||||
#if defined(HAVE___THREAD)
|
||||
if (tls_serialization_float_format)
|
||||
{
|
||||
free(tls_serialization_float_format);
|
||||
tls_serialization_float_format = NULL;
|
||||
}
|
||||
if (double_format)
|
||||
{
|
||||
char *p = strdup(double_format);
|
||||
@@ -1237,10 +1232,12 @@ int json_c_set_serialization_double_format(const char *double_format, int global
|
||||
"out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
free(tls_serialization_float_format);
|
||||
tls_serialization_float_format = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(tls_serialization_float_format);
|
||||
tls_serialization_float_format = NULL;
|
||||
}
|
||||
#else
|
||||
|
||||
Reference in new issue
Block a user