} \
} 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)
l = strlen (s);
r = xmalloc (l + 2);
- strcpy (r, s);
+ strcpy_safe (r, s);
if (r[l -1] != ' ')
r[l++] = ' ';
r[l] = '\0';
if (nestlen)
{
RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
- strcpy (ret + retind, nestret);
+ strcpy_safe (ret + retind, nestret);
retind += nestlen;
}
FREE (nestret);
if (nestlen)
{
RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
- strcpy (ret + retind, nestret);
+ strcpy_safe (ret + retind, nestret);
retind += nestlen;
}
FREE (nestret);
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;
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;
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;
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;
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;
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;
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;
token[token_index++] = '(';
if (ttok)
{
- strcpy (token + token_index, ttok);
+ strcpy_safe (token + token_index, ttok);
token_index += ttoklen;
}
token[token_index++] = ')';
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)
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;
{
t = strrchr (t_string, '/');
if (t)
- strcpy (t_string, t + 1);
+ strcpy_safe (t_string, t + 1);
}
}
#undef ROOT_PATH
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. */