fix null pointer dereference in dcngettext under specific conditions
[musl] / src / locale / dcngettext.c
index 51e6522..30dd41d 100644 (file)
@@ -12,7 +12,7 @@
 struct binding {
        struct binding *next;
        int dirlen;
-       int active;
+       volatile int active;
        char *domainname;
        char *dirname;
        char buf[];
@@ -34,7 +34,7 @@ static char *gettextdir(const char *domainname, size_t *dirlen)
 
 char *bindtextdomain(const char *domainname, const char *dirname)
 {
-       static int lock[2];
+       static volatile int lock[2];
        struct binding *p, *q;
 
        if (!domainname) return 0;
@@ -96,8 +96,8 @@ struct msgcat {
        struct msgcat *next;
        const void *map;
        size_t map_size;
-       void *plural_rule;
-       int nplurals;
+       void *volatile plural_rule;
+       volatile int nplurals;
        char name[];
 };
 
@@ -132,7 +132,7 @@ char *dcngettext(const char *domainname, const char *msgid1, const char *msgid2,
        switch (category) {
        case LC_MESSAGES:
                locname = loc->messages_name;
-               if (!*locname) goto notrans;
+               if (!locname || !*locname) goto notrans;
                break;
        case LC_TIME:
        case LC_MONETARY:
@@ -229,8 +229,9 @@ notrans:
                unsigned long plural = __pleval(p->plural_rule, n);
                if (plural > p->nplurals) goto notrans;
                while (plural--) {
-                       size_t l = strlen(trans);
-                       if (l+1 >= p->map_size - (trans - (char *)p->map))
+                       size_t rem = p->map_size - (trans - (char *)p->map);
+                       size_t l = strnlen(trans, rem);
+                       if (l+1 >= rem)
                                goto notrans;
                        trans += l+1;
                }