Page 41 - 《软件学报》2026年第7期
P. 41
2726 软件学报 2026 年第 37 卷第 7 期
2.1.3 缓冲区溢出 (M3)
Python 语言提供包含编译辅助的边界检查机制, 开发者无需关心缓冲区边界, 甚至可以通过负数来倒序索引;
而 C/C++不具备运行时的边界检查能力. 当 Python 向 C/C++外部函数传递字符串、字节流、对象指针等数据时,
若互操作程序未对数据类型或长度做充分校验, 使用如 strcpy、memcpy、PyArg_ParseTuple 等直接操作指针的函
数, 便可能在处理不受信任输入时写入超出目标缓冲区的内存, 触发缓冲区越界访问 (M3.1).
如代码 4 所示, 外部函数实现 unsafe_copy 使用 16 字节固定大小的缓冲区接收来自 Python 的字符串输入, 但
在未检查输入长度的情况下直接调用 strcpy 复制内容, 导致当传入字符串超过 16 字节时发生栈缓冲区溢出.
代码 4. 缓冲区越界访问 (M3.1) 测例.
static PyObject* unsafe_copy(PyObject* self, PyObject* args) {
const char* input;
char buffer[16];
if (!PyArg_ParseTuple(args, “s”, &input)) return NULL;
strcpy(buffer, input); //不安全的字符串复制 (未检查长度)
return PyUnicode_FromString(buffer);
}
2.2 类型系统
2.2.1 整数溢出 (T1)
C/C++的整数类型 (如 int、long 等) 具有固定的字长和取值范围; 而 Python 则支持统一的长整型表示, 能够动
态扩展以适应不同的数值大小. 这一类型系统上的差异导致数据从 Python 传至 C/C++侧时可能引发整数溢出漏
洞. 若外部函数从 Python 侧得到的实参超出目标 C/C++类型的表示范围, 就需要跨语言接口程序进行有效的边界
检查或类型转换, 否则便可能导致截断、符号翻转、未定义行为等安全性漏洞.
如代码 5 所示, 外部函数实现 add_one 在调用 Python/C API 函数 PyLong_AsLong 时, 将 Python 侧传入的任
意精度整数转换为 C 中的 long 类型对象. 若传入的整型值超出 long 类型的表示范围, 将引发数值截断或转换失
败, 导致运行时错误或隐式信息丢失. 这一漏洞被归类为跨语言传参溢出 (T1.1).
代码 5. 整数溢出测例.
static PyObject* add_one(PyObject* self, PyObject* args) {
PyObject* input_obj; long num; int x;
if (!PyArg_ParseTuple(args, “O”, &input_obj)) return NULL;
//将 Python 整数转换为 C long 类型, 此时若 Python 端传入数据过大可能发生截断 (T1.1)
num = PyLong_AsLong(input_obj);
if (num == −1 && PyErr_Occurred()) return NULL;
x = (int)num; //显式地转换为 int(可能导致溢出)
x += x; //接口层运算可能导致溢出, 无法返回有效值 (T1.2)
return PyLong_FromLong(x);
}
其次, 即便跨语言传参过程中转换成功, 由于接口代码可以进行 C/C++的强制类型转换和整数运算, 仍存在因
整数宽度不足而导致接口层运算溢出 (T1.2), 进而影响外部函数返回的正确性.
2.2.2 类型一致性错误 (T2)
在跨语言传参过程中, PyArg_ParseXXX 族 Python/C API 函数被用于外部调用的参数解析, 其依赖格式化字

