fopen 响应不相关的字符缓冲区而崩溃
fopen crashing in response to unrelated char buffer
所以我有一个 C++ 函数,它接受一个字符串和一个标志,并根据标志将它们写入日志。在适当填充将写入文件的 char 缓冲区后,我调用 fopen。这个 fopen 根据某些随机输入持续(大部分)崩溃。这是代码:
int log_command(char* source, int flag)
{
char *log_file_name = "db.log";
char *buffer = NULL;
int rc = 0;
SYSTEMTIME st;
FILE *fhandle = NULL;
switch(flag){
case 0:
buffer = (char*)calloc(1, strlen(source)+ 18/* 18: size for timestamp, quotes and [=10=] */);
GetSystemTime(&st);
sprintf(buffer, "%04d%02d%02d%02d%02d%02d \"%s\"\n", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, source);
break;
case ROLLFORWARD:
sprintf(buffer, "RF_START\n");
break;
case BACKUP:
sprintf(buffer, "BACKUP %s", source);
break;
}
printf("fopen attempt\n");
// Print buffer info for Whosebug
printf("%s\n", buffer);
print_mem(buffer, strlen(buffer));
if( (fhandle = fopen(log_file_name, "a") ) == NULL ){ // Randomly crashes
rc = FILE_OPEN_ERROR;
}
else{
printf("fopen success\n");
if(info) printf("Logging to %s: \"%s\" \n", log_file_name, buffer);
fwrite(buffer, strlen(buffer), 1, fhandle);
fclose(fhandle);
}
return rc;
}
当缓冲区中包含以下文本时:
20160513050408 "insert into other values(120)"
原始字节数据如:
32 30 31 36 30 35 31 33 30 35 30 34 30 38 20 22 20160513050408 "
69 6e 73 65 72 74 20 69 6e 74 6f 20 6f 74 68 65 insert into othe
72 20 76 61 6c 75 65 73 28 31 32 30 29 22 0a r values(120)".
它会持续崩溃一段时间.. 然后就莫名其妙地工作了。当 *source 有 4、176 或大多数其他数字而不是 120 时,它工作得很好。
您没有为 buffer
分配足够的字符。因此,您最终会覆盖不应该写入的内存,从而导致未定义的行为。
您在 sprintf
.
的调用中使用了以下格式
"%04d%02d%02d%02d%02d%02d \"%s\"\n"
该格式说明符的需求是:
4
个字符 st.wYear
2
个字符 st.wMonth
2
个字符 st.wDay
2
个字符 st.wMonth
2
个字符 st.wMinute
2
个字符 st.wSecond
1
字符为 space 字符
1
字符 "
strlen(source)
个字符 source
1
字符 "
1
字符 \n
1
终止空字符的字符。
您至少需要 strlen(source) + 19
个字符。
改变
buffer = (char*)calloc(1, strlen(source)+ 18);
到
buffer = (char*)calloc(strlen(source) + 19, 1); // Make it 19 or higher.
所以我有一个 C++ 函数,它接受一个字符串和一个标志,并根据标志将它们写入日志。在适当填充将写入文件的 char 缓冲区后,我调用 fopen。这个 fopen 根据某些随机输入持续(大部分)崩溃。这是代码:
int log_command(char* source, int flag)
{
char *log_file_name = "db.log";
char *buffer = NULL;
int rc = 0;
SYSTEMTIME st;
FILE *fhandle = NULL;
switch(flag){
case 0:
buffer = (char*)calloc(1, strlen(source)+ 18/* 18: size for timestamp, quotes and [=10=] */);
GetSystemTime(&st);
sprintf(buffer, "%04d%02d%02d%02d%02d%02d \"%s\"\n", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, source);
break;
case ROLLFORWARD:
sprintf(buffer, "RF_START\n");
break;
case BACKUP:
sprintf(buffer, "BACKUP %s", source);
break;
}
printf("fopen attempt\n");
// Print buffer info for Whosebug
printf("%s\n", buffer);
print_mem(buffer, strlen(buffer));
if( (fhandle = fopen(log_file_name, "a") ) == NULL ){ // Randomly crashes
rc = FILE_OPEN_ERROR;
}
else{
printf("fopen success\n");
if(info) printf("Logging to %s: \"%s\" \n", log_file_name, buffer);
fwrite(buffer, strlen(buffer), 1, fhandle);
fclose(fhandle);
}
return rc;
}
当缓冲区中包含以下文本时:
20160513050408 "insert into other values(120)"
原始字节数据如:
32 30 31 36 30 35 31 33 30 35 30 34 30 38 20 22 20160513050408 "
69 6e 73 65 72 74 20 69 6e 74 6f 20 6f 74 68 65 insert into othe
72 20 76 61 6c 75 65 73 28 31 32 30 29 22 0a r values(120)".
它会持续崩溃一段时间.. 然后就莫名其妙地工作了。当 *source 有 4、176 或大多数其他数字而不是 120 时,它工作得很好。
您没有为 buffer
分配足够的字符。因此,您最终会覆盖不应该写入的内存,从而导致未定义的行为。
您在 sprintf
.
"%04d%02d%02d%02d%02d%02d \"%s\"\n"
该格式说明符的需求是:
4
个字符st.wYear
2
个字符st.wMonth
2
个字符st.wDay
2
个字符st.wMonth
2
个字符st.wMinute
2
个字符st.wSecond
1
字符为 space 字符1
字符"
strlen(source)
个字符source
1
字符"
1
字符\n
1
终止空字符的字符。
您至少需要 strlen(source) + 19
个字符。
改变
buffer = (char*)calloc(1, strlen(source)+ 18);
到
buffer = (char*)calloc(strlen(source) + 19, 1); // Make it 19 or higher.