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 函数被用于外部调用的参数解析, 其依赖格式化字
   36   37   38   39   40   41   42   43   44   45   46