]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
intl: Fix undefined pointer behaviour
authorAvinal Kumar <avinal.xlvii@gmail.com>
Mon, 18 May 2026 10:14:52 +0000 (15:44 +0530)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Wed, 20 May 2026 20:22:03 +0000 (17:22 -0300)
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 <bruno@clisp.org>

Signed-off-by: Avinal Kumar <avinal.xlvii@gmail.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
intl/dcigettext.c
intl/localealias.c

index d738e485f3b2b1dec6dcc0f91c7efdcf09b6582f..43b99c2dea1b8d741b919294dae3cd5fbd3558ad 100644 (file)
@@ -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
index fbb26d9efd7c35b6b8dfdf5ac18a89a835e014a4..53da04ba2fd15fab58466baaba7f36259cc1cdf8 100644 (file)
@@ -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);
                            }
                        }