From 1d2c9e3786e4d6af0faf5aa8f4f78e89727a322878171718d19f26d3a7de7ac6 Mon Sep 17 00:00:00 2001 From: Dominique Leuenberger Date: Fri, 2 Oct 2015 07:23:13 +0000 Subject: [PATCH] Accepting request 334939 from Base:System - nss-files-long-lines-2.patch: Properly reread entry after failure in nss_files getent function (bsc#945779, BZ #18991) (forwarded request 334938 from Andreas_Schwab) OBS-URL: https://build.opensuse.org/request/show/334939 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/glibc?expand=0&rev=195 --- fnmatch-collating-elements.patch | 484 +++++++++++++++++++++++++++++++ glibc-testsuite.changes | 12 + glibc-testsuite.spec | 6 + glibc-utils.changes | 12 + glibc-utils.spec | 6 + glibc.changes | 12 + glibc.spec | 6 + nss-files-long-lines-2.patch | 164 +++++++++++ 8 files changed, 702 insertions(+) create mode 100644 fnmatch-collating-elements.patch create mode 100644 nss-files-long-lines-2.patch diff --git a/fnmatch-collating-elements.patch b/fnmatch-collating-elements.patch new file mode 100644 index 0000000..3000d7e --- /dev/null +++ b/fnmatch-collating-elements.patch @@ -0,0 +1,484 @@ +Fix fnmatch handling of collating elements (BZ #17396, BZ #16976) + + [BZ #16976] + [BZ #17396] + * posix/fnmatch_loop.c (internal_fnmatch, internal_fnwmatch): When + looking up collating elements match against (wide) character + sequence instead of name. Correct alignment adjustment. + * posix/fnmatch.c: Don't include "../locale/elem-hash.h". + * posix/Makefile (tests): Add tst-fnmatch4 and tst-fnmatch5. + * posix/tst-fnmatch4.c: New file. + * posix/tst-fnmatch5.c: New file. + + * Makefile (LOCALES): Add es_US.UTF-8 and es_US.ISO-8859-1. + +Index: glibc-2.22/localedata/Makefile +=================================================================== +--- glibc-2.22.orig/localedata/Makefile ++++ glibc-2.22/localedata/Makefile +@@ -106,7 +106,7 @@ LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 + hr_HR.ISO-8859-2 sv_SE.ISO-8859-1 ja_JP.SJIS fr_FR.ISO-8859-1 \ + nb_NO.ISO-8859-1 nn_NO.ISO-8859-1 tr_TR.UTF-8 cs_CZ.UTF-8 \ + zh_TW.EUC-TW fa_IR.UTF-8 fr_FR.UTF-8 ja_JP.UTF-8 si_LK.UTF-8 \ +- tr_TR.ISO-8859-9 en_GB.UTF-8 uk_UA.UTF-8 ++ tr_TR.ISO-8859-9 en_GB.UTF-8 uk_UA.UTF-8 es_US.UTF-8 es_US.ISO-8859-1 + include ../gen-locales.mk + endif + +Index: glibc-2.22/posix/Makefile +=================================================================== +--- glibc-2.22.orig/posix/Makefile ++++ glibc-2.22/posix/Makefile +@@ -87,7 +87,8 @@ tests := tstgetopt testfnm runtests run + bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \ + bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \ + tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \ +- tst-fnmatch3 bug-regex36 tst-getaddrinfo5 ++ tst-fnmatch3 bug-regex36 tst-fnmatch4 tst-fnmatch5 \ ++ tst-getaddrinfo5 + xtests := bug-ga2 + ifeq (yes,$(build-shared)) + test-srcs := globtest +Index: glibc-2.22/posix/fnmatch.c +=================================================================== +--- glibc-2.22.orig/posix/fnmatch.c ++++ glibc-2.22/posix/fnmatch.c +@@ -53,7 +53,6 @@ + we support a correct implementation only in glibc. */ + #ifdef _LIBC + # include "../locale/localeinfo.h" +-# include "../locale/elem-hash.h" + # include "../locale/coll-lookup.h" + # include + +Index: glibc-2.22/posix/fnmatch_loop.c +=================================================================== +--- glibc-2.22.orig/posix/fnmatch_loop.c ++++ glibc-2.22/posix/fnmatch_loop.c +@@ -503,26 +503,12 @@ FCT (pattern, string, string_end, no_lea + { + int32_t table_size; + const int32_t *symb_table; +-# if WIDE_CHAR_VERSION +- char str[c1]; +- unsigned int strcnt; +-# else +-# define str (startp + 1) +-# endif + const unsigned char *extra; + int32_t idx; + int32_t elem; +- int32_t second; +- int32_t hash; +- + # if WIDE_CHAR_VERSION +- /* We have to convert the name to a single-byte +- string. This is possible since the names +- consist of ASCII characters and the internal +- representation is UCS4. */ +- for (strcnt = 0; strcnt < c1; ++strcnt) +- str[strcnt] = startp[1 + strcnt]; +-#endif ++ int32_t *wextra; ++# endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, +@@ -534,71 +520,55 @@ FCT (pattern, string, string_end, no_lea + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + +- /* Locate the character in the hashing table. */ +- hash = elem_hash (str, c1); +- +- idx = 0; +- elem = hash % table_size; +- if (symb_table[2 * elem] != 0) +- { +- second = hash % (table_size - 2) + 1; +- +- do +- { +- /* First compare the hashing value. */ +- if (symb_table[2 * elem] == hash +- && (c1 +- == extra[symb_table[2 * elem + 1]]) +- && memcmp (str, +- &extra[symb_table[2 * elem +- + 1] +- + 1], c1) == 0) +- { +- /* Yep, this is the entry. */ +- idx = symb_table[2 * elem + 1]; +- idx += 1 + extra[idx]; +- break; +- } +- +- /* Next entry. */ +- elem += second; +- } +- while (symb_table[2 * elem] != 0); +- } ++ for (elem = 0; elem < table_size; elem++) ++ if (symb_table[2 * elem] != 0) ++ { ++ idx = symb_table[2 * elem + 1]; ++ /* Skip the name of collating element. */ ++ idx += 1 + extra[idx]; ++# if WIDE_CHAR_VERSION ++ /* Skip the byte sequence of the ++ collating element. */ ++ idx += 1 + extra[idx]; ++ /* Adjust for the alignment. */ ++ idx = (idx + 3) & ~3; ++ ++ wextra = (int32_t *) &extra[idx + 4]; ++ ++ if (/* Compare the length of the sequence. */ ++ c1 == wextra[0] ++ /* Compare the wide char sequence. */ ++ && memcmp (startp + 1, &wextra[1], ++ c1 * sizeof (UCHAR)) == 0) ++ /* Yep, this is the entry. */ ++ break; ++# else ++ if (/* Compare the length of the sequence. */ ++ c1 == extra[idx] ++ /* Compare the byte sequence. */ ++ && memcmp (startp + 1, ++ &extra[idx + 1], c1) == 0) ++ /* Yep, this is the entry. */ ++ break; ++# endif ++ } + +- if (symb_table[2 * elem] != 0) ++ if (elem < table_size) + { + /* Compare the byte sequence but only if + this is not part of a range. */ +-# if WIDE_CHAR_VERSION +- int32_t *wextra; ++ if (! is_range + +- idx += 1 + extra[idx]; +- /* Adjust for the alignment. */ +- idx = (idx + 3) & ~3; +- +- wextra = (int32_t *) &extra[idx + 4]; +-# endif +- +- if (! is_range) +- { + # if WIDE_CHAR_VERSION +- for (c1 = 0; +- (int32_t) c1 < wextra[idx]; +- ++c1) +- if (n[c1] != wextra[1 + c1]) +- break; +- +- if ((int32_t) c1 == wextra[idx]) +- goto matched; ++ && memcmp (n, &wextra[1], ++ c1 * sizeof (UCHAR)) == 0 + # else +- for (c1 = 0; c1 < extra[idx]; ++c1) +- if (n[c1] != extra[1 + c1]) +- break; +- +- if (c1 == extra[idx]) +- goto matched; ++ && memcmp (n, &extra[idx + 1], c1) == 0 + # endif ++ ) ++ { ++ n += c1 - 1; ++ goto matched; + } + + /* Get the collation sequence value. */ +@@ -606,9 +576,9 @@ FCT (pattern, string, string_end, no_lea + # if WIDE_CHAR_VERSION + cold = wextra[1 + wextra[idx]]; + # else +- /* Adjust for the alignment. */ + idx += 1 + extra[idx]; +- idx = (idx + 3) & ~4; ++ /* Adjust for the alignment. */ ++ idx = (idx + 3) & ~3; + cold = *((int32_t *) &extra[idx]); + # endif + +@@ -618,10 +588,10 @@ FCT (pattern, string, string_end, no_lea + { + /* No valid character. Match it as a + single byte. */ +- if (!is_range && *n == str[0]) ++ if (!is_range && *n == startp[1]) + goto matched; + +- cold = str[0]; ++ cold = startp[1]; + c = *p++; + } + else +@@ -629,7 +599,6 @@ FCT (pattern, string, string_end, no_lea + } + } + else +-# undef str + #endif + { + c = FOLD (c); +@@ -721,25 +690,11 @@ FCT (pattern, string, string_end, no_lea + { + int32_t table_size; + const int32_t *symb_table; +-# if WIDE_CHAR_VERSION +- char str[c1]; +- unsigned int strcnt; +-# else +-# define str (startp + 1) +-# endif + const unsigned char *extra; + int32_t idx; + int32_t elem; +- int32_t second; +- int32_t hash; +- + # if WIDE_CHAR_VERSION +- /* We have to convert the name to a single-byte +- string. This is possible since the names +- consist of ASCII characters and the internal +- representation is UCS4. */ +- for (strcnt = 0; strcnt < c1; ++strcnt) +- str[strcnt] = startp[1 + strcnt]; ++ int32_t *wextra; + # endif + + table_size = +@@ -752,51 +707,44 @@ FCT (pattern, string, string_end, no_lea + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + +- /* Locate the character in the hashing +- table. */ +- hash = elem_hash (str, c1); +- +- idx = 0; +- elem = hash % table_size; +- if (symb_table[2 * elem] != 0) +- { +- second = hash % (table_size - 2) + 1; +- +- do +- { +- /* First compare the hashing value. */ +- if (symb_table[2 * elem] == hash +- && (c1 +- == extra[symb_table[2 * elem + 1]]) +- && memcmp (str, +- &extra[symb_table[2 * elem + 1] +- + 1], c1) == 0) +- { +- /* Yep, this is the entry. */ +- idx = symb_table[2 * elem + 1]; +- idx += 1 + extra[idx]; +- break; +- } +- +- /* Next entry. */ +- elem += second; +- } +- while (symb_table[2 * elem] != 0); +- } +- +- if (symb_table[2 * elem] != 0) +- { +- /* Compare the byte sequence but only if +- this is not part of a range. */ ++ for (elem = 0; elem < table_size; elem++) ++ if (symb_table[2 * elem] != 0) ++ { ++ idx = symb_table[2 * elem + 1]; ++ /* Skip the name of collating ++ element. */ ++ idx += 1 + extra[idx]; + # if WIDE_CHAR_VERSION +- int32_t *wextra; +- +- idx += 1 + extra[idx]; +- /* Adjust for the alignment. */ +- idx = (idx + 3) & ~4; +- +- wextra = (int32_t *) &extra[idx + 4]; ++ /* Skip the byte sequence of the ++ collating element. */ ++ idx += 1 + extra[idx]; ++ /* Adjust for the alignment. */ ++ idx = (idx + 3) & ~3; ++ ++ wextra = (int32_t *) &extra[idx + 4]; ++ ++ if (/* Compare the length of the ++ sequence. */ ++ c1 == wextra[0] ++ /* Compare the wide char sequence. */ ++ && memcmp (startp + 1, &wextra[1], ++ c1 * sizeof (int32_t)) == 0) ++ /* Yep, this is the entry. */ ++ break; ++# else ++ if (/* Compare the length of the ++ sequence. */ ++ c1 == extra[idx] ++ /* Compare the byte sequence. */ ++ && memcmp (startp + 1, ++ &extra[idx + 1], c1) == 0) ++ /* Yep, this is the entry. */ ++ break; + # endif ++ } ++ ++ if (elem < table_size) ++ { + /* Get the collation sequence value. */ + is_seqval = 1; + # if WIDE_CHAR_VERSION +@@ -804,19 +752,18 @@ FCT (pattern, string, string_end, no_lea + # else + /* Adjust for the alignment. */ + idx += 1 + extra[idx]; +- idx = (idx + 3) & ~4; ++ idx = (idx + 3) & ~3; + cend = *((int32_t *) &extra[idx]); + # endif + } +- else if (symb_table[2 * elem] != 0 && c1 == 1) ++ else if (c1 == 1) + { +- cend = str[0]; ++ cend = startp[1]; + c = *p++; + } + else + return FNM_NOMATCH; + } +-# undef str + } + else + { +Index: glibc-2.22/posix/tst-fnmatch4.c +=================================================================== +--- /dev/null ++++ glibc-2.22/posix/tst-fnmatch4.c +@@ -0,0 +1,51 @@ ++/* Test for fnmatch handling of collating elements ++ Copyright (C) 2015 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 ++ ++static int ++do_test_locale (const char *locale) ++{ ++ const char *pattern = "[[.ll.]]"; ++ ++ if (setlocale (LC_ALL, locale) == NULL) ++ { ++ printf ("could not set locale %s\n", locale); ++ return 1; ++ } ++ ++ if (fnmatch (pattern, "ll", 0) != 0) ++ { ++ printf ("%s didn't match in locale %s\n", pattern, locale); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ++do_test (void) ++{ ++ return (do_test_locale ("es_US.ISO-8859-1") ++ || do_test_locale ("es_US.UTF-8")); ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" +Index: glibc-2.22/posix/tst-fnmatch5.c +=================================================================== +--- /dev/null ++++ glibc-2.22/posix/tst-fnmatch5.c +@@ -0,0 +1,53 @@ ++/* Test for fnmatch handling of collating elements ++ Copyright (C) 2015 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 ++ ++#define LENGTH 20000000 ++ ++char pattern[LENGTH + 7]; ++ ++static int ++do_test (void) ++{ ++ if (setlocale (LC_ALL, "en_US.UTF-8") == NULL) ++ { ++ puts ("could not set locale"); ++ return 1; ++ } ++ pattern[0] = '['; ++ pattern[1] = '['; ++ pattern[2] = '.'; ++ memset (pattern + 3, 'a', LENGTH); ++ pattern[LENGTH + 3] = '.'; ++ pattern[LENGTH + 4] = ']'; ++ pattern[LENGTH + 5] = ']'; ++ int ret = fnmatch (pattern, "a", 0); ++ if (ret == 0) ++ { ++ puts ("fnmatch returned 0 for invalid pattern"); ++ return 1; ++ } ++ return 0; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" diff --git a/glibc-testsuite.changes b/glibc-testsuite.changes index 6b4d233..df4e7ef 100644 --- a/glibc-testsuite.changes +++ b/glibc-testsuite.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Thu Sep 24 09:41:13 UTC 2015 - schwab@suse.de + +- nss-files-long-lines-2.patch: Properly reread entry after failure in + nss_files getent function (bsc#945779, BZ #18991) + +------------------------------------------------------------------- +Wed Sep 16 10:21:43 UTC 2015 - schwab@suse.de + +- fnmatch-collating-elements.patch: Fix fnmatch handling of collating + elements (BZ #17396, BZ #16976) + ------------------------------------------------------------------- Mon Sep 7 13:27:58 UTC 2015 - schwab@suse.de diff --git a/glibc-testsuite.spec b/glibc-testsuite.spec index 68a89ba..022d1cf 100644 --- a/glibc-testsuite.spec +++ b/glibc-testsuite.spec @@ -254,6 +254,10 @@ Patch2005: glibc-memset-nontemporal.diff Patch2006: ibm93x-redundant-shift-si.patch # PATCH-FIX-UPSTREAM Static dlopen default library search path fix (BZ #17250) Patch2007: static-dlopen.patch +# PATCH-FIX-UPSTREAM Fix fnmatch handling of collating elements (BZ #17396, BZ #16976) +Patch2008: fnmatch-collating-elements.patch +# PATCH-FIX-UPSTREAM Properly reread entry after failure in nss_files getent function (BZ #18991) +Patch2009: nss-files-long-lines-2.patch # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -464,6 +468,8 @@ rm nscd/s-stamp %patch2005 -p1 %patch2006 -p1 %patch2007 -p1 +%patch2008 -p1 +%patch2009 -p1 %patch3000 diff --git a/glibc-utils.changes b/glibc-utils.changes index 6b4d233..df4e7ef 100644 --- a/glibc-utils.changes +++ b/glibc-utils.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Thu Sep 24 09:41:13 UTC 2015 - schwab@suse.de + +- nss-files-long-lines-2.patch: Properly reread entry after failure in + nss_files getent function (bsc#945779, BZ #18991) + +------------------------------------------------------------------- +Wed Sep 16 10:21:43 UTC 2015 - schwab@suse.de + +- fnmatch-collating-elements.patch: Fix fnmatch handling of collating + elements (BZ #17396, BZ #16976) + ------------------------------------------------------------------- Mon Sep 7 13:27:58 UTC 2015 - schwab@suse.de diff --git a/glibc-utils.spec b/glibc-utils.spec index b89b3a2..e17d5fe 100644 --- a/glibc-utils.spec +++ b/glibc-utils.spec @@ -253,6 +253,10 @@ Patch2005: glibc-memset-nontemporal.diff Patch2006: ibm93x-redundant-shift-si.patch # PATCH-FIX-UPSTREAM Static dlopen default library search path fix (BZ #17250) Patch2007: static-dlopen.patch +# PATCH-FIX-UPSTREAM Fix fnmatch handling of collating elements (BZ #17396, BZ #16976) +Patch2008: fnmatch-collating-elements.patch +# PATCH-FIX-UPSTREAM Properly reread entry after failure in nss_files getent function (BZ #18991) +Patch2009: nss-files-long-lines-2.patch # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -464,6 +468,8 @@ rm nscd/s-stamp %patch2005 -p1 %patch2006 -p1 %patch2007 -p1 +%patch2008 -p1 +%patch2009 -p1 %patch3000 diff --git a/glibc.changes b/glibc.changes index 6b4d233..df4e7ef 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Thu Sep 24 09:41:13 UTC 2015 - schwab@suse.de + +- nss-files-long-lines-2.patch: Properly reread entry after failure in + nss_files getent function (bsc#945779, BZ #18991) + +------------------------------------------------------------------- +Wed Sep 16 10:21:43 UTC 2015 - schwab@suse.de + +- fnmatch-collating-elements.patch: Fix fnmatch handling of collating + elements (BZ #17396, BZ #16976) + ------------------------------------------------------------------- Mon Sep 7 13:27:58 UTC 2015 - schwab@suse.de diff --git a/glibc.spec b/glibc.spec index e544dbb..ae68e2a 100644 --- a/glibc.spec +++ b/glibc.spec @@ -254,6 +254,10 @@ Patch2005: glibc-memset-nontemporal.diff Patch2006: ibm93x-redundant-shift-si.patch # PATCH-FIX-UPSTREAM Static dlopen default library search path fix (BZ #17250) Patch2007: static-dlopen.patch +# PATCH-FIX-UPSTREAM Fix fnmatch handling of collating elements (BZ #17396, BZ #16976) +Patch2008: fnmatch-collating-elements.patch +# PATCH-FIX-UPSTREAM Properly reread entry after failure in nss_files getent function (BZ #18991) +Patch2009: nss-files-long-lines-2.patch # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -464,6 +468,8 @@ rm nscd/s-stamp %patch2005 -p1 %patch2006 -p1 %patch2007 -p1 +%patch2008 -p1 +%patch2009 -p1 %patch3000 diff --git a/nss-files-long-lines-2.patch b/nss-files-long-lines-2.patch new file mode 100644 index 0000000..ec41f8a --- /dev/null +++ b/nss-files-long-lines-2.patch @@ -0,0 +1,164 @@ +Properly reread entry after failure in nss_files getent function (bug 18991) + + * nss/nss_files/files-XXX.c (position, need_reread): New + variables. + (CONCAT(_nss_files_set,ENTNAME)): Initialize them. + (CONCAT(_nss_files_get,ENTNAME_r)): Likewise. Reposition stream + if last call was uncessful. + * nss/nss_files/files-alias.c (position, need_reread): New + variables. + (_nss_files_setaliasent): Initialize them. + (_nss_files_getaliasent_r): Likewise. Reposition stream if last + call was uncessful. + +Index: glibc-2.19/nss/nss_files/files-XXX.c +=================================================================== +--- glibc-2.19.orig/nss/nss_files/files-XXX.c ++++ glibc-2.19/nss/nss_files/files-XXX.c +@@ -65,6 +65,10 @@ __libc_lock_define_initialized (static, + getXXbyYY operations all use their own stream. */ + + static FILE *stream; ++/* Position after the last sucessfully read entry. */ ++static fpos_t position; ++/* Whether we need to reread the last entry on the next call. */ ++static bool need_reread; + + /* Open database file if not already opened. */ + static enum nss_status +@@ -131,6 +135,15 @@ CONCAT(_nss_files_set,ENTNAME) (int stay + + status = internal_setent (&stream); + ++ if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0) ++ { ++ fclose (stream); ++ stream = NULL; ++ status = NSS_STATUS_UNAVAIL; ++ } ++ ++ need_reread = false; ++ + __libc_lock_unlock (lock); + + return status; +@@ -286,11 +299,42 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct + status = internal_setent (&stream); + + __set_errno (save_errno); ++ ++ if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0) ++ { ++ fclose (stream); ++ stream = NULL; ++ status = NSS_STATUS_UNAVAIL; ++ } ++ need_reread = false; + } + + if (status == NSS_STATUS_SUCCESS) +- status = internal_getent (stream, result, buffer, buflen, errnop +- H_ERRNO_ARG EXTRA_ARGS_VALUE); ++ { ++ /* Reposition the stream if the last call was unsucessful. */ ++ if (need_reread) ++ { ++ if (fsetpos (stream, &position) < 0) ++ status = NSS_STATUS_UNAVAIL; ++ else ++ need_reread = false; ++ } ++ } ++ ++ if (status == NSS_STATUS_SUCCESS) ++ { ++ status = internal_getent (stream, result, buffer, buflen, errnop ++ H_ERRNO_ARG EXTRA_ARGS_VALUE); ++ ++ /* Remember this position if we were successful. If the ++ operation failed we give the user a chance to repeat the ++ operation (perhaps the buffer was too small). */ ++ if (status == NSS_STATUS_SUCCESS) ++ fgetpos (stream, &position); ++ else ++ /* We must make sure we reposition the stream the next call. */ ++ need_reread = true; ++ } + + __libc_lock_unlock (lock); + +Index: glibc-2.19/nss/nss_files/files-alias.c +=================================================================== +--- glibc-2.19.orig/nss/nss_files/files-alias.c ++++ glibc-2.19/nss/nss_files/files-alias.c +@@ -38,6 +38,10 @@ __libc_lock_define_initialized (static, + getXXbyYY operations all use their own stream. */ + + static FILE *stream; ++/* Position after the last sucessfully read entry. */ ++static fpos_t position; ++/* Whether we need to reread the last entry on the next call. */ ++static bool need_reread; + + + static enum nss_status +@@ -104,6 +108,15 @@ _nss_files_setaliasent (void) + + status = internal_setent (&stream); + ++ if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0) ++ { ++ fclose (stream); ++ stream = NULL; ++ status = NSS_STATUS_UNAVAIL; ++ } ++ ++ need_reread = false; ++ + __libc_lock_unlock (lock); + + return status; +@@ -388,7 +401,29 @@ _nss_files_getaliasent_r (struct aliasen + + /* Be prepared that the set*ent function was not called before. */ + if (stream == NULL) +- status = internal_setent (&stream); ++ { ++ status = internal_setent (&stream); ++ ++ if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0) ++ { ++ fclose (stream); ++ stream = NULL; ++ status = NSS_STATUS_UNAVAIL; ++ } ++ need_reread = false; ++ } ++ ++ if (status == NSS_STATUS_SUCCESS) ++ { ++ /* Reposition the stream if the last call way unsucessful. */ ++ if (need_reread) ++ { ++ if (fsetpos (stream, &position) < 0) ++ status = NSS_STATUS_UNAVAIL; ++ else ++ need_reread = false; ++ } ++ } + + if (status == NSS_STATUS_SUCCESS) + { +@@ -398,6 +433,12 @@ _nss_files_getaliasent_r (struct aliasen + do + status = get_next_alias (stream, NULL, result, buffer, buflen, errnop); + while (status == NSS_STATUS_RETURN); ++ ++ /* If we successfully read an entry remember this position. */ ++ if (status == NSS_STATUS_SUCCESS) ++ fgetpos (stream, &position); ++ else ++ need_reread = true; + } + + __libc_lock_unlock (lock);