SWIG 编码错误的字符串崩溃 Python
SWIG wrong encoded string crashes Python
我遇到了一个问题,我所有处理字符串的 SWIG 包装器都崩溃了如果我在 std::string 中传递错误的编码字符串,我的意思是包含 èé 等的字符串,字符对当前有效语言环境,但 UTF-8 无效。
在我的代码方面,我已经解决了将输入解析为宽字符串并将它们转换为 UTF-8 的问题,但我想用异常而不是崩溃来捕获这类错误,这不是应该的 PyUnicode_Check 使用这些字符串失败 ?
Swig 在调用 PyString_AsStringAndSize() 时实际上在 SWIG_AsCharPtrAndSize() 中崩溃,这是 swig 生成的代码:
SWIGINTERN int
SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
{
#if PY_VERSION_HEX>=0x03000000
#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR)
if (PyBytes_Check(obj))
#else
if (PyUnicode_Check(obj))
#endif
#else
if (PyString_Check(obj))
#endif
{
char *cstr; Py_ssize_t len;
#if PY_VERSION_HEX>=0x03000000
#if !defined(SWIG_PYTHON_STRICT_BYTE_CHAR)
if (!alloc && cptr) {
/* We can't allow converting without allocation, since the internal
representation of string in Python 3 is UCS-2/UCS-4 but we require
a UTF-8 representation.
TODO(bhy) More detailed explanation */
return SWIG_RuntimeError;
}
obj = PyUnicode_AsUTF8String(obj);
if(alloc) *alloc = SWIG_NEWOBJ;
#endif
PyBytes_AsStringAndSize(obj, &cstr, &len);
#else
PyString_AsStringAndSize(obj, &cstr, &len);
#endif
if (cptr) {
崩溃恰好进入最后一个 PyString_AsStringAndSize 可见。
我注意到字符串作为 std::string 传递,但在 const char* 中也会发生,没有任何区别。
多谢指教!
无法重现。如果此示例无法解决您的问题并需要进一步帮助,请编辑您的问题并添加 Minimal, Complete, Verifable Example:
test.i
%module test
%include <std_string.i>
%inline %{
#include <string>
std::string func(std::string s)
{
return '[' + s + ']';
}
%}
演示:
Python 3.3.5 (v3.3.5:62cf4e77f785, Mar 9 2014, 10:35:05) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> test.func('ábc')
'[ábc]'
问题出在我们仍在使用的 3.3.0 版本上,更新到 3.3.7 解决了这个问题,在 Python 发行说明中修复了几个关于 PyUnicode_Check[=10 的错误=]
我遇到了一个问题,我所有处理字符串的 SWIG 包装器都崩溃了如果我在 std::string 中传递错误的编码字符串,我的意思是包含 èé 等的字符串,字符对当前有效语言环境,但 UTF-8 无效。
在我的代码方面,我已经解决了将输入解析为宽字符串并将它们转换为 UTF-8 的问题,但我想用异常而不是崩溃来捕获这类错误,这不是应该的 PyUnicode_Check 使用这些字符串失败 ?
Swig 在调用 PyString_AsStringAndSize() 时实际上在 SWIG_AsCharPtrAndSize() 中崩溃,这是 swig 生成的代码:
SWIGINTERN int
SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
{
#if PY_VERSION_HEX>=0x03000000
#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR)
if (PyBytes_Check(obj))
#else
if (PyUnicode_Check(obj))
#endif
#else
if (PyString_Check(obj))
#endif
{
char *cstr; Py_ssize_t len;
#if PY_VERSION_HEX>=0x03000000
#if !defined(SWIG_PYTHON_STRICT_BYTE_CHAR)
if (!alloc && cptr) {
/* We can't allow converting without allocation, since the internal
representation of string in Python 3 is UCS-2/UCS-4 but we require
a UTF-8 representation.
TODO(bhy) More detailed explanation */
return SWIG_RuntimeError;
}
obj = PyUnicode_AsUTF8String(obj);
if(alloc) *alloc = SWIG_NEWOBJ;
#endif
PyBytes_AsStringAndSize(obj, &cstr, &len);
#else
PyString_AsStringAndSize(obj, &cstr, &len);
#endif
if (cptr) {
崩溃恰好进入最后一个 PyString_AsStringAndSize 可见。 我注意到字符串作为 std::string 传递,但在 const char* 中也会发生,没有任何区别。
多谢指教!
无法重现。如果此示例无法解决您的问题并需要进一步帮助,请编辑您的问题并添加 Minimal, Complete, Verifable Example:
test.i
%module test
%include <std_string.i>
%inline %{
#include <string>
std::string func(std::string s)
{
return '[' + s + ']';
}
%}
演示:
Python 3.3.5 (v3.3.5:62cf4e77f785, Mar 9 2014, 10:35:05) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> test.func('ábc')
'[ábc]'
问题出在我们仍在使用的 3.3.0 版本上,更新到 3.3.7 解决了这个问题,在 Python 发行说明中修复了几个关于 PyUnicode_Check[=10 的错误=]