【缺陷周话】第17期:有符号整数溢出
字数 1594 2025-08-18 11:37:49
有符号整数溢出缺陷分析与防护指南
1. 有符号整数溢出概述
在C/C++编程语言中,整数类型分为有符号整数和无符号整数:
- 有符号整数:最高位表示符号(正或负),其余位表示数值大小
- 无符号整数:所有位都用于表示数值大小
有符号整数的取值范围为[-2n-1, 2n-1-1],当有符号整数的值超出这个范围时,就会发生有符号整数溢出。
2. 有符号整数溢出的主要原因
导致有符号整数溢出的重要原因之一是运算操作不当,常见运算包括:
- 加法
- 减法
- 乘法
- 除法
- 位移运算
如果没有对值的范围进行判断和限制,很容易导致有符号整数溢出问题。
3. 有符号整数溢出的危害
有符号整数溢出会产生数值错误,根据错误数值的使用位置不同,可能导致不同的安全问题:
- 拒绝服务攻击:错误的数值可能导致程序崩溃或无限循环
- 内存破坏:错误的数值用于内存操作可能导致缓冲区溢出
- 任意代码执行:在严重情况下可能被利用执行恶意代码
实际案例统计:仅2018年1月至12月,CVE中就有605条与有符号整数溢出相关的漏洞信息。
4. 典型漏洞案例
| CVE编号 | 影响范围 | 危害 | 修复版本 |
|---|---|---|---|
| CVE-2018-1000876 | binutils 2.32及更早版本 | 任意代码执行 | 3a551c7a1b80fca579461774860574eabfd7f18f |
| CVE-2018-1000098 | teluu pjsip 2.7.1及更低版本 | 崩溃 | 2.7.2 |
| CVE-2018-1000524 | miniSphere 5.2.9及更早版本 | 拒绝服务 | 5.0.3/5.1.5/5.2.10 |
| CVE-2018-1000127 | memcached 1.4.37以前版本 | 数据损坏和死锁 | 1.4.37 |
5. 示例代码分析
5.1 缺陷代码示例
// 示例来源于Samate Juliet Test Suite for C/C++ v1.3
// 源文件名: CWE190_Integer_Overflow__int64_t_max_multiply_01.c
void bad()
{
int64_t data;
/* 初始化data为最大值 */
data = INT64_MAX;
if(data > 0) /* 确保data不小于等于0 */
{
/* 潜在缺陷: 没有检查data的上限 */
int64_t result = data * 2; // 这里会发生整数溢出
printLongLongLine(result);
}
}
问题分析:
- 虽然代码通过
if(data > 0)确保了data的值不小于等于0 - 但没有对data值的上限进行限制
- 当执行
data * 2运算时,结果超出了int64_t的最大值,导致有符号整数溢出
5.2 修复后的代码
void good()
{
int64_t data;
/* 初始化data为最大值 */
data = INT64_MAX;
if(data > 0) /* 确保data不小于等于0 */
{
/* 修复: 添加上限检查 */
if (data < (INT64_MAX/2))
{
int64_t result = data * 2;
printLongLongLine(result);
}
else
{
printLine("data value is too large to perform multiplication.");
}
}
}
修复要点:
- 添加了对data最大值的限制检查
data < (INT64_MAX/2) - 当data过大时,提供错误处理路径
- 确保乘法运算不会导致整数溢出
6. 防护措施
要避免有符号整数溢出,需要注意以下几点:
-
范围检查:
- 在进行有符号整数操作前,必须检查操作数的取值范围
- 特别注意乘法运算,应确保
a * b不会超过最大值(检查a <= MAX/b) - 对于加法,检查
a <= MAX - b
-
输入验证:
- 对来自不可信源的有符号整数进行严格验证
- 确保输入值在预期范围内
-
使用安全库:
- 考虑使用经过安全验证的数学运算库
- 使用编译器内置的安全检查功能
-
静态代码分析:
- 使用源代码静态分析工具进行自动化检测
- 将整数溢出检查纳入代码审查清单
-
防御性编程:
- 假设所有外部输入都可能包含恶意值
- 为所有数值运算添加边界检查
- 使用更大的数据类型存储中间结果(如用
int64_t存储int32_t的运算结果)
7. 检测工具示例
使用360代码卫士等静态分析工具可以有效地检测有符号整数溢出问题:
- 缺陷检测:能够准确识别潜在的整数溢出点
- 风险评级:对整数溢出缺陷通常标记为高风险
- 修复验证:可以验证修复后的代码是否消除了缺陷
8. 总结
有符号整数溢出是C/C++程序中常见的安全隐患,可能导致严重后果。通过:
- 严格的输入验证
- 完善的边界检查
- 防御性编程实践
- 自动化工具辅助
可以有效地预防和消除这类安全问题,提高软件的安全性和可靠性。