diff --git a/glibc-rh1307234-1.patch b/glibc-rh1307234-1.patch new file mode 100644 index 0000000..ae6b62c --- /dev/null +++ b/glibc-rh1307234-1.patch @@ -0,0 +1,453 @@ +commit 985fc132f23dbb83de76c5af9e783ef1b5900148 +Author: Florian Weimer +Date: Mon Apr 4 15:18:13 2016 +0200 + + strfmon_l: Use specified locale for number formatting [BZ #19633] + +Index: b/include/printf.h +=================================================================== +--- a/include/printf.h ++++ b/include/printf.h +@@ -1,6 +1,7 @@ + #ifndef _PRINTF_H + + #include ++#include + + /* Now define the internal interfaces. */ + extern int __printf_fphex (FILE *, const struct printf_info *, +@@ -8,5 +9,8 @@ extern int __printf_fphex (FILE *, const + extern int __printf_fp (FILE *, const struct printf_info *, + const void *const *); + libc_hidden_proto (__printf_fp) ++extern int __printf_fp_l (FILE *, locale_t, const struct printf_info *, ++ const void *const *); ++libc_hidden_proto (__printf_fp_l) + + #endif +Index: b/locale/localeinfo.h +=================================================================== +--- a/locale/localeinfo.h ++++ b/locale/localeinfo.h +@@ -299,6 +299,27 @@ extern __thread struct __locale_data *co + + #endif + ++/* Extract CATEGORY locale's string for ITEM. */ ++static inline const char * ++_nl_lookup (locale_t l, int category, int item) ++{ ++ return l->__locales[category]->values[_NL_ITEM_INDEX (item)].string; ++} ++ ++/* Extract CATEGORY locale's wide string for ITEM. */ ++static inline const wchar_t * ++_nl_lookup_wstr (locale_t l, int category, int item) ++{ ++ return (wchar_t *) l->__locales[category] ++ ->values[_NL_ITEM_INDEX (item)].wstr; ++} ++ ++/* Extract the CATEGORY locale's word for ITEM. */ ++static inline uint32_t ++_nl_lookup_word (locale_t l, int category, int item) ++{ ++ return l->__locales[category]->values[_NL_ITEM_INDEX (item)].word; ++} + + /* Default search path if no LOCPATH environment variable. */ + extern const char _nl_default_locale_path[] attribute_hidden; +Index: b/stdio-common/printf_fp.c +=================================================================== +--- a/stdio-common/printf_fp.c ++++ b/stdio-common/printf_fp.c +@@ -209,9 +209,9 @@ hack_digit (struct hack_digit_param *p) + } + + int +-___printf_fp (FILE *fp, +- const struct printf_info *info, +- const void *const *args) ++___printf_fp_l (FILE *fp, locale_t loc, ++ const struct printf_info *info, ++ const void *const *args) + { + /* The floating-point value to output. */ + union +@@ -263,18 +263,19 @@ ___printf_fp (FILE *fp, + /* Figure out the decimal point character. */ + if (info->extra == 0) + { +- decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); +- decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); ++ decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT); ++ decimalwc = _nl_lookup_word ++ (loc, LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); + } + else + { +- decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT); ++ decimal = _nl_lookup (loc, LC_MONETARY, MON_DECIMAL_POINT); + if (*decimal == '\0') +- decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); +- decimalwc = _NL_CURRENT_WORD (LC_MONETARY, ++ decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT); ++ decimalwc = _nl_lookup_word (loc, LC_MONETARY, + _NL_MONETARY_DECIMAL_POINT_WC); + if (decimalwc == L'\0') +- decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, ++ decimalwc = _nl_lookup_word (loc, LC_NUMERIC, + _NL_NUMERIC_DECIMAL_POINT_WC); + } + /* The decimal point character must not be zero. */ +@@ -284,9 +285,9 @@ ___printf_fp (FILE *fp, + if (info->group) + { + if (info->extra == 0) +- grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); ++ grouping = _nl_lookup (loc, LC_NUMERIC, GROUPING); + else +- grouping = _NL_CURRENT (LC_MONETARY, MON_GROUPING); ++ grouping = _nl_lookup (loc, LC_MONETARY, MON_GROUPING); + + if (*grouping <= 0 || *grouping == CHAR_MAX) + grouping = NULL; +@@ -296,19 +297,20 @@ ___printf_fp (FILE *fp, + if (wide) + { + if (info->extra == 0) +- thousands_sepwc = +- _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC); ++ thousands_sepwc = _nl_lookup_word ++ (loc, LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC); + else + thousands_sepwc = +- _NL_CURRENT_WORD (LC_MONETARY, ++ _nl_lookup_word (loc, LC_MONETARY, + _NL_MONETARY_THOUSANDS_SEP_WC); + } + else + { + if (info->extra == 0) +- thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); ++ thousands_sep = _nl_lookup (loc, LC_NUMERIC, THOUSANDS_SEP); + else +- thousands_sep = _NL_CURRENT (LC_MONETARY, MON_THOUSANDS_SEP); ++ thousands_sep = _nl_lookup ++ (loc, LC_MONETARY, MON_THOUSANDS_SEP); + } + + if ((wide && thousands_sepwc == L'\0') +@@ -1174,9 +1176,11 @@ ___printf_fp (FILE *fp, + size_t decimal_len; + size_t thousands_sep_len; + wchar_t *copywc; +- size_t factor = (info->i18n +- ? _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX) +- : 1); ++ size_t factor; ++ if (info->i18n) ++ factor = _nl_lookup_word (loc, LC_CTYPE, _NL_CTYPE_MB_CUR_MAX); ++ else ++ factor = 1; + + decimal_len = strlen (decimal); + +@@ -1247,8 +1251,18 @@ ___printf_fp (FILE *fp, + } + return done; + } ++ldbl_hidden_def (___printf_fp_l, __printf_fp_l) ++ldbl_strong_alias (___printf_fp_l, __printf_fp_l) ++ ++int ++___printf_fp (FILE *fp, const struct printf_info *info, ++ const void *const *args) ++{ ++ return ___printf_fp_l (fp, _NL_CURRENT_LOCALE, info, args); ++} + ldbl_hidden_def (___printf_fp, __printf_fp) + ldbl_strong_alias (___printf_fp, __printf_fp) ++ + + /* Return the number of extra grouping characters that will be inserted + into a number with INTDIG_MAX integer digits. */ +Index: b/stdlib/Makefile +=================================================================== +--- a/stdlib/Makefile ++++ b/stdlib/Makefile +@@ -76,7 +76,7 @@ tests := tst-strtol tst-strtod testmb t + tst-secure-getenv tst-strtod-overflow tst-strtod-round \ + tst-tininess tst-strtod-underflow tst-tls-atexit \ + tst-setcontext3 tst-tls-atexit-nodelete \ +- tst-strtol-locale tst-strtod-nan-locale ++ tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l + tests-static := tst-secure-getenv + + modules-names = tst-tls-atexit-lib +@@ -125,7 +125,8 @@ include ../Rules + + ifeq ($(run-built-tests),yes) + LOCALES := cs_CZ.UTF-8 de_DE.UTF-8 en_US.ISO-8859-1 tr_TR.UTF-8 \ +- tr_TR.ISO-8859-9 ++ tr_TR.ISO-8859-9 tg_TJ.UTF-8 te_IN.UTF-8 bn_IN.UTF-8 \ ++ el_GR.UTF-8 + include ../gen-locales.mk + + $(objpfx)bug-strtod2.out: $(gen-locales) +@@ -136,6 +137,7 @@ $(objpfx)tst-strtod4.out: $(gen-locales) + $(objpfx)tst-strtod5.out: $(gen-locales) + $(objpfx)tst-strtol-locale.out: $(gen-locales) + $(objpfx)tst-strtod-nan-locale.out: $(gen-locales) ++$(objpfx)tst-strfmon_l.out: $(gen-locales) + endif + + # Testdir has to be named stdlib and needs to be writable +Index: b/stdlib/strfmon_l.c +=================================================================== +--- a/stdlib/strfmon_l.c ++++ b/stdlib/strfmon_l.c +@@ -68,9 +68,6 @@ + #define _NL_CURRENT(category, item) \ + (current->values[_NL_ITEM_INDEX (item)].string) + +-extern int __printf_fp (FILE *, const struct printf_info *, +- const void *const *); +-libc_hidden_proto (__printf_fp) + /* This function determines the number of digit groups in the output. + The definition is in printf_fp.c. */ + extern unsigned int __guess_grouping (unsigned int intdig_max, +@@ -532,7 +529,7 @@ __vstrfmon_l (char *s, size_t maxsize, _ + info.extra = 1; /* This means use values from LC_MONETARY. */ + + ptr = &fpnum; +- done = __printf_fp (&f._sbf._f, &info, &ptr); ++ done = __printf_fp_l (&f._sbf._f, loc, &info, &ptr); + if (done < 0) + return -1; + +Index: b/stdlib/tst-strfmon_l.c +=================================================================== +--- /dev/null ++++ b/stdlib/tst-strfmon_l.c +@@ -0,0 +1,220 @@ ++/* Test locale dependence of strfmon_l. ++ Copyright (C) 2016 Free Software Foundation, Inc. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static const char *const en_us_name = "en_US.ISO-8859-1"; ++ ++/* Locale value to be used by tests. */ ++static locale_t loc; ++static const char *loc_name; ++ ++/* Set the global locale to GLOBAL_NAME, and the locale referenced by ++ the loc variable above to LOCAL_NAME. */ ++static void ++init_loc (const char *global_name, const char *local_name) ++{ ++ loc = newlocale (LC_ALL_MASK, local_name, 0); ++ if (loc == 0) ++ { ++ printf ("error: newlocale (%s): %m\n", local_name); ++ abort (); ++ } ++ loc_name = local_name; ++ ++ if (setlocale (LC_ALL, global_name) == NULL) ++ { ++ printf ("error: setlocale (%s): %m\n", global_name); ++ abort (); ++ } ++} ++ ++/* Expected strings for a positive or negative value. */ ++struct testcase ++{ ++ const char *i; /* %i */ ++ const char *n; /* %n */ ++ const char *i_ungrouped; /* %^i */ ++ const char *n_ungrouped; /* %^n */ ++}; ++ ++/* Collected expected strings for both positive and negative ++ values. */ ++struct testcase_pair ++{ ++ struct testcase positive; /* 1234567.89 */ ++ struct testcase negative; /* -1234567.89 */ ++}; ++ ++static bool errors; ++ ++/* Test one value using the locale loc. */ ++static void ++test_one (const char *format, double value, const char *expected) ++{ ++ static char actual[64]; ++ int result = strfmon_l (actual, sizeof (actual), loc, format, value); ++ if (result < 0) ++ { ++ printf ("error: locale %s, format \"%s\", value %g: strfmon_l: %m\n", ++ loc_name, format, value); ++ errors = true; ++ } ++ else if (strcmp (actual, expected) != 0) ++ { ++ printf ("error: locale %s, format \"%s\", value %g: mismatch\n", ++ loc_name, format, value); ++ printf ("error: expected: \"%s\"\n", expected); ++ printf ("error: actual: \"%s\"\n", actual); ++ errors = true; ++ } ++} ++ ++static void ++test_pair (const struct testcase_pair *pair) ++{ ++ double positive = 1234567.89; ++ test_one ("%i", positive, pair->positive.i); ++ test_one ("%n", positive, pair->positive.n); ++ test_one ("%^i", positive, pair->positive.i_ungrouped); ++ test_one ("%^n", positive, pair->positive.n_ungrouped); ++ double negative = -1234567.89; ++ test_one ("%i", negative, pair->negative.i); ++ test_one ("%n", negative, pair->negative.n); ++ test_one ("%^i", negative, pair->negative.i_ungrouped); ++ test_one ("%^n", negative, pair->negative.n_ungrouped); ++} ++ ++static const struct testcase_pair en_us = ++ { ++ { ++ "USD 1,234,567.89", "$1,234,567.89", ++ "USD 1234567.89", "$1234567.89" ++ }, ++ { ++ "-USD 1,234,567.89", "-$1,234,567.89", ++ "-USD 1234567.89", "-$1234567.89" ++ } ++ }; ++ ++static void ++test_en_us (const char *other_name) ++{ ++ init_loc (other_name, en_us_name); ++ test_pair (&en_us); ++ freelocale (loc); ++} ++ ++struct locale_pair ++{ ++ const char *locale_name; ++ struct testcase_pair pair; ++}; ++ ++static const struct locale_pair tests[] = ++ { ++ { ++ "de_DE.UTF-8", ++ { ++ { ++ "1.234.567,89 EUR", "1.234.567,89 \u20ac", ++ "1234567,89 EUR", "1234567,89 \u20ac" ++ }, ++ { ++ "-1.234.567,89 EUR", "-1.234.567,89 \u20ac", ++ "-1234567,89 EUR", "-1234567,89 \u20ac" ++ } ++ }, ++ }, ++ { ++ "tg_TJ.UTF-8", ++ { ++ { ++ "1 234 567.89 TJS", "1 234 567.89 \u0440\u0443\u0431", ++ "1234567.89 TJS", "1234567.89 \u0440\u0443\u0431" ++ }, ++ { ++ "-1 234 567.89 TJS", "-1 234 567.89 \u0440\u0443\u0431", ++ "-1234567.89 TJS", "-1234567.89 \u0440\u0443\u0431" ++ } ++ } ++ }, ++ { ++ "te_IN.UTF-8", ++ { ++ { ++ "INR12,34,567.89", "\u20b912,34,567.89", ++ "INR1234567.89", "\u20b91234567.89" ++ }, ++ { ++ "-INR12,34,567.89", "-\u20b912,34,567.89", ++ "-INR1234567.89", "-\u20b91234567.89" ++ } ++ } ++ }, ++ { ++ "bn_IN.UTF-8", ++ { ++ { ++ "INR 12,345,67.89", "\u20b9 12,345,67.89", ++ "INR 1234567.89", "\u20b9 1234567.89" ++ }, ++ { ++ "-INR 12,345,67.89", "-\u20b9 12,345,67.89", ++ "-INR 1234567.89", "-\u20b9 1234567.89" ++ } ++ } ++ }, ++ { ++ "el_GR.UTF-8", ++ { ++ { ++ "1.234.567,89EUR", "1.234.567,89\u20ac", ++ "1234567,89EUR", "1234567,89\u20ac" ++ }, ++ { ++ "-EUR1.234.567,89", "-\u20ac1.234.567,89", ++ "-EUR1234567,89", "-\u20ac1234567,89", ++ } ++ } ++ }, ++ {} ++ }; ++ ++static int ++do_test (void) ++{ ++ for (const struct locale_pair *test = tests; ++ test->locale_name != NULL; ++test) ++ { ++ init_loc (en_us_name, test->locale_name); ++ test_pair (&test->pair); ++ freelocale (loc); ++ test_en_us (test->locale_name); ++ } ++ ++ return errors; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" diff --git a/glibc-rh1307234-2.patch b/glibc-rh1307234-2.patch new file mode 100644 index 0000000..142063f --- /dev/null +++ b/glibc-rh1307234-2.patch @@ -0,0 +1,56 @@ +commit b1b8f5d89d06a994773e22ad4b7fe1036b37f8ab +Author: Stefan Liebler +Date: Thu Apr 14 12:21:53 2016 +0200 + + Fix strfmon_l: Use specified locale for number formatting [BZ #19633] + + The commit 985fc132f23dbb83de76c5af9e783ef1b5900148 + "strfmon_l: Use specified locale for number formatting [BZ #19633]" + introduced an elf/check-abi-libc testfailure due to __printf_fp_l + on architectures which use sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h. + + This patch uses libc_hidden_def instead of ldbl_hidden_def. + The ldbl_strong_alias is removed due to the rename of ___printf_fp_l + to __printf_fp_l. + + ChangeLog: + + * stdio-common/printf_fp.c (__printf_fp_l): + Rename ___printf_fp_l to __printf_fp_l and + remove strong alias. Use libc_hidden_def instead + of ldbl_hidden_def macro. + +Index: b/stdio-common/printf_fp.c +=================================================================== +--- a/stdio-common/printf_fp.c ++++ b/stdio-common/printf_fp.c +@@ -209,9 +209,9 @@ hack_digit (struct hack_digit_param *p) + } + + int +-___printf_fp_l (FILE *fp, locale_t loc, +- const struct printf_info *info, +- const void *const *args) ++__printf_fp_l (FILE *fp, locale_t loc, ++ const struct printf_info *info, ++ const void *const *args) + { + /* The floating-point value to output. */ + union +@@ -1251,14 +1251,13 @@ ___printf_fp_l (FILE *fp, locale_t loc, + } + return done; + } +-ldbl_hidden_def (___printf_fp_l, __printf_fp_l) +-ldbl_strong_alias (___printf_fp_l, __printf_fp_l) ++libc_hidden_def (__printf_fp_l) + + int + ___printf_fp (FILE *fp, const struct printf_info *info, + const void *const *args) + { +- return ___printf_fp_l (fp, _NL_CURRENT_LOCALE, info, args); ++ return __printf_fp_l (fp, _NL_CURRENT_LOCALE, info, args); + } + ldbl_hidden_def (___printf_fp, __printf_fp) + ldbl_strong_alias (___printf_fp, __printf_fp) diff --git a/glibc.spec b/glibc.spec index a66a858..bb23284 100644 --- a/glibc.spec +++ b/glibc.spec @@ -263,6 +263,8 @@ Patch1040: glibc-rh1300300.patch Patch1041: glibc-rh1300304-1.patch Patch1042: glibc-rh1300304-2.patch Patch1043: glibc-rh1300304-3.patch +Patch1044: glibc-rh1307234-1.patch +Patch1045: glibc-rh1307234-2.patch ############################################################################## # @@ -725,6 +727,8 @@ microbenchmark tests on the system. %patch1041 -p1 %patch1042 -p1 %patch1043 -p1 +%patch1044 -p1 +%patch1045 -p1 %patch0059 -p1 ############################################################################## @@ -1952,6 +1956,7 @@ rm -f *.filelist* - Fix invalid memory access in getmntent_r (#1293139) - CVE-2015-8776: crash with invalid data in strftime (#1300300) - CVE-2015-8778: integer overflow in hcreate and hcreate_r (#1300304) +- Fix strfmon_l to use the locale object for grouping (#1307234) * Fri May 6 2016 Florian Weimer - 2.22-14 - Fix getnameinfo memory leak and incorrect truncation (#1333901)