Browse Source

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.
rdb 6 years ago
parent
commit
fa62344452

+ 3 - 15
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)) {
       TypeManager::is_vector_unsigned_char(type)) {
     // Most types are now handled by the many overloads of Dtool_WrapValue,
     // Most types are now handled by the many overloads of Dtool_WrapValue,
     // defined in py_panda.h.
     // 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)) {
   } else if (TypeManager::is_pointer(type)) {
     bool is_const = TypeManager::is_const_pointer_to_anything(type);
     bool is_const = TypeManager::is_const_pointer_to_anything(type);
     bool owns_memory = remap->_return_value_needs_management;
     bool owns_memory = remap->_return_value_needs_management;

+ 10 - 7
panda/src/express/encrypt_string.cxx

@@ -17,6 +17,7 @@
 #include "encryptStream.h"
 #include "encryptStream.h"
 #include "virtualFileSystem.h"
 #include "virtualFileSystem.h"
 #include "config_express.h"
 #include "config_express.h"
+#include "stringStream.h"
 
 
 using std::istream;
 using std::istream;
 using std::istringstream;
 using std::istringstream;
@@ -26,12 +27,12 @@ using std::string;
 
 
 /**
 /**
  * Encrypts the indicated source string using the given password, and the
  * 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,
 encrypt_string(const string &source, const string &password,
                const string &algorithm, int key_length, int iteration_count) {
                const string &algorithm, int key_length, int iteration_count) {
-  ostringstream dest;
+  StringStream dest;
 
 
   {
   {
     OEncryptStream encrypt;
     OEncryptStream encrypt;
@@ -48,11 +49,13 @@ encrypt_string(const string &source, const string &password,
     encrypt.write(source.data(), source.length());
     encrypt.write(source.data(), source.length());
 
 
     if (encrypt.fail()) {
     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.
  * easily be detected, and the return value may simply be a garbage string.
  */
  */
 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;
   ostringstream dest_stream;
 
 
   if (!decrypt_stream(source_stream, dest_stream, password)) {
   if (!decrypt_stream(source_stream, dest_stream, password)) {

+ 3 - 2
panda/src/express/encrypt_string.h

@@ -19,15 +19,16 @@
 #ifdef HAVE_OPENSSL
 #ifdef HAVE_OPENSSL
 
 
 #include "filename.h"
 #include "filename.h"
+#include "vector_uchar.h"
 
 
 BEGIN_PUBLISH
 BEGIN_PUBLISH
 
 
-EXPCL_PANDA_EXPRESS std::string
+EXPCL_PANDA_EXPRESS vector_uchar
 encrypt_string(const std::string &source, const std::string &password,
 encrypt_string(const std::string &source, const std::string &password,
                const std::string &algorithm = std::string(), int key_length = -1,
                const std::string &algorithm = std::string(), int key_length = -1,
                int iteration_count = -1);
                int iteration_count = -1);
 EXPCL_PANDA_EXPRESS std::string
 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
 EXPCL_PANDA_EXPRESS bool
 encrypt_file(const Filename &source, const Filename &dest, const std::string &password,
 encrypt_file(const Filename &source, const Filename &dest, const std::string &password,

+ 14 - 0
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')