From: Bruno Haible Date: Sun, 24 Sep 2017 12:25:53 +0000 (+0200) Subject: Verify that system dependent strings in .mo files are NUL terminated. X-Git-Tag: v0.20~448 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=861745b3c53362925eaf3605a334565af378556c;p=thirdparty%2Fgettext.git Verify that system dependent strings in .mo files are NUL terminated. Reported by Jakub Wilk in . * gettext-runtime/intl/loadmsgcat.c (_nl_load_domain): Bail out if some of the system-dependent strings has a last static segment that is not NUL terminated. * gettext-tools/src/read-mo.c (get_sysdep_string): Likewise. --- diff --git a/gettext-runtime/intl/loadmsgcat.c b/gettext-runtime/intl/loadmsgcat.c index beb52a3ac..314d2393d 100644 --- a/gettext-runtime/intl/loadmsgcat.c +++ b/gettext-runtime/intl/loadmsgcat.c @@ -1039,19 +1039,26 @@ _nl_load_domain (struct loaded_l10nfile *domain_file, ? orig_sysdep_tab[i] : trans_sysdep_tab[i])); size_t need = 0; + const char *static_segments = + (char *) data + + W (domain->must_swap, sysdep_string->offset); const struct segment_pair *p = sysdep_string->segments; if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END) - for (p = sysdep_string->segments;; p++) + for (;; p++) { + nls_uint32 segsize; nls_uint32 sysdepref; - need += W (domain->must_swap, p->segsize); + segsize = W (domain->must_swap, p->segsize); + need += segsize; sysdepref = W (domain->must_swap, p->sysdepref); if (sysdepref == SEGMENTS_END) break; + static_segments += segsize; + if (sysdepref >= n_sysdep_segments) { /* Invalid. */ @@ -1063,12 +1070,25 @@ _nl_load_domain (struct loaded_l10nfile *domain_file, { /* This particular string pair is invalid. */ valid = 0; - break; } need += strlen (sysdep_segment_values[sysdepref]); } + /* The last static segment must end in a NUL. */ + { + nls_uint32 segsize = + W (domain->must_swap, p->segsize); + + if (!(segsize > 0 + && static_segments[segsize - 1] == '\0')) + { + /* Invalid. */ + freea (sysdep_segment_values); + goto invalid; + } + } + needs[j] = need; if (!valid) break; @@ -1122,7 +1142,7 @@ _nl_load_domain (struct loaded_l10nfile *domain_file, if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END) - for (p = sysdep_string->segments;; p++) + for (;; p++) { nls_uint32 sysdepref; @@ -1183,7 +1203,7 @@ _nl_load_domain (struct loaded_l10nfile *domain_file, { inmem_tab_entry->pointer = mem; - for (p = sysdep_string->segments;; p++) + for (;; p++) { nls_uint32 segsize = W (domain->must_swap, p->segsize); diff --git a/gettext-tools/src/read-mo.c b/gettext-tools/src/read-mo.c index 9ddd6b2d2..1745864a6 100644 --- a/gettext-tools/src/read-mo.c +++ b/gettext-tools/src/read-mo.c @@ -169,11 +169,19 @@ get_sysdep_string (const struct binary_mo_file *bfp, size_t offset, s_offset += segsize; if (sysdepref == SEGMENTS_END) - break; + { + /* The last static segment must end in a NUL. */ + if (!(segsize > 0 && bfp->data[s_offset - 1] == '\0')) + /* Invalid. */ + error (EXIT_FAILURE, 0, + _("file \"%s\" contains a not NUL terminated system dependent string"), + bfp->filename); + break; + } if (sysdepref >= header->n_sysdep_segments) /* Invalid. */ - error (EXIT_FAILURE, 0, _("file \"%s\" is not in GNU .mo format"), - bfp->filename); + error (EXIT_FAILURE, 0, _("file \"%s\" is not in GNU .mo format"), + bfp->filename); /* See 'struct sysdep_segment'. */ sysdep_segment_offset = header->sysdep_segments_offset + sysdepref * 8; ss_length = get_uint32 (bfp, sysdep_segment_offset);