Page 40 - 《软件学报》2026年第7期
P. 40

胡明哲 等: Python  软件包库中   C/C++外部语言调用的安全性分析                                        2725


                 32  字节内存, 错误地使用     C  标准库的  free 函数释放该内存将绕过       Python  内存管理器, 可能破坏其内部状态导致
                 未定义行为甚至内存损坏. 类似地, 外部函数实现              demo_rawmalloc_pymemfree 通过  PyMem_RawMalloc 分配原始
                 内存块, 但错误地使用      PyMem_Free 进行释放. 不同族内存接口的内部实现机制不同, 不匹配的使用会导致内存回
                 收异常, 引发崩溃或堆结构破坏.
                 代码  2. 构造析构不匹配测例.

                 //测例  1: PyMem_Malloc 错配  free (M2.1)
                 static PyObject* demo_pymem_malloc_free(PyObject *self, PyObject *args) {
                   char *buf = PyMem_Malloc(32);
                   if (!buf) return PyErr_NoMemory(), NULL;
                   free(buf); //错误: PyMem_Malloc 应对应  PyMem_Free
                   Py_RETURN_NONE;
                 }
                 //测例  2: PyMem_RawMalloc 错配  PyMem_Free (M2.1)
                 static PyObject* demo_rawmalloc_pymemfree(PyObject *self, PyObject *args) {
                   void *buf = PyMem_RawMalloc(64);
                   if (!buf) return PyErr_NoMemory(), NULL;
                   PyMem_Free(buf); //错误: PyMem_RawMalloc 应对应  PyMem_RawFree
                   Py_RETURN_NONE;
                 }
                    除了不同域之间内存操作          Python/C API 错配的问题外, 在表   2  中同一族内存接口内部, 重复释放、释放后使
                 用、内存泄漏、非法释放、偏移释放等              C  语言经典内存管理错误仍然存在, 我们将其统一记为非法内存分配与
                 释放  (M2.2). 漏洞测例如代码    3  所示. 代码  3  的测例  1  会破坏堆内存分配器的空闲链表结构或分配元数据, 进而引
                 发程序崩溃. 代码     3  的测例  2  堆中释放的内存可能已被回收到空闲池或分配给其他对象, 后续的写操作将产生未
                 定义行为, 可能带来数据破坏、非法访问和内存劫持的风险.
                 代码  3. 非法内存分配与释放测例.
                 //测例  1: 重复释放  (M2.2)
                 static PyObject* demo_double_free(PyObject *self, PyObject *args) {
                   char *buf = PyMem_Malloc(16);
                   if (!buf) return PyErr_NoMemory(), NULL;
                   PyMem_Free(buf);
                   PyMem_Free(buf); //错误
                   Py_RETURN_NONE;
                 }
                 //测例  2: 释放后使用  (M2.2)
                 static PyObject* demo_use_after_free(PyObject *self, PyObject *args) {
                   char *buf = PyMem_Malloc(16);
                   if (!buf) return PyErr_NoMemory(), NULL;
                   PyMem_Free(buf);
                   buf[0] = “X”; //错误: 释放后写入
                   Py_RETURN_NONE;
                 }
   35   36   37   38   39   40   41   42   43   44   45