alid() 函数,当 str == NULL
时,程序将发生严重错误。
解决 bug 的方法是显然的,即将 head
转换为 unsigned char
再比较,并调换两个 if
语句的顺序。NULL dereference,这是一个曾经让 Linux 内核爆出严重漏洞的 UB,我们刚刚成功复现了这一过程。诚然,此处的程序是异常简单的,看出两个写反的 if
语句非常容易;但对于代码业务特别复杂的场景,特别是对一行代码需要数行注释的底层代码或其它核心代码而言,这个 bug 可能一致遗留下来,并成为一个长期休眠的不定时炸弹。它的出现让许多可能是至关重要的代码段,如第二个 if
语句失效,可能给程序使用者造成难以预计的后果。还好当前版本的 GCC 友好地给出了应有的警告,这也再次向我们证明,随意地忽略编译器给出的 Warning 是不可取的。
Google 等团队开发的 sanitizer 已经集成到了当前版本的 GCC 中,让我们用 sanitizer 更为有效地发现上述未定义行为:
lyazj@HelloWorld:~$ gcc -Wall -Wshadow -Wextra ub_null.c -o ub_null -O2 -fsanitize=undefined -fno-sanitize-recover=all
ub_null.c: In function ‘is_valid’:
ub_null.c:7:11: warning: comparison is always false due to limited range of data type [-Wtype-limits]
7 | if(head == 0x80) return 0;
| ^~
lyazj@HelloWorld:~$ ./ub_null
ub_null.c:6:8: runtime error: load of null pointer of type 'const char'
看到这里,是不是很轻松就发现了两个 if
语句写反的问题?