[glibc] intl: Fix undefined pointer behaviour
Adhemerval Zanella via Glibc-cvs <[email protected]> Wed, 20 May 2026 20:22:48 +0000 (GMT)
| Newsgroups | gmane.comp.lib.glibc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=8aa4a704314e6039bf1efbc1d8d57bb095956862 commit 8aa4a704314e6039bf1efbc1d8d57bb095956862 Author: Avinal Kumar <[email protected]> Date: Mon May 18 15:44:52 2026 +0530 intl: Fix undefined pointer behaviour In _nl_find_msg (dcigettext.c), outbuf was computed as freemem + sizeof(size_t) before checking whether freemem_size is large enough. When freemem is NULL (initial state), this is undefined behaviour i.e arithmetic on a null pointer. Move the outbuf assignment after the size check where freemem is guaranteed to be a valid allocation. In read_alias_file (localealias.c), after realloc the old string_space pointer is dangling. The expression new_pool - string_space subtracts a valid pointer from a dangling one, which is undefined behaviour per ISO C 23. Rewrite as new_pool + (map[i].alias - string_space) so both operands of the subtraction point into the same (old) object before string_space is reassigned. Based on GNU gettext commits 695429040 and 2ebbdd0e2. Original author: Bruno Haible <[email protected]> Signed-off-by: Avinal Kumar <[email protected]> Reviewed-by: Adhemerval Zanella <[email protected]> Diff: --- intl/dcigettext.c | 15 ++++++--------- intl/localealias.c | 6 ++++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/intl/dcigettext.c b/intl/dcigettext.c index d738e485f3..43b99c2dea 100644 --- a/intl/dcigettext.c +++ b/intl/dcigettext.c @@ -1136,7 +1136,6 @@ _nl_find_msg (struct loaded_l10nfile *domain_file, not_translated_yet: inbuf = (const unsigned char *) result; - outbuf = freemem + sizeof (size_t); # ifndef _LIBC transmem_list = NULL; # endif @@ -1145,13 +1144,16 @@ _nl_find_msg (struct loaded_l10nfile *domain_file, while (1) { transmem_block_t *newmem; -# ifdef _LIBC - size_t non_reversible; - int res; if (freemem_size < sizeof (size_t)) goto resize_freemem; + outbuf = freemem + sizeof (size_t); + +# ifdef _LIBC + size_t non_reversible; + int res; + res = __gconv (convd->conv, &inbuf, inbuf + resultlen, &outbuf, @@ -1177,9 +1179,6 @@ _nl_find_msg (struct loaded_l10nfile *domain_file, char *outptr = (char *) outbuf; size_t outleft; - if (freemem_size < sizeof (size_t)) - goto resize_freemem; - outleft = freemem_size - sizeof (size_t); if (iconv (convd->conv, (ICONV_CONST char **) &inptr, &inleft, @@ -1248,8 +1247,6 @@ _nl_find_msg (struct loaded_l10nfile *domain_file, transmem_list = newmem; freemem = newmem; # endif - - outbuf = freemem + sizeof (size_t); } /* We have now in our buffer a converted string. Put this diff --git a/intl/localealias.c b/intl/localealias.c index fbb26d9efd..53da04ba2f 100644 --- a/intl/localealias.c +++ b/intl/localealias.c @@ -329,8 +329,10 @@ read_alias_file (const char *fname, int fname_len) for (i = 0; i < nmap; i++) { - map[i].alias += new_pool - string_space; - map[i].value += new_pool - string_space; + map[i].alias = + new_pool + (map[i].alias - string_space); + map[i].value = + new_pool + (map[i].value - string_space); } }