C 安全函数与安全编程
C 提供的部分传统库函数存在缓冲区溢出等风险。本章总结常见不安全用法、改进方式与通用安全实践。
1. 避免的函数与替代
gets:已被移除,使用fgets。strcpy/strcat:可能溢出,考虑strncpy/strncat或snprintf组合(注意strncpy不保证结尾\0)。sprintf:可能溢出,使用snprintf。scanf读取字符串时使用宽度限制:%31s。
示例:
c
char buf[32];
snprintf(buf, sizeof buf, "%s-%d", "id", 42);2. 输入校验与边界检查
- 对外部输入做范围与格式校验(
strtol、strtod)。 - 文件与网络 I/O 检查返回值,处理部分读写。
3. 格式化字符串安全
printf(fmt, ...)中fmt不可由不可信输入直接提供,防止格式化字符串漏洞。- 使用
"%s"明确输出字符串:printf("%s", user_input);
4. 内存安全
- 分配前检查大小是否溢出;分配后检查返回值。
- 使用
memmove处理可能重叠的内存区域。 - 释放后指针置 NULL,避免悬空。
5. 其他建议
- 使用最小权限原则与最小暴露接口。
- 编译时开启更多告警,进行静态/动态分析。
- 对敏感数据内存进行显式清理(注意编译器优化,可用
volatile或专用清理 API)。
6. 小结
通过选择更安全的函数变体、系统的输入校验与内存管理习惯,可以显著降低 C 程序的安全风险。