mirror of
https://github.com/json-c/json-c.git
synced 2026-11-10 16:00: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 (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 defined(HAVE___THREAD)
|
||||||
if (tls_serialization_float_format)
|
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;
|
tls_serialization_float_format = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
else if (global_or_thread == JSON_C_OPTION_THREAD)
|
||||||
{
|
{
|
||||||
#if defined(HAVE___THREAD)
|
#if defined(HAVE___THREAD)
|
||||||
if (tls_serialization_float_format)
|
|
||||||
{
|
|
||||||
free(tls_serialization_float_format);
|
|
||||||
tls_serialization_float_format = NULL;
|
|
||||||
}
|
|
||||||
if (double_format)
|
if (double_format)
|
||||||
{
|
{
|
||||||
char *p = strdup(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");
|
"out of memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
free(tls_serialization_float_format);
|
||||||
tls_serialization_float_format = p;
|
tls_serialization_float_format = p;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
free(tls_serialization_float_format);
|
||||||
tls_serialization_float_format = NULL;
|
tls_serialization_float_format = NULL;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|||||||
Reference in new issue
Block a user