为什么这里有无效写入(Valgrind)
Why is there an Invalid Write here (Valgrind)
我正在编写 shell。当我像这样执行 cat /dev/urandom | valgrind ./myshell
到 运行 一些测试并查看我是否没有任何段错误或其他错误时,valgrind
有时会告诉我我有一个 Invalid Write
在函数 my_wordcpy
中这一行 tab[++j] = str[*i];
不是每次都会发生,但确实会发生,我就是不明白为什么。这是我的代码:
static int count_words(char *str, char *sep)
{
int quote;
int words;
int i;
i = -1;
if (count_quotes(str) == -1)
return (0);
words = 0;
quote = 0;
while (str[++i] != '[=10=]')
{
if (str[i] == '"')
{
if (quote == 0)
quote = 1;
else
quote = 0;
}
if (quote == 0
&& (is_cinside(sep, str[i]) == 0 && str[i] != '\t' &&
(is_cinside(sep, str[i + 1]) == 1 ||
str[i + 1] == '\t' || str[i + 1] == '[=10=]')))
++words;
}
return (words);
}
static int my_wordlen(char *str, int *i, char *sep)
{
int quote;
int j;
j = 0;
quote = 0;
while (str[++(*i)] != '[=10=]')
if (str[*i] == '"' && quote == 0)
quote = 1;
else if (quote == 1 || (quote == 0 && is_cinside(sep, str[*i]) == 0 &&
str[*i] != '\t'))
{
++j;
if ((quote == 1 && str[*i + 1] == '"') ||
(quote == 0 && (is_cinside(sep, str[*i + 1]) == 1 ||
str[*i + 1] == '\t' ||
str[*i + 1] == '[=10=]')))
{
if (quote == 1 && str[*i + 1] == '"')
++(*i);
return (j);
}
}
return (-1);
}
static char *my_wordcpy(char *tab, char *str, int *i, char *sep)
{
int quote;
int j;
j = -1;
quote = 0;
while (str[++(*i)] != '[=10=]')
if (str[*i] == '"' && quote == 0)
quote = 1;
else if (quote == 1 || (quote == 0 &&
is_cinside(sep, str[*i]) == 0 && str[*i] != '\t'))
{
tab[++j] = str[*i]; /* here is the invalid write. */
if ((quote == 1 && str[*i + 1] == '"') ||
(quote == 0 && (is_cinside(sep, str[*i + 1]) == 1 ||
str[*i + 1] == '\t' || str[*i + 1] == '[=10=]')))
{
if (quote == 1 && str[*i + 1] == '"')
++(*i);
tab[++j] = '[=10=]';
return (tab);
}
}
return (NULL);
}
char **my_quotetowordtab(char *str, char *sep)
{
char **tab;
int words;
int i;
int j;
int k;
i = -1;
j = -1;
k = -1;
if (str == NULL)
return (NULL);
words = count_words(str, sep);
if ((tab = malloc(sizeof(char *) * (words + 1))) == NULL)
return (NULL);
while (++i < words)
{
if ((tab[i] = malloc(sizeof(char) * (my_wordlen(str, &j, sep) + 1)))
== NULL)
return (NULL);
tab[i] = my_wordcpy(tab[i], str, &k, sep);
}
tab[i] = NULL;
return (tab);
}
如果您的 str
只有一个或奇数个 "
引号字符会怎样?在那种情况下,您的代码似乎不会检查 [=12=]
,因此它可以写入通过选项卡的末尾。我认为您需要将 NUL
字符检查移到第二个 if 子句之外以捕获这两种情况。
my_wordlen
可以 return -1
而你在将它交给 malloc
之前不检查它。在这种情况下,分配了 0
个字节,因此在 my_wordcopy
中发生了堆缓冲区溢出。
我正在编写 shell。当我像这样执行 cat /dev/urandom | valgrind ./myshell
到 运行 一些测试并查看我是否没有任何段错误或其他错误时,valgrind
有时会告诉我我有一个 Invalid Write
在函数 my_wordcpy
中这一行 tab[++j] = str[*i];
不是每次都会发生,但确实会发生,我就是不明白为什么。这是我的代码:
static int count_words(char *str, char *sep)
{
int quote;
int words;
int i;
i = -1;
if (count_quotes(str) == -1)
return (0);
words = 0;
quote = 0;
while (str[++i] != '[=10=]')
{
if (str[i] == '"')
{
if (quote == 0)
quote = 1;
else
quote = 0;
}
if (quote == 0
&& (is_cinside(sep, str[i]) == 0 && str[i] != '\t' &&
(is_cinside(sep, str[i + 1]) == 1 ||
str[i + 1] == '\t' || str[i + 1] == '[=10=]')))
++words;
}
return (words);
}
static int my_wordlen(char *str, int *i, char *sep)
{
int quote;
int j;
j = 0;
quote = 0;
while (str[++(*i)] != '[=10=]')
if (str[*i] == '"' && quote == 0)
quote = 1;
else if (quote == 1 || (quote == 0 && is_cinside(sep, str[*i]) == 0 &&
str[*i] != '\t'))
{
++j;
if ((quote == 1 && str[*i + 1] == '"') ||
(quote == 0 && (is_cinside(sep, str[*i + 1]) == 1 ||
str[*i + 1] == '\t' ||
str[*i + 1] == '[=10=]')))
{
if (quote == 1 && str[*i + 1] == '"')
++(*i);
return (j);
}
}
return (-1);
}
static char *my_wordcpy(char *tab, char *str, int *i, char *sep)
{
int quote;
int j;
j = -1;
quote = 0;
while (str[++(*i)] != '[=10=]')
if (str[*i] == '"' && quote == 0)
quote = 1;
else if (quote == 1 || (quote == 0 &&
is_cinside(sep, str[*i]) == 0 && str[*i] != '\t'))
{
tab[++j] = str[*i]; /* here is the invalid write. */
if ((quote == 1 && str[*i + 1] == '"') ||
(quote == 0 && (is_cinside(sep, str[*i + 1]) == 1 ||
str[*i + 1] == '\t' || str[*i + 1] == '[=10=]')))
{
if (quote == 1 && str[*i + 1] == '"')
++(*i);
tab[++j] = '[=10=]';
return (tab);
}
}
return (NULL);
}
char **my_quotetowordtab(char *str, char *sep)
{
char **tab;
int words;
int i;
int j;
int k;
i = -1;
j = -1;
k = -1;
if (str == NULL)
return (NULL);
words = count_words(str, sep);
if ((tab = malloc(sizeof(char *) * (words + 1))) == NULL)
return (NULL);
while (++i < words)
{
if ((tab[i] = malloc(sizeof(char) * (my_wordlen(str, &j, sep) + 1)))
== NULL)
return (NULL);
tab[i] = my_wordcpy(tab[i], str, &k, sep);
}
tab[i] = NULL;
return (tab);
}
如果您的 str
只有一个或奇数个 "
引号字符会怎样?在那种情况下,您的代码似乎不会检查 [=12=]
,因此它可以写入通过选项卡的末尾。我认为您需要将 NUL
字符检查移到第二个 if 子句之外以捕获这两种情况。
my_wordlen
可以 return -1
而你在将它交给 malloc
之前不检查它。在这种情况下,分配了 0
个字节,因此在 my_wordcopy
中发生了堆缓冲区溢出。