【发布时间】:2019-10-28 00:47:32
【问题描述】:
众所周知pysha3与pypy不兼容,因为3年未维护,我只好自己修改。
当然,正确的方法是用纯 Python 代码执行完全重写(这也将导致比当前代码更快的实现),但我缺乏所需的密码学和背景数学知识来做到这一点, 并且使用它的程序非常密集(它需要一个没有 gil 的 python3 用于多线程或带有 jit 的 python3)。
必须由C代码调用的单点故障boils down to this function:
static PyObject*
_Py_strhex(const char* argbuf, const Py_ssize_t arglen)
{
static const char *hexdigits = "0123456789abcdef";
PyObject *retval;
#if PY_MAJOR_VERSION >= 3
Py_UCS1 *retbuf;
#else
char *retbuf;
#endif
Py_ssize_t i, j;
assert(arglen >= 0);
if (arglen > PY_SSIZE_T_MAX / 2)
return PyErr_NoMemory();
#if PY_MAJOR_VERSION >= 3
retval = PyUnicode_New(arglen * 2, 127);
if (!retval)
return NULL;
retbuf = PyUnicode_1BYTE_DATA(retval);
#else
retval = PyString_FromStringAndSize(NULL, arglen * 2);
if (!retval)
return NULL;
retbuf = PyString_AsString(retval);
if (!retbuf) {
Py_DECREF(retval);
return NULL;
}
#endif
/* make hex version of string, taken from shamodule.c */
for (i=j=0; i < arglen; i++) {
unsigned char c;
c = (argbuf[i] >> 4) & 0xf;
retbuf[j++] = hexdigits[c];
c = argbuf[i] & 0xf;
retbuf[j++] = hexdigits[c];
}
return retval;
}
pypy 的 cython 兼容级别为 3.2,PyUnicode_New 是在 python3.3 中引入的。
我尝试用锤子方法修复它,用以下 cython 代码替换整个文件:
cdef Py_strhex(const char* argbuf, const Py_ssize_t arglen):
return (argbuf[:arglen]).hex()
但它似乎触发了分段错误,包括编译和使用官方 Python 实现。而且使用官方的 PyPy 二进制文件,我没有 gdb 的调试符号,所以我不知道为什么。
(gdb) bt
#0 0x00007ffff564cd00 in pypy_g_text_w__pypy_interpreter_baseobjspace_W_Root () from /usr/lib64/pypy3.6-v7.2.0-linux64/bin/libpypy3-c.so
#1 0x00007ffff5d721a8 in pypy_g_getattr () from /usr/lib64/pypy3.6-v7.2.0-linux64/bin/libpypy3-c.so
#2 0x00007ffff543a8bd in pypy_g_dispatcher_15 () from /usr/lib64/pypy3.6-v7.2.0-linux64/bin/libpypy3-c.so
#3 0x00007ffff5ab909b in pypy_g_wrapper_second_level.star_2_14 () from /usr/lib64/pypy3.6-v7.2.0-linux64/bin/libpypy3-c.so
#4 0x00007fffd7212372 in _Py_strhex.2738 () from /usr/lib64/pypy3.6-v7.2.0-linux64/site-packages/pysha3-1.0.3.dev1-py3.6-linux-x86_64.egg/_pysha3.pypy3-72-x86_64-linux-gnu.so
#5 0x00007fffd7217990 in _sha3_sha3_224_hexdigest_impl.2958 () from /usr/lib64/pypy3.6-v7.2.0-linux64/site-packages/pysha3-1.0.3.dev1-py3.6-linux-x86_64.egg/_pysha3.pypy3-72-x86_64-linux-gnu.so
#6 0x00007ffff5be2170 in pypy_g_generic_cpy_call__StdObjSpaceConst_funcPtr_SomeI_5 () from /usr/lib64/pypy3.6-v7.2.0-linux64/bin/libpypy3-c.so
#7 0x00007ffff54b25cd in pypy_g.call_1 () from /usr/lib64/pypy3.6-v7.2.0-linux64/bin/libpypy3-c.so
#8 0x00007ffff56715b9 in pypy_g_BuiltinCodePassThroughArguments1_funcrun_obj () from /usr/lib64/pypy3.6-v7.2.0-linux64/bin/libpypy3-c.so
#9 0x00007ffff56ffc06 in pypy_g_call_valuestack__AccessDirect_None () from /usr/lib64/pypy3.6-v7.2.0-linux64/bin/libpypy3-c.so
#10 0x00007ffff5edb29b in pypy_g_CALL_METHOD__AccessDirect_star_1 () from /usr/lib64/pypy3.6-v7.2.0-linux64/bin/libpypy3-c.so
将默认 Linux 堆栈深度增加到 65Mb 不会改变发生段错误的递归深度,因此即使堆栈深度大于 200,这似乎也与堆栈溢出无关。
【问题讨论】:
-
是否有机会将您的代码库更新到 Python 3.6 或更高版本?
-
@Selcuk PyPy 支持 python3.6,但仅限于 python 级别。在 C 级别,它仍然处于 3.2 级别的兼容性。即使是最新版本的pysha3也没有运行的功能。
-
对不起,我说的是使用 Python 3.6 自带的内置
hashlib.sha3。 -
@Selcuk 是为了做 sha3 的 keccak 变体,以便与以太坊兼容,所以很遗憾它不兼容。项目本身不使用 pysha3:它被许多 pip 依赖项使用,因此修复这个问题会更简单。
-
我不知道你为什么说C级还是3.2级。也许它错过了一个特定的 API 函数,但如果你报告它,我们会修复这个错误。
标签: python c python-3.x cython pypy