tst-C-locale \
tst-duplocale \
tst-locname \
+ tst-newlocale \
# tests
tests-container = \
tst-localedef-path-norm \
ifeq ($(run-built-tests),yes)
tests-special += $(objpfx)tst-locale-locpath.out
+ifeq ($(build-shared),yes)
+ifneq ($(PERL),no)
+generated += \
+ tst-newlocale.mtrace \
+ # generated
+tests-special += \
+ $(objpfx)tst-newlocale-mem.out \
+ # tests-special
+endif # $(PERL) == yes
+endif # $(build-shared) == yes
endif
include ../Rules
$(evaluate-test)
$(objpfx)tst-localedef-path-norm: $(shared-thread-library)
+
+LDLIBS-tst-newlocale = $(shared-thread-library)
+tst-newlocale-ENV = MALLOC_TRACE=$(objpfx)tst-newlocale.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+$(objpfx)tst-newlocale-mem.out: $(objpfx)tst-newlocale.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-newlocale.mtrace > $@; \
+ $(evaluate-test)
#include <locale.h>
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include "localeinfo.h"
} while (0)
-locale_t
-__newlocale (int category_mask, const char *locale, locale_t base)
+static locale_t
+__newlocale_1 (int category_mask, const char *locale, locale_t base,
+ char ** const locale_path_ptr)
{
/* Intermediate memory for result. */
const char *newnames[__LC_LAST];
struct __locale_struct result;
locale_t result_ptr;
- char *locale_path;
size_t locale_path_len;
const char *locpath_var;
int cnt;
size_t names_len;
+ *locale_path_ptr = NULL;
+
/* We treat LC_ALL in the same way as if all bits were set. */
if (category_mask == 1 << LC_ALL)
category_mask = (1 << __LC_LAST) - 1 - (1 << LC_ALL);
`LOCPATH' must only be used when the binary has no SUID or SGID
bit set. If using the default path, we tell _nl_find_locale
by passing null and it can check the canonical locale archive. */
- locale_path = NULL;
locale_path_len = 0;
locpath_var = getenv ("LOCPATH");
if (locpath_var != NULL && locpath_var[0] != '\0')
{
if (__argz_create_sep (locpath_var, ':',
- &locale_path, &locale_path_len) != 0)
+ locale_path_ptr, &locale_path_len) != 0)
return NULL;
- if (__argz_add_sep (&locale_path, &locale_path_len,
+ if (__argz_add_sep (locale_path_ptr, &locale_path_len,
_nl_default_locale_path, ':') != 0)
return NULL;
+
+ assert (*locale_path_ptr != NULL);
}
/* Get the names for the locales we are interested in. We either
{
if ((category_mask & 1 << cnt) != 0)
{
- result.__locales[cnt] = _nl_find_locale (locale_path,
+ result.__locales[cnt] = _nl_find_locale (*locale_path_ptr,
locale_path_len,
cnt, &newnames[cnt]);
if (result.__locales[cnt] == NULL)
return result_ptr;
}
+
+locale_t
+__newlocale (int category_mask, const char *locale, locale_t base)
+{
+ char *tmp_buffer = NULL;
+
+ const locale_t result = __newlocale_1 (category_mask, locale,
+ base, &tmp_buffer);
+
+ free (tmp_buffer);
+
+ return result;
+}
+
weak_alias (__newlocale, newlocale)
--- /dev/null
+/* This test checks a memory leak in newlocal function [BZ #25770].
+ Copyright The GNU Toolchain Authors.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <locale.h>
+
+static int
+do_test (void)
+{
+ mtrace ();
+
+ /* We can use an any valid path here.
+ If setenv fails, the next part of test should still run okay. */
+ TEST_COMPARE (setenv ("LOCPATH", ".", 1), 0);
+
+ {
+ locale_t const l = newlocale (1 << LC_CTYPE, "POSIX", NULL);
+ TEST_VERIFY_EXIT (l != NULL);
+
+ freelocale (l);
+ }
+
+ return 0;
+}
+
+#include <support/test-driver.c>