harden mo file processing for locale/translations
authorRich Felker <dalias@aerifal.cx>
Tue, 29 Jul 2014 15:48:36 +0000 (11:48 -0400)
committerRich Felker <dalias@aerifal.cx>
Tue, 29 Jul 2014 15:48:36 +0000 (11:48 -0400)
rather than just checking that the start of the string lies within the
mapping, also check that the nominal length remains within the
mapping, and that the null terminator is present at the nominal
length. this ensures that the caller, using the result as a C string,
will not read past the end of the mapping.

the nominal length is never exposed to the caller, but it's useful
internally to find where the null terminator should be without having
to restort to linear search via strnlen/memchr.

src/locale/__mo_lookup.c

index 8112d91c441c08133c900a0682da4c1eb39d9d68..d18ab7744246bd286fbc8a67117c320a29169700 100644 (file)
@@ -18,12 +18,16 @@ const char *__mo_lookup(const void *p, size_t size, const char *s)
        o/=4;
        t/=4;
        for (;;) {
+               uint32_t ol = swapc(mo[o+2*(b+n/2)], sw);
                uint32_t os = swapc(mo[o+2*(b+n/2)+1], sw);
-               if (os >= size) return 0;
+               if (os >= size || ol >= size-os || ((char *)p)[os+ol])
+                       return 0;
                int sign = strcmp(s, (char *)p + os);
                if (!sign) {
+                       uint32_t tl = swapc(mo[t+2*(b+n/2)], sw);
                        uint32_t ts = swapc(mo[t+2*(b+n/2)+1], sw);
-                       if (ts >= size) return 0;
+                       if (ts >= size || tl >= size-ts || ((char *)p)[ts+tl])
+                               return 0;
                        return (char *)p + ts;
                }
                else if (n == 1) return 0;