diff options
author | Mark Johnston <markj@FreeBSD.org> | 2020-10-02 18:35:55 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2020-10-02 18:35:55 +0000 |
commit | afd95785c0b15302b2dc1bc0adfc21d58d0f2367 (patch) | |
tree | 32c6df89833a360072a614fcf0fe43bc587e46f2 /lib | |
parent | 1e145e73b8c939caf210c8992960c2d9d5a28d37 (diff) | |
download | src-afd95785c0b15302b2dc1bc0adfc21d58d0f2367.tar.gz src-afd95785c0b15302b2dc1bc0adfc21d58d0f2367.zip |
newlocale(3): Fix a memory leak.
newlocale() optionally takes a "base" locale, from which components not
specified in the mask are inherited. POSIX says that newlocale() may
modify "base" and return it, or free "base" and return a newly allocated
locale. We were not doing either, so applications which use newlocale()
to modify an existing base locale end up leaking memory on FreeBSD.
This diff fixes the leak by releasing a reference to the base locale
before returning. This is less efficient than modifying "base"
directly, but is simpler for an initial bug fix. Also, update the man
page to clarify behaviour with respect to "base".
PR: 249416
MFC after: 3 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D26522
Notes
Notes:
svn path=/head/; revision=366375
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/locale/newlocale.3 | 17 | ||||
-rw-r--r-- | lib/libc/locale/xlocale.c | 4 |
2 files changed, 19 insertions, 2 deletions
diff --git a/lib/libc/locale/newlocale.3 b/lib/libc/locale/newlocale.3 index c7414be73d3a..cc5043df8eb1 100644 --- a/lib/libc/locale/newlocale.3 +++ b/lib/libc/locale/newlocale.3 @@ -26,7 +26,7 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.Dd September 17, 2011 +.Dd October 2, 2020 .Dt NEWLOCALE 3 .Os .Sh NAME @@ -46,7 +46,20 @@ defines the components that the new locale will have set to the locale with the name specified in the .Fa locale parameter. -Any other components will be inherited from +Any components not specified in +.Fa mask +will be inherited from the locale referenced by +.Fa base , +if +.Fa base +is not +.Dv NULL . +If the call is successful, the state of the locale referenced by +.Fa base +is unspecified, and it must not be accessed. +The special locale +.Dv LC_GLOBAL_LOCALE +may not be specified for .Fa base . The .Fa mask diff --git a/lib/libc/locale/xlocale.c b/lib/libc/locale/xlocale.c index c1995179463e..465172fe24eb 100644 --- a/lib/libc/locale/xlocale.c +++ b/lib/libc/locale/xlocale.c @@ -251,6 +251,7 @@ static int dupcomponent(int type, locale_t base, locale_t new) locale_t newlocale(int mask, const char *locale, locale_t base) { + locale_t orig_base; int type; const char *realLocale = locale; int useenv = 0; @@ -263,6 +264,7 @@ locale_t newlocale(int mask, const char *locale, locale_t base) return (NULL); } + orig_base = base; FIX_LOCALE(base); copyflags(new, base); @@ -297,6 +299,8 @@ locale_t newlocale(int mask, const char *locale, locale_t base) if (0 == success) { xlocale_release(new); new = NULL; + } else if (base == orig_base) { + xlocale_release(base); } return (new); |