我有一个函数可以从字符串中提取出 pgn 元数据(标签对) 并将它们放入一个结构中。结构定义为:
typedef struct {
char key[15];
char value[31];
} metadata_txt;
功能:
// (szt is size_t and u8f is uint_fast8_t)
void carve_metadata(char* line, metadata_txt* metadata_buf) {
if (metadata_buf == NULL) {
console_error("PANIC. METADATA_BUF IS NULL %s, %d, %s", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
if (line == NULL) {
console_error("PANIC. LINE IS NULL %s, %d, %s", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
register szt length = strlen(line);
if (length < 5) {
console_error("PANIC. LINE LENGTH IS LESS THAN 5 %s, %d, %s", __FILE__, __LINE__, __FUNCTION__);
// The smallest valid tag pair should be [ ""] whichs length is 5.
}
// Example input string: [Foo "Bar"]
line++; length--; // Remove the `[` ==> Foo "Bar"]
line[length-1] = '\0'; line[length-2] = '\0'; length -= 2; // Removes the ending `"]` ==> Foo "Bar
// Extract the key
register u8f i = 0;
while (*line != ' ') {
// printf("%c | i: %d | line: %s\n", *line, i, line); fflush(stdout);
metadata_buf->key[i] = *line;
i++; line++; length--;
} // ==> "Bar
line += 2; length -= 2; // Remove the ` "`. ==> Bar
// Now, all that's left in line is the value. So we can copy it into the metadata_buf->value
strncpy(metadata_buf->value, line, length);
}
使用-fsanitize=address编译程序后,发现是metadata_buf->key[i] = *line;
这一行引起的crash。我进一步调查,发现 i
在这种情况下是 0。另外,metadata_buf is 初始化为 0。
输入字符串 (char* line
): [Site "Buenos Aires"]
fsanitize 输出:
==906==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffffe1c40c2 at pc 0x7fa318a914fc bp 0x7ffffe1c3a80 sp 0x7ffffe1c3a70
WRITE of size 1 at 0x7ffffe1c40c2 thread T0
#0 0x7fa318a914fb in carve_metadata src/convert.c:55
#1 0x7fa318a92941 in convert_pgn_to_cmbr src/convert.c:199
#2 0x7fa318a937d3 in main src/main.c:68
#3 0x7fa317e19d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#4 0x7fa317e19e3f in __libc_start_main_impl ../csu/libc-start.c:392
#5 0x7fa318a90204 in _start (/mnt/c/Users/datag/Desktop/programming/c/cmbr/out/main+0x5204)
(这是在 wsl 下运行的)
编译标志:-Wall -Wextra -Werror -std=c99 -fuse-ld=mold -fsanitize=address -ggdb
抄送:gcc
我尝试使用 -fsanitize=address 和 printf 调试。使用 gdb 是不可能的,因为我在 WSL 上运行
提前谢谢你。