From fa62344452fb80b09c1a0a0db60fbfbd6a02392f Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 10 Jul 2019 13:46:42 +0200 Subject: [PATCH] express: better fix for encrypt_string Python 3 issues A workaround for the bug described in #684 was made in e080d33e313939be26c6859e2ae43f2cfe3f23a5 but this fix is significantly cleaner. Unit test was added. --- .../interrogate/interfaceMakerPythonNative.cxx | 18 +++--------------- panda/src/express/encrypt_string.cxx | 17 ++++++++++------- panda/src/express/encrypt_string.h | 5 +++-- tests/express/test_encrypt.py | 14 ++++++++++++++ 4 files changed, 30 insertions(+), 24 deletions(-) create mode 100644 tests/express/test_encrypt.py diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index d8ce85041c..af30943212 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -6408,21 +6408,9 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap, TypeManager::is_vector_unsigned_char(type)) { // Most types are now handled by the many overloads of Dtool_WrapValue, // defined in py_panda.h. - if (!remap->_has_this && remap->_cppfunc != nullptr && - remap->_cppfunc->get_simple_name() == "encrypt_string" && - return_expr == "return_value") { - // Temporary hack to fix #684 to avoid an ABI change. - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyBytes_FromStringAndSize((char *)return_value.data(), (Py_ssize_t)return_value.size());\n"; - out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromStringAndSize((char *)return_value.data(), (Py_ssize_t)return_value.size());\n"; - out << "#endif\n"; - } else { - indent(out, indent_level) - << "return Dtool_WrapValue(" << return_expr << ");\n"; - } + indent(out, indent_level) + << "return Dtool_WrapValue(" << return_expr << ");\n"; + } else if (TypeManager::is_pointer(type)) { bool is_const = TypeManager::is_const_pointer_to_anything(type); bool owns_memory = remap->_return_value_needs_management; diff --git a/panda/src/express/encrypt_string.cxx b/panda/src/express/encrypt_string.cxx index 6c400d77f7..8c21d986fa 100644 --- a/panda/src/express/encrypt_string.cxx +++ b/panda/src/express/encrypt_string.cxx @@ -17,6 +17,7 @@ #include "encryptStream.h" #include "virtualFileSystem.h" #include "config_express.h" +#include "stringStream.h" using std::istream; using std::istringstream; @@ -26,12 +27,12 @@ using std::string; /** * Encrypts the indicated source string using the given password, and the - * algorithm specified by encryption-algorithm. Returns the encrypted string. + * algorithm specified by encryption-algorithm. Returns the encrypted data. */ -string +vector_uchar encrypt_string(const string &source, const string &password, const string &algorithm, int key_length, int iteration_count) { - ostringstream dest; + StringStream dest; { OEncryptStream encrypt; @@ -48,11 +49,13 @@ encrypt_string(const string &source, const string &password, encrypt.write(source.data(), source.length()); if (encrypt.fail()) { - return string(); + return vector_uchar(); } } - return dest.str(); + vector_uchar result; + dest.swap_data(result); + return result; } /** @@ -64,8 +67,8 @@ encrypt_string(const string &source, const string &password, * easily be detected, and the return value may simply be a garbage string. */ string -decrypt_string(const string &source, const string &password) { - istringstream source_stream(source); +decrypt_string(const vector_uchar &source, const string &password) { + StringStream source_stream(source); ostringstream dest_stream; if (!decrypt_stream(source_stream, dest_stream, password)) { diff --git a/panda/src/express/encrypt_string.h b/panda/src/express/encrypt_string.h index 7b247baefe..caf7f14466 100644 --- a/panda/src/express/encrypt_string.h +++ b/panda/src/express/encrypt_string.h @@ -19,15 +19,16 @@ #ifdef HAVE_OPENSSL #include "filename.h" +#include "vector_uchar.h" BEGIN_PUBLISH -EXPCL_PANDA_EXPRESS std::string +EXPCL_PANDA_EXPRESS vector_uchar encrypt_string(const std::string &source, const std::string &password, const std::string &algorithm = std::string(), int key_length = -1, int iteration_count = -1); EXPCL_PANDA_EXPRESS std::string -decrypt_string(const std::string &source, const std::string &password); +decrypt_string(const vector_uchar &source, const std::string &password); EXPCL_PANDA_EXPRESS bool encrypt_file(const Filename &source, const Filename &dest, const std::string &password, diff --git a/tests/express/test_encrypt.py b/tests/express/test_encrypt.py new file mode 100644 index 0000000000..5624bcae99 --- /dev/null +++ b/tests/express/test_encrypt.py @@ -0,0 +1,14 @@ +from panda3d import core + + +def test_encrypt_string(): + # Test encrypt and then decrypt cycle + enc = core.encrypt_string('abcdefg', '12345') + assert len(enc) > 0 + + dec = core.decrypt_string(enc, '12345') + assert dec == 'abcdefg' + + # Test pre-encrypted string + enc = b'[\x00\x10\x00d\x00\xb5\x7f\xc44Y\xb7\xd9\x15\xe3\xbd\xcf\xb3yK\xfb\xf6' + assert 'test' == core.decrypt_string(enc, '98765')