我用 C 语言为 DWM 编写了一个状态栏实用程序,用于显示时间、日期、CPU 温度和电池电量。我最近注意到该程序崩溃了,并发现它有一个核心转储。我重新编译了
编写了一个状态栏实用程序, DWM 用于显示时间、日期、CPU 温度和电池电量。我最近注意到该程序崩溃了,并且发现它有一个核心转储。我重新编译了该实用程序以包含调试符号来调试 gdb
,它在启动后大约 10 分钟崩溃了。在分析核心转储时, coredumpctl debug
我在回溯中发现了以下行。
0x0000716af522c799 in __GI___fortify_fail (msg=msg@entry=0x716af52ba153 "buffer overflow detected") at fortify_fail.c:24
我一直在梳理代码,但我不明白是什么导致了缓冲区溢出,因为它在很长一段时间内运行良好,并且没有发生另一次崩溃。
代码中导致该问题的那一行是:
strcat(status, battery_buff);
包含代码的 GitHub 存储库
我创建的 Github 问题
系统信息:
完整的 GDB 回溯( thread apply all backtrace full
)
Thread 1 (Thread 0x716af50ce2c0 (LWP 1963)):
#0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
tid = <optimized out>
ret = 0
pd = <optimized out>
old_mask = {__val = {23}}
ret = <optimized out>
#1 0x0000716af519d463 in __pthread_kill_internal (threadid=<optimized out>, signo=6) at pthread_kill.c:78
No locals.
#2 0x0000716af5144120 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
ret = <optimized out>
#3 0x0000716af512b4c3 in __GI_abort () at abort.c:79
save_stage = 1
act = {__sigaction_handler = {sa_handler = 0x20, sa_sigaction = 0x20}, sa_mask = {__val = {6786648855210017280, 0, 140721397189936, 101591911342992, 101591911411072, 100, 32, 140721397190128, 124704192526143, 101591911343744, 101591911343751, 101591911343752, 0, 140720308486146, 124704193122162, 1088703904}}, sa_flags = 907723264, sa_restorer = 0xb}
#4 0x0000716af512c354 in __libc_message_impl (fmt=fmt@entry=0x716af52ba16c "*** %s ***: terminated\n") at ../sysdeps/posix/libc_fatal.c:132
ap = {{gp_offset = 16, fp_offset = 23653, overflow_arg_area = 0x7ffc40e44ec0, reg_save_area = 0x7ffc40e44e50}}
fd = 2
iov = {{iov_base = 0x716af52ba16c, iov_len = 4}, {iov_base = 0x716af52ba153, iov_len = 24}, {iov_base = 0x716af52ba172, iov_len = 17}, {iov_base = 0x3000000030, iov_len = 140721397190376}, {iov_base = 0x7ffc40e44e20, iov_len = 6786648855210017280}, {iov_base = 0x7ffc40e44e60, iov_len = 124704192628220}, {iov_base = 0x5c65b5c98010, iov_len = 528}}
iovcnt = <optimized out>
total = <optimized out>
cp = <optimized out>
#5 0x0000716af522c799 in __GI___fortify_fail (msg=msg@entry=0x716af52ba153 "buffer overflow detected") at fortify_fail.c:24
No locals.
#6 0x0000716af522c124 in __GI___chk_fail () at chk_fail.c:28
No locals.
#7 0x0000716af522db1a in __strcat_chk (dest=dest@entry=0x5c65b5c9a390 " 12:17:25 PM | 08/18/2024 | 100°C | 100% ", src=src@entry=0x5c65b5c9a680 "| 100% ", destlen=<optimized out>, destlen@entry=42) at strcat_chk.c:34
s1 = <optimized out>
s2 = <optimized out>
c = <optimized out>
#8 0x00005c658482c381 in strcat (__dest=0x5c65b5c9a390 " 12:17:25 PM | 08/18/2024 | 100°C | 100% ", __src=0x5c65b5c9a680 "| 100% ") at /usr/include/bits/string_fortified.h:140
No locals.
#9 main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/dmenustatus/dmenustatus/src/dmenustatus.c:87
step = 1
status = 0x5c65b5c9a390 " 12:17:25 PM | 08/18/2024 | 100°C | 100% "
datetime_buff = 0x5c65b5c9a9a0 " 12:17:25 PM | 08/18/2024 "
cputemp_buff = 0x5c65b5c9a450 "| 100°C "
battery_buff = 0x5c65b5c9a680 "| 100% "
p0
p1
char battery_status(char *base)
{
char status;
char *buff = readfile(base, "status");
if (buff == NULL) {
return 'E';
}
if (!strncmp(buff, "Discharging", 11)) {
...
} else {
buff[strlen(buff) - 1] = '\0';
status = '?';
}
是 buff == NULL
假的( readfile
永远不会返回 NULL
在这种 存在缓冲区 下溢 else
:如果 buff
是空的,则您正在写入 buff[-1]
.
一般来说,只分配 42 个字节既有 status
缺陷又浪费( malloc
可能 将其四舍五入为 48 或 64 个字节)。
最好重新构造它,这样您就可以将 char status[512];
之后的 指针 。类似于以下内容:
char status[513];
const int sz = sizeof(status) - 1;
while (running) {
char *p = datetime(status, sz /*sz characters remaining*/);
p = cputemp(9, p, sz - (p - status) /* remaining space*/);
p = battery(0, p, sz - (p - status) /* remaining space*/);
...