Fix ASan check __strcpy_chk-param-overlap fail sandbox/y.yamshchiko/asan accepted/tizen/base/x/asan/20241010.231911
authorYaroslav Yamshchikov <y.yamshchiko@samsung.com>
Tue, 24 Sep 2024 16:18:55 +0000 (19:18 +0300)
committerDongkyun Son <dongkyun.s@samsung.com>
Thu, 10 Oct 2024 01:40:20 +0000 (10:40 +0900)
The check fail caused by using of undocumented abilities of strcpy.
ASan complains when strcpy-family functions used
with overlapping memory regions. strcpy specification does
not allow overlapping. This change makes strcpy wrapper
called strcpy_safe across whole parse.y, the wrapper detects
overlapping and redirects to memmove in such case.

Change-Id: I8c1c2d2195ade6bd2cd1c33690d656d0ceac33d8
Signed-off-by: Yaroslav Yamshchikov <y.yamshchiko@samsung.com>
parse.y

diff --git a/parse.y b/parse.y
index f1967ab55552856d510e825fa29034b0252fa224..cd60dd7f78fdd2d3086ed69a8d2a4eda9a630ef9 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -2297,6 +2297,18 @@ static int open_brace_count;
       } \
   } while (0)
 
+/* This function is similar to libc strcpy() but handles
+   overlapping source and destination regions properly, if any */
+static char *
+strcpy_safe(char *dest, const char *src)
+{
+  size_t size = strlen(src) + 1;
+  if (dest + size <= src || src + size <= dest)
+    return strcpy(dest, src); /* no overlap, redirect to libc */
+  else
+    return (char *)memmove(dest, src, size); /* overlap detected, move the string including '\0' */
+}
+
 #if defined (ALIAS)
 
     /* OK, we have a token.  Let's try to alias expand it, if (and only if)
@@ -2321,7 +2333,7 @@ mk_alexpansion (s)
 
   l = strlen (s);
   r = xmalloc (l + 2);
-  strcpy (r, s);
+  strcpy_safe (r, s);
   if (r[l -1] != ' ')
     r[l++] = ' ';
   r[l] = '\0';
@@ -2919,7 +2931,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
              if (nestlen)
                {
                  RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
-                 strcpy (ret + retind, nestret);
+                 strcpy_safe (ret + retind, nestret);
                  retind += nestlen;
                }
              FREE (nestret);
@@ -2940,7 +2952,7 @@ add_nestret:
          if (nestlen)
            {
              RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
-             strcpy (ret + retind, nestret);
+             strcpy_safe (ret + retind, nestret);
              retind += nestlen;
            }
          FREE (nestret);
@@ -3451,7 +3463,7 @@ read_token_word (character)
          RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
                                  token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
          token[token_index++] = character;
-         strcpy (token + token_index, ttok);
+         strcpy_safe (token + token_index, ttok);
          token_index += ttoklen;
          all_digit_token = 0;
          quoted = 1;
@@ -3477,7 +3489,7 @@ read_token_word (character)
          RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
                                  token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
          token[token_index++] = character;
-         strcpy (token + token_index, ttok);
+         strcpy_safe (token + token_index, ttok);
          token_index += ttoklen;
          FREE (ttok);
          dollar_present = all_digit_token = 0;
@@ -3502,7 +3514,7 @@ read_token_word (character)
                                      TOKEN_DEFAULT_GROW_SIZE);
              token[token_index++] = character;
              token[token_index++] = peek_char;
-             strcpy (token + token_index, ttok);
+             strcpy_safe (token + token_index, ttok);
              token_index += ttoklen;
              FREE (ttok);
              dollar_present = all_digit_token = 0;
@@ -3544,7 +3556,7 @@ read_token_word (character)
                                      TOKEN_DEFAULT_GROW_SIZE);
              token[token_index++] = character;
              token[token_index++] = peek_char;
-             strcpy (token + token_index, ttok);
+             strcpy_safe (token + token_index, ttok);
              token_index += ttoklen;
              FREE (ttok);
              dollar_present = 1;
@@ -3593,7 +3605,7 @@ read_token_word (character)
              RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 2,
                                      token_buffer_size,
                                      TOKEN_DEFAULT_GROW_SIZE);
-             strcpy (token + token_index, ttrans);
+             strcpy_safe (token + token_index, ttrans);
              token_index += ttranslen;
              FREE (ttrans);
              quoted = 1;
@@ -3610,7 +3622,7 @@ read_token_word (character)
              RESIZE_MALLOCED_BUFFER (token, token_index, 3,
                                      token_buffer_size,
                                      TOKEN_DEFAULT_GROW_SIZE);
-             strcpy (token + token_index, ttok);
+             strcpy_safe (token + token_index, ttok);
              token_index += 2;
              dollar_present = 1;
              all_digit_token = 0;
@@ -3632,7 +3644,7 @@ read_token_word (character)
                                  token_buffer_size,
                                  TOKEN_DEFAULT_GROW_SIZE);
          token[token_index++] = character;
-         strcpy (token + token_index, ttok);
+         strcpy_safe (token + token_index, ttok);
          token_index += ttoklen;
          FREE (ttok);
          all_digit_token = 0;
@@ -3654,7 +3666,7 @@ read_token_word (character)
              token[token_index++] = '(';
              if (ttok)
                {
-                 strcpy (token + token_index, ttok);
+                 strcpy_safe (token + token_index, ttok);
                  token_index += ttoklen;
                }
              token[token_index++] = ')';
@@ -3757,7 +3769,7 @@ got_token:
   the_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
   the_word->word = (char *)xmalloc (1 + token_index);
   the_word->flags = 0;
-  strcpy (the_word->word, token);
+  strcpy_safe (the_word->word, token);
   if (dollar_present)
     the_word->flags |= W_HASDOLLAR;
   if (quoted)
@@ -4214,7 +4226,7 @@ decode_prompt_string (string)
            case 'V':
              temp = (char *)xmalloc (16);
              if (c == 'v')
-               strcpy (temp, dist_version);
+               strcpy_safe (temp, dist_version);
              else
                sprintf (temp, "%s.%d", dist_version, patch_level);
              goto add_string;
@@ -4254,7 +4266,7 @@ decode_prompt_string (string)
                      {
                        t = strrchr (t_string, '/');
                        if (t)
-                         strcpy (t_string, t + 1);
+                         strcpy_safe (t_string, t + 1);
                      }
                  }
 #undef ROOT_PATH
@@ -4262,7 +4274,7 @@ decode_prompt_string (string)
                else
                  /* polite_directory_format is guaranteed to return a string
                     no longer than PATH_MAX - 1 characters. */
-                 strcpy (t_string, polite_directory_format (t_string));
+                 strcpy_safe (t_string, polite_directory_format (t_string));
 
                /* If we're going to be expanding the prompt string later,
                   quote the directory name. */