aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2020-10-02 18:35:55 +0000
committerMark Johnston <markj@FreeBSD.org>2020-10-02 18:35:55 +0000
commitafd95785c0b15302b2dc1bc0adfc21d58d0f2367 (patch)
tree32c6df89833a360072a614fcf0fe43bc587e46f2 /lib
parent1e145e73b8c939caf210c8992960c2d9d5a28d37 (diff)
downloadsrc-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.317
-rw-r--r--lib/libc/locale/xlocale.c4
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);