您的位置:首页 > 其它

一个fread失败时处理不当引发的crash

2013-04-03 16:42 1266 查看
最近发现一次web机上的agent程序crash了,通过对日志分析,发现是代码中对fread使用理解有误导致。
agent程序的作用是实时收集web机上的某消息文件,然后转发到消息服务器上。在web请求中业务如果需要发送消息,则会将消息写入消息文件中,消息文件的格式为msg1_len:msg1_data:msg2_len:msg2_data...

//该函数每次从文件中取一条消息
#define MESSAGE_SIZE_LEN 4
bool get_one_msg(FILE *fp, char **msg_buf, uint32_t *msg_buf_len)
{
uint32_t msg_len;
if (1 != fread(&msg_len, sizeof(msg_len), 1, fp))
{
return false;
}
msg_len = ntohl(msg_len); //msg_len in network byte order
char *msg_buf = (char *)malloc(msg_len + MESSAGE_SIZE_LEN);
if (p == NULL)
{
return false;
}
memcpy(*msg_buf, &net_msg_len, MESSAGESET_SIZE_LEN);
if (1 != fread(*msg_buf + MESSAGE_SIZE_LEN, msg_len, 1, fp))
{
free(*msg_buf);
*msg_buf = NULL;
return false;
}
*msg_buf_len = msg_len + MESSAGE_SIZE_LEN;
return true;
}
在上面的代码中,如果另外一个进程正在写消息文件,但只写了消息长度(假定消息为200字节),消息内容还未写完,那么此时调用get_one_msg函数时,会从文件中读取了该消息的长度200字节。接着在执行第二个fread读内容时读取失败,fread返回为0(也许读了20字节就到了文件结尾),但当前文件的偏移量已向前移动。
当下次调用该函数获取消息时,文件偏移量已不在正确的消息边界上了,此时读出的msg_len为4294967295。
由于没有msg_len进行判断,在malloc时,msg_len + 4,实际结果为3。则在memcpy或者每二个fread时就出现了crash
在这优代码中至少有两个地方处理不当:
1 fread失败后,要么把文件offset向前移到之前正确的位置,或者将当前的已读的buffer保存,下次再接着去读余下的。
2 未对msg_len进行检测
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐