locale: ensure dcngettext() preserves errno
authorA. Wilcox <AWilcox@Wilcox-Tech.com>
Mon, 28 Jan 2019 03:34:57 +0000 (21:34 -0600)
committerRich Felker <dalias@aerifal.cx>
Thu, 7 Feb 2019 17:41:16 +0000 (12:41 -0500)
Some packages call gettext to format a message to be sent to perror.
If the currently set user locale points to a non-existent .mo file,
open via __map_file in dcngettext will set errno to ENOENT.

Maintainer's notes: Non-modification of errno is a documented part of
the interface contract for the GNU version of this function and likely
other versions. The issue being fixed here seems to be a regression
from commit 1b52863e244ecee5b5935b6d36bb9e6efe84c035, which enabled
setting of errno from __map_file.

src/locale/dcngettext.c

index 8b891d0001d3da1e6550e2d71e43c3cfdd530bd8..4c30439389805224cb14910f09674b56a2177711 100644 (file)
@@ -122,6 +122,7 @@ char *dcngettext(const char *domainname, const char *msgid1, const char *msgid2,
        const struct __locale_map *lm;
        size_t domlen;
        struct binding *q;
+       int old_errno = errno;
 
        if ((unsigned)category >= LC_ALL) goto notrans;
 
@@ -138,6 +139,7 @@ char *dcngettext(const char *domainname, const char *msgid1, const char *msgid2,
        lm = loc->cat[category];
        if (!lm) {
 notrans:
+               errno = old_errno;
                return (char *) ((n == 1) ? msgid1 : msgid2);
        }
 
@@ -250,6 +252,7 @@ notrans:
                        trans += l+1;
                }
        }
+       errno = old_errno;
        return (char *)trans;
 }