gcc (GCC) 4.7.2
valgrind-3.8.1
c89
您好,
==1160== Invalid read of size 1
==1160== at 0x8048C94: get_input_values (parse_cmd_input.c:278)
==1160== by 0x8048BA0: parse_input (parse_cmd_input.c:245)
==1160== by 0x80489A1: main (parse_cmd_input.c:50)
==1160== Address 0x40ef02c is 0 bytes after a block of size 4 alloc'd
==1160== at 0x40072C5: calloc (vg_replace_malloc.c:593)
==1160== by 0x8048B28: parse_input (parse_cmd_input.c:239)
==1160== by 0x80489A1: main (parse_cmd_input.c:50)
所以它说地址正在读取分配大小为4的零字节,并试图从中读取1个字节。但是,我没有超过数组的界限,我正在访问元素0。
我已经使用gdb检查过,元素零包含一个字符。
我的程序没有崩溃,似乎工作正常。但它可能会导致生产服务器出现问题。
我不确定我在这里是否正确: 应该是:
cpy_input = calloc(strlen(input) + 1, sizeof(char*));
或:
cpy_input = calloc(strlen(input) + 1, sizeof(char));
char是1个字节,指向char的指针是我系统上的4个字节。
传入的字符串类似于"25 b"
int parse_input(const char *input)
{
char *cpy_input = NULL;
int has_error = -1;
if(strlen(input) == 0) {
LOG_ERR("FAILED: Empty string");
return -1;
}
cpy_input = calloc(strlen(input) + 1, sizeof(char));
apr_cpystrn(cpy_input, input, sizeof(cpy_input));
LOG_INFO("[ %s ]", cpy_input);
memset(&channel, 0, sizeof channel);
has_error = get_input_values(cpy_input, &channel);
free(cpy_input);
return has_error;
}
int get_input_values(const char *str, channel_t *channel)
{
size_t i = 0;
size_t k = 0;
int upper_flag = 0;
/* Indicates no digits or command found*/
channel->lower = -1;
channel->upper = -1;
channel->cmd = -1;
#define DIG_BUFFER_SIZE 32
char dig_buffer_lower[DIG_BUFFER_SIZE];
char dig_buffer_upper[DIG_BUFFER_SIZE];
if(strlen(str) == 0) {
LOG_ERR("FAILED: Empty string");
return -1;
}
memset(dig_buffer_lower, 0, DIG_BUFFER_SIZE);
memset(dig_buffer_upper, 0, DIG_BUFFER_SIZE);
LOG_INFO("SIZE %d %d", sizeof(char), sizeof(char*));
/* Increament and check for digits */
for(i = 0; i < DIG_BUFFER_SIZE; i++) {
switch(str[i]) {
case 32: /* ignore space */
continue;
case 45: /* '-' Start upper bounds */
LOG_DEBUG("Found a '-' check upper value");
/* Having a second '-' means the string is invalid */
if(!upper_flag) {
upper_flag = 1;
k = 0;
}
break;
} /* switch */
/* Insert on digits into the lower and upper values */
if(isdigit(str[i])) {
if(upper_flag) {
dig_buffer_upper[k++] = str[i];
LOG_DEBUG("dig_buffer_upper[%d] %s", i, dig_buffer_upper);
}
else {
/* Add to digit buffer */
dig_buffer_lower[k++] = str[i];
LOG_DEBUG("dig_buffer_lower[%d] %s", i, dig_buffer_lower);
}
}
} /* for loop */
非常感谢任何建议,
答案 0 :(得分:4)
sizeof(cpy_input)
只是sizeof(char *)
,而不是字符串长度。相反,请说:
apr_cpystrn(cpy_input, input, strlen(input) + 1);
或者更好,使用裸strcpy
或同等物。此外,不需要使用calloc
将数组清零,因为您无论如何都要覆盖它。由于sizeof(char)
根据定义为1
,因此您可以使用以下内容分配数组:
cpy_input = malloc(strlen(input) + 1);
(想想字符串一分钟:你已经在一个明智的地方有一个空终结符,或者strlen
会崩溃或返回一个巨大的值。一旦你相信{的结果{1}},保证为strlen
字符串和空终止符分配足够的内存。或者,您可以使用strcpy
来获得更高效的副本,因为你知道尺寸。)
答案 1 :(得分:1)
好吧,也许我错过了一些东西,但是for
循环会重复0 .. DIG_BUFFER_SIZE-1
,从str[i]
读取。我没有看到会导致该循环提前爆发的原因,特别是因为它似乎立即包裹switch
,因此break
内的任何switch
都会退出{{1} },但不是switch
。
您的for
正确分配存储空间以获得确切的输入长度。如果字符串短于calloc(strlen(input) + 1, sizeof(char));
,则get_input_values
中的下游代码似乎不会停止。
(我希望被证明是错误的,但要知道,我们需要查看更多代码。)