From 07c8b4f5d65201a86948d089101d9e6806bae1aa Mon Sep 17 00:00:00 2001 From: Yaroslav Yamshchikov Date: Tue, 24 Sep 2024 19:18:55 +0300 Subject: [PATCH] Fix ASan check __strcpy_chk-param-overlap fail 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 --- parse.y | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/parse.y b/parse.y index f1967ab..cd60dd7 100644 --- 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. */ -- 2.34.1