mirror of
https://github.com/json-c/json-c.git
synced 2026-11-05 21:20:16 +08:00
Merge pull request #976 from sswamy48/AIX_memleak
AIX:Fix memory leak in json_tokener_parse_ex due to duplocale
This commit is contained in:
1 file changed
+34
-27
+34
-27
@@ -315,6 +315,15 @@ struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokene
|
|||||||
|
|
||||||
/* End optimization macro defs */
|
/* End optimization macro defs */
|
||||||
|
|
||||||
|
#ifdef HAVE_USELOCALE
|
||||||
|
/* One-time C-numeric locale, created on first call and reused forever.
|
||||||
|
* Avoids per-call duplocale() overhead and the memory leak seen on AIX
|
||||||
|
* where freelocale() does not release all locale category memory.
|
||||||
|
* Freed on library unload by json_tokener_locale_fini().
|
||||||
|
*/
|
||||||
|
static locale_t c_numeric_locale = (locale_t)0;
|
||||||
|
#endif /* HAVE_USELOCALE */
|
||||||
|
|
||||||
struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len)
|
struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len)
|
||||||
{
|
{
|
||||||
struct json_object *obj = NULL;
|
struct json_object *obj = NULL;
|
||||||
@@ -324,7 +333,6 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
|
|||||||
|
|
||||||
#ifdef HAVE_USELOCALE
|
#ifdef HAVE_USELOCALE
|
||||||
locale_t oldlocale = uselocale(NULL);
|
locale_t oldlocale = uselocale(NULL);
|
||||||
locale_t newloc;
|
|
||||||
#elif defined(HAVE_SETLOCALE)
|
#elif defined(HAVE_SETLOCALE)
|
||||||
char *oldlocale = NULL;
|
char *oldlocale = NULL;
|
||||||
#endif
|
#endif
|
||||||
@@ -346,33 +354,16 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
|
|||||||
|
|
||||||
#ifdef HAVE_USELOCALE
|
#ifdef HAVE_USELOCALE
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DUPLOCALE
|
if (c_numeric_locale == (locale_t)0)
|
||||||
locale_t duploc = duplocale(oldlocale);
|
|
||||||
if (duploc == NULL && errno == ENOMEM)
|
|
||||||
{
|
{
|
||||||
tok->err = json_tokener_error_memory;
|
c_numeric_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
|
||||||
return NULL;
|
if (c_numeric_locale == (locale_t)0)
|
||||||
|
{
|
||||||
|
tok->err = json_tokener_error_memory;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
|
uselocale(c_numeric_locale);
|
||||||
#else
|
|
||||||
newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
|
|
||||||
#endif
|
|
||||||
if (newloc == NULL)
|
|
||||||
{
|
|
||||||
tok->err = json_tokener_error_memory;
|
|
||||||
#ifdef HAVE_DUPLOCALE
|
|
||||||
freelocale(duploc);
|
|
||||||
#endif
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#ifdef NEWLOCALE_NEEDS_FREELOCALE
|
|
||||||
#ifdef HAVE_DUPLOCALE
|
|
||||||
// Older versions of FreeBSD (<12.4) don't free the locale
|
|
||||||
// passed to newlocale(), so do it here
|
|
||||||
freelocale(duploc);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
uselocale(newloc);
|
|
||||||
}
|
}
|
||||||
#elif defined(HAVE_SETLOCALE)
|
#elif defined(HAVE_SETLOCALE)
|
||||||
{
|
{
|
||||||
@@ -1410,7 +1401,6 @@ out:
|
|||||||
|
|
||||||
#ifdef HAVE_USELOCALE
|
#ifdef HAVE_USELOCALE
|
||||||
uselocale(oldlocale);
|
uselocale(oldlocale);
|
||||||
freelocale(newloc);
|
|
||||||
#elif defined(HAVE_SETLOCALE)
|
#elif defined(HAVE_SETLOCALE)
|
||||||
setlocale(LC_NUMERIC, oldlocale);
|
setlocale(LC_NUMERIC, oldlocale);
|
||||||
free(oldlocale);
|
free(oldlocale);
|
||||||
@@ -1477,3 +1467,20 @@ static int json_tokener_parse_double(const char *buf, int len, double *retval)
|
|||||||
return 0; // It worked
|
return 0; // It worked
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_USELOCALE
|
||||||
|
/* Release the static C-numeric locale when the library is unloaded.
|
||||||
|
* This keeps Valgrind clean.
|
||||||
|
*/
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
__attribute__((destructor))
|
||||||
|
static void json_tokener_locale_fini(void)
|
||||||
|
{
|
||||||
|
if (c_numeric_locale != (locale_t)0)
|
||||||
|
{
|
||||||
|
freelocale(c_numeric_locale);
|
||||||
|
c_numeric_locale = (locale_t)0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* __GNUC__ || __clang__ */
|
||||||
|
#endif /* HAVE_USELOCALE */
|
||||||
Reference in new issue
Block a user