本文将为您提供关于Pythonctypes示例异常的详细介绍,我们还将为您解释python异常处理try的相关知识,同时,我们还将为您提供关于ctypes.CDLL()可从anacondapython
本文将为您提供关于Python ctypes 示例异常的详细介绍,我们还将为您解释python异常处理try的相关知识,同时,我们还将为您提供关于ctypes.CDLL() 可从 anaconda python 安装运行,但不能从“原始”python 安装运行、ctypes.CDLL() 和 ctypes.cdll.LoadLibrary() 有什么区别?、CVE-2021-3177:Python ctypes 缓冲区溢出漏洞分析、Python 3.5,ctypes:TypeError:应使用字节或整数地址(而非str实例)的实用信息。
本文目录一览:- Python ctypes 示例异常(python异常处理try)
- ctypes.CDLL() 可从 anaconda python 安装运行,但不能从“原始”python 安装运行
- ctypes.CDLL() 和 ctypes.cdll.LoadLibrary() 有什么区别?
- CVE-2021-3177:Python ctypes 缓冲区溢出漏洞分析
- Python 3.5,ctypes:TypeError:应使用字节或整数地址(而非str实例)
Python ctypes 示例异常(python异常处理try)
如何解决Python ctypes 示例异常
我正在研究如何通过 ctypes 将带有字符串字段的结构传递给 C。我在 Ubuntu (DigitalOcean) 上使用 python3。我一直在努力让它工作。我在设置 ctypes.c_char_p
对象指向 Python 字符串的 documentation what appears to be a very simple example 中找到。
>>> from ctypes import *
>>> class cell(Structure):
... pass
>>> cell._fields_ = [(''name'',c_char_p),(''next'',POINTER(cell))]
>>> c1=cell()
>>> c1.name = "foo"
但我收到此异常:
TypeError: bytes or integer address expected instead of str instance
根据我的代码运行情况,此错误与我的预期一致。所以,我的问题是,我误解了这个例子还是这个例子不对?
解决方法
这可能是因为 ctypes.c_char_p
是一个字节流,而不是一个字符串。如果你写 c1.name = b''bar''
它应该工作。然后要从中恢复 Python 字符串,您应该使用 c1.name.decode(''utf-8'')
对其进行解码。
ctypes.CDLL() 可从 anaconda python 安装运行,但不能从“原始”python 安装运行
如何解决ctypes.CDLL() 可从 anaconda python 安装运行,但不能从“原始”python 安装运行
我有一个关于 ctypes 的使用的奇怪问题: ctypes 的行为取决于我是使用 anaconda 的 python 安装还是 python.org 的“原始”python 安装(均在 Windows 10 上)。
复制:只需转到 anaconda.com,通过默认安装程序安装 anaconda(和 anaconda python)。转到 python.org 并通过默认安装程序安装 python。
anaconda 安装附带了 mingw(x64) 二进制文件,这些文件至少是一些 .dll 所需的(我在这里不太了解,但至少我正在使用的 dll 需要它们)。 “原始”python 没有这些,因此需要手动添加它们(需要部分或全部(未检查):libatomic-1.dll、libgccc_s_seh-1.dll、libgomp-1.dll、libquadmath- 0.dll、libssp-0.dll、libstdc++-6.dll、libwinpthread-1.dll,只需将它们复制到您正在工作的目录中或将它们的目录添加到PATH)。
现在您有两个版本的 python,每个版本都有自己的 ctypes 版本(我的 anaconda python 版本为 3.8.8,“raw”python 版本为 3.9.5,ctypes 版本均为 1.1.0)。>
尝试通过 anaconda python 加载 dll,例如:
import ctypes
dll = ctypes.CDLL(<insertdllname>)
完全没问题(前提是你在dll的目录下工作,否则你需要指定完整路径)。
尝试相同的“原始”python 安装失败。问题是来自“原始”python 的 ctypes 找不到要加载的 dll 所依赖的 mingw 库。尽管这些库位于工作目录中(或明确地将它们的文件夹添加到 PATH)(两者都在使用 anaconda python 时工作)。仅当将附加库放入 python 安装文件夹(“python.exe”所在的位置)时,才会找到它们。
现在,当我将 ctypes 文件夹从 anaconda 安装复制到“raw”安装的 ctypes 文件夹所在的位置(将 ctypes 从“raw”安装重命名为 ctypes_raw)时,我有两个版本的 ctypes 可用。
使用:
import ctypes_roh
ctypes_roh.CDLL(<insertdllname>)
失败,如上。
import ctypes
ctypes.CDLL(<insertdllname>)
有效,所以显然两个 ctypes 库是不同的,anaconda 安装中的 ctypes 能够在工作目录和 PATH 中查找 dll,而“原始”python 安装中的 ctypes 不能这样做。
import ctypes
import ctypes_raw
ctypes.CDLL(<insertdllname>)
ctypes_raw.CDLL(<insertdllname>)
现在两个调用都有效。显然,从 anaconda ctypes 调用 CDLL 修复了阻止 CDLL 从“原始”ctypes 在工作目录或 PATH 中查找 dll 的任何问题。
所以我的问题是:
- python anaconda 安装中的 ctypes 和 python.org 中的“原始”python 安装中的 ctypes 是否应该不同?
- 有什么区别?为什么来自“原始”python 的 ctypes 无法在工作目录或 PATH 中查找 dll?为什么从 anaconda python 调用 ctypes 会“修复”这个问题?
编辑:在发现“原始”python 安装没有所需的 mingw 库后,我重写了帖子以说明这一点并(希望)澄清剩余的问题。
ctypes.CDLL() 和 ctypes.cdll.LoadLibrary() 有什么区别?
如何解决ctypes.CDLL() 和 ctypes.cdll.LoadLibrary() 有什么区别?
这两种方法似乎都有效(对我来说),但似乎 CDLL()
方法返回一个具有 _handle
属性的对象,该对象可用于通过 ctypes.windll.kernel32.FreeLibrary()
卸载库(至少在 Windows 上 - 我还不知道如何在 Linux 上做到这一点)。
这两种方法有什么区别 - 为什么我会选择一种而不是另一种?
最终,我的目标是能够在 Linux 上的两个 Windows 上加载和卸载库(因为我有一个 3rd 方库,有时似乎会进入损坏状态 - 我希望卸载/重新加载会重置它) .
解决方法
一切都在[Python.Docs]: ctypes - A foreign function library for Python中得到了很好的解释:
class ctypes.CDLL(名称,mode=DEFAULT_MODE,handle=None,use_errno=False,use_last_error=False,winmode=0 )
此类的实例表示加载的共享库。这些库中的函数使用标准的 C 调用约定,并假定返回 int。
...
class ctypes.LibraryLoader(dlltype)
...
LoadLibrary(名称)
将共享库加载到进程中并返回。此方法始终返回库的新实例。
这些预制的库加载器可用:
ctypes.cdll
创建 CDLL 个实例。
所以,第 2nd 表单只是一个方便的包装器,它们之间绝对没有功能上的区别,如下所示:
>>> import ctypes as ct
>>>
>>>
>>> k32_1 = ct.CDLL("kernel32.dll") # 1.
>>> k32_2 = ct.cdll.LoadLibrary("kernel32.dll") # 2.1.
>>> k32_3 = ct.cdll.kernel32 # 2.2.
>>>
>>> k32_1,k32_2,k32_3
(<CDLL ''kernel32.dll'',handle 7fff59100000 at 0x2335c444ee0>,<CDLL ''kernel32.dll'',handle 7fff59100000 at 0x2335b44bc10>,<CDLL ''kernel32'',handle 7fff59100000 at 0x2335c45a790>)
>>> type(k32_1),type(k32_2),type(k32_3)
(<class ''ctypes.CDLL''>,<class ''ctypes.CDLL''>,<class ''ctypes.CDLL''>)
>>>
>>> k32_1._handle == k32_2._handle == k32_3._handle
True
使用最适合您的方式。
2nd 形式(#2.2.)更短(我想这就是它的目的)。
#1. 和 #2.1. 是相同的(#2.1. 可能更具解释性(因为它有 LoadLibrary)) 并且它们允许您从自定义路径或具有与默认值不同的扩展名加载库。就我个人而言,#1. 是我更喜欢的。
更多细节,你可以看看[GitHub]: python/cpython - (master) cpython/Lib/ctypes/__init__.py,特别是LibraryLoader在实现中(cdll实际上是,并且)很容易理解.
提醒一下(可能您已经知道自己在做什么):加载和卸载库有时会很棘手。
CVE-2021-3177:Python ctypes 缓冲区溢出漏洞分析
起步
相关的 issue 与 修复 ,从描述来看,这是一个 sprintf
函数引发的缓冲区溢出漏洞。
补丁获取链接:https://python-security.readthedocs.io/vuln/ctypes-buffer-overflow-pycarg_repr.html
复现
使用 3.8.7
进行复现:
这个漏洞在 3.8.8
便已修复:
分析
通过生成的 coredump
文件,查看异常堆栈:
注意到 Python-3.8.7/Modules/_ctypes/callproc.c
:
PyCArg_repr(PyCArgObject *self)
{
char buffer[256];
switch(self->tag) {
...
case ''d'':
sprintf(buffer, "<cparam ''%c'' (%f)>", // 这行引发异常
self->tag, self->value.d); // value.d 的值是 1e300
break;
变量 buffer
的长度为 256 ,因此长度不够使得 sprintf
的缓冲区溢出,造成内存的破坏。
写个简单的 C 代码复现这个问题:
#include <stdio.h>
int main(int argc, char **argv) {
char buffer[256];
char tag = ''d'';
double value = 1e300;
sprintf(buffer, "<cparam ''%c'' (%f)>", tag, value);
return 0;
}
我在中间加了一行 printf("%f\n", value);
再次执行:
这个长度已经超过 buffer
定义的长度了。double
类型,表示的小数位数能很大,所以至少可以覆盖 300 个字节;如果是 float
类型,就要小的多了。
在新版本之中该问题已经得到修复,已经将 sprintf
换成 PyUnicode_FromFormat
。
参考链接
- https://bugs.python.org/issue42938
- https://blog.python.org/2021/02/python-392-and-388-are-now-available.html
- https://www.randori.com/blog/cve-2021-3177-vulnerability-analysis/
- http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-202101-1467
- https://access.redhat.com/security/cve/cve-2021-3177
Python 3.5,ctypes:TypeError:应使用字节或整数地址(而非str实例)
我的ctypes有问题。我认为我的类型转换是正确的,并且该错误对我来说没有意义。第“ arg-ct.c_char_p(logfilepath)行错误”
TypeError:预期为字节或整数地址,而不是str实例
我在python 3.5和3.4中都尝试过。
我正在调用的功能:
stream_initialize(''stream_log.txt'')
Stream_initialize代码”
def stream_initialize(logfilepath): f = shim.stream_initialize arg = ct.c_char_p(logfilepath) result = f(arg) if result: print(find_shim_error(result))
答案1
小编典典c_char_p
需要bytes
对象,因此您必须先将其转换string
为bytes
:
ct.c_char_p(logfilepath.encode(''utf-8''))
另一种解决方案是使用c_wchar_p
带有的类型string
。
今天关于Python ctypes 示例异常和python异常处理try的讲解已经结束,谢谢您的阅读,如果想了解更多关于ctypes.CDLL() 可从 anaconda python 安装运行,但不能从“原始”python 安装运行、ctypes.CDLL() 和 ctypes.cdll.LoadLibrary() 有什么区别?、CVE-2021-3177:Python ctypes 缓冲区溢出漏洞分析、Python 3.5,ctypes:TypeError:应使用字节或整数地址(而非str实例)的相关知识,请在本站搜索。
本文标签: