[PR PATCH] [Updated] Python3 misc bugfixes

Douglas Bagnall douglas.bagnall at catalyst.net.nz
Tue Mar 20 21:48:41 UTC 2018


On 08/03/18 10:15, Github bot account via samba-technical wrote:
> There is an updated pull request by noelpower against master on the Samba Samba Github repository
> 
> https://github.com/noelpower/samba python3-misc-bugfixes
> https://github.com/samba-team/samba/pull/138
> 
> Python3 misc bugfixes
> 
Noel,

I think we should have the additional test in the last of these patches
squashed into your test patch.

It checks that the long-form bytes GUID is equal to the long-form string
GUID.

cheers,

Douglas
-------------- next part --------------
From 7b2c4f01be72b9ff98aaa375d82c7c2dd2e932c9 Mon Sep 17 00:00:00 2001
From: Noel Power <noel.power at suse.com>
Date: Thu, 22 Feb 2018 12:49:36 +0000
Subject: [PATCH 1/5] s4/dsdb: python3 api should take 'bytes'

Attributes are properly represented by 'bytes' and *maybe* can be
converted into strings (if they are text).
py_dsdb_normalise_attributes currently expects strings, this is fine
in python2 however in python3 we need to actually pass a 'bytes'
class.

Signed-off-by: Noel Power <noel.power at suse.com>
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
---
 source4/dsdb/pydsdb.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index d38d7095efa..8d84a16dd18 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -625,7 +625,6 @@ static PyObject *py_dsdb_normalise_attributes(PyObject *self, PyObject *args)
 	TALLOC_CTX *tmp_ctx;
 	WERROR werr;
 	Py_ssize_t i;
-	Py_ssize_t _size;
 	PyTypeObject *py_type = NULL;
 	PyObject *module = NULL;
 
@@ -688,13 +687,16 @@ static PyObject *py_dsdb_normalise_attributes(PyObject *self, PyObject *args)
 
 		for (i = 0; i < el->num_values; i++) {
 			PyObject *item = PyList_GetItem(el_list, i);
-			if (!PyStr_Check(item)) {
-				PyErr_Format(PyExc_TypeError, "ldif_elements should be strings");
+			if (!PyBytes_Check(item)) {
+				PyErr_Format(PyExc_TypeError,
+					     "ldif_element type should be "
+					     PY_DESC_PY3_BYTES
+					     );
 				talloc_free(tmp_ctx);
 				return NULL;
 			}
-			el->values[i].data = (uint8_t *)PyStr_AsUTF8AndSize(item, &_size);;
-			el->values[i].length = _size;
+			el->values[i].data = (uint8_t *)PyBytes_AsString(item);
+			el->values[i].length = PyBytes_Size(item);
 		}
 	}
 
-- 
2.14.1


From b8c551d96550261d926b570de1cb6c64fddc67b4 Mon Sep 17 00:00:00 2001
From: Noel Power <noel.power at suse.com>
Date: Wed, 7 Mar 2018 14:39:54 +0000
Subject: [PATCH 2/5] python: Add compatability helpers to determine if type is
 really bytes

py3compat has PyBytes_Check macro which evalates to PyString_Check in
python2. To help switch behaviour based on whether you are dealing
with the bytes type the following macros have been added.

IsPy3Bytes
IsPy3BytesOrString

IsPy3Bytes will evaluate to false in python2 and will return the
expected result in python3. IsPy3BytesOrString will test for string
type alone in python2 or bytes and string in python3.

Signed-off-by: Noel Power <noel.power at suse.com>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
---
 python/py3compat.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/python/py3compat.h b/python/py3compat.h
index ce317c65f8e..5fa57f323d5 100644
--- a/python/py3compat.h
+++ b/python/py3compat.h
@@ -82,6 +82,19 @@
 #define PY_DESC_PY3_BYTES "bytes"
 #define PY_DESC_PY3_STRING "string"
 
+/* Determine if object is really bytes, for code that runs
+ * in python2 & python3 (note: PyBytes_Check is replaced by
+ * PyString_Check in python2) so care needs to be taken when
+ * writing code that will check if incoming type is bytes that
+ * will work as expected in python2 & python3
+ */
+
+#define IsPy3Bytes PyBytes_Check
+
+#define IsPy3BytesOrString(pystr) \
+    (PyStr_Check(pystr) || PyBytes_Check(pystr))
+
+
 /* Ints */
 
 #define PyInt_Type PyLong_Type
@@ -152,6 +165,17 @@
 #define PY_DESC_PY3_BYTES "string"
 #define PY_DESC_PY3_STRING "unicode"
 
+/* Determine if object is really bytes, for code that runs
+ * in python2 & python3 (note: PyBytes_Check is replaced by
+ * PyString_Check in python2) so care needs to be taken when
+ * writing code that will check if incoming type is bytes that
+ * will work as expected in python2 & python3
+ */
+
+#define IsPy3Bytes(pystr) false
+
+#define IsPy3BytesOrString PyStr_Check
+
 /* PyArg_ParseTuple/Py_BuildValue argument */
 
 #define PYARG_BYTES_LEN "s#"
-- 
2.14.1


From 5f4c2f73167e059d233a9cbb7a8316d2b0502c55 Mon Sep 17 00:00:00 2001
From: Noel Power <noel.power at suse.com>
Date: Wed, 28 Feb 2018 16:25:55 +1300
Subject: [PATCH 3/5] s4/librpc: GUID should accept string or bytes in python3

In python3 you can't store a binary blob GUID in a string class, you
need to use 'bytes'. This change ensures python2 code continues to use
a string and in python3 both 'bytes' and 'string' are supported.

Signed-off-by: Noel Power <noel.power at suse.com>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
---
 source4/librpc/ndr/py_misc.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/source4/librpc/ndr/py_misc.c b/source4/librpc/ndr/py_misc.c
index 6316b9b6704..849a11460a4 100644
--- a/source4/librpc/ndr/py_misc.c
+++ b/source4/librpc/ndr/py_misc.c
@@ -97,11 +97,19 @@ static int py_GUID_init(PyObject *self, PyObject *args, PyObject *kwargs)
 		DATA_BLOB guid_val;
 		Py_ssize_t _size;
 
-		if (!PyStr_Check(str)) {
-			PyErr_SetString(PyExc_TypeError, "Expected a string argument to GUID()");
+		if (!IsPy3BytesOrString(str)) {
+			PyErr_SetString(PyExc_TypeError, "Expected a string or bytes argument to GUID()");
 			return -1;
 		}
-		guid_val.data = (uint8_t *)PyStr_AsUTF8AndSize(str, &_size);
+
+		if (!IsPy3Bytes(str)) {
+			guid_val.data =
+				(uint8_t *)PyStr_AsUTF8AndSize(str,
+							       &_size);
+		} else {
+			guid_val.data = (uint8_t *)PyBytes_AsString(str);
+			_size = PyBytes_Size(str);
+		}
 		guid_val.length = _size;
 		status = GUID_from_data_blob(&guid_val, guid);
 		if (!NT_STATUS_IS_OK(status)) {
-- 
2.14.1


From 3d3a7645ddae139204805d66c8baab8f00317cf5 Mon Sep 17 00:00:00 2001
From: Noel Power <noel.power at suse.com>
Date: Wed, 28 Feb 2018 14:40:26 +0000
Subject: [PATCH 4/5] samba python tests: Ensure GUIDTests cover all input
 formats

Signed-off-by: Noel Power <noel.power at suse.com>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
---
 python/samba/tests/dcerpc/misc.py | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/python/samba/tests/dcerpc/misc.py b/python/samba/tests/dcerpc/misc.py
index 2ec095063e9..a66f6c25bd0 100644
--- a/python/samba/tests/dcerpc/misc.py
+++ b/python/samba/tests/dcerpc/misc.py
@@ -23,6 +23,9 @@ from samba.compat import PY3
 
 text1 = "76f53846-a7c2-476a-ae2c-20e2b80d7b34"
 text2 = "344edffa-330a-4b39-b96e-2c34da52e8b1"
+text3_s = "00112233-4455-6677-8899-aabbccddeeff"
+text3_b = b"\x33\x22\x11\x00\x55\x44\x77\x66\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
+text3_h = "33221100554477668899aabbccddeeff"
 
 
 if PY3:
@@ -55,6 +58,18 @@ class GUIDTests(samba.tests.TestCase):
         self.assertEquals(guid1, guid2)
         self.assertEquals(0, cmp(guid1, guid2))
 
+    def test_binary_format(self):
+        guid = misc.GUID(text3_b)
+        self.assertEquals(text3_s, str(guid))
+
+    def test_strhex_format(self):
+        guid = misc.GUID(text3_h)
+        self.assertEquals(text3_s, str(guid))
+
+    def test_bracketed_format(self):
+        guid = misc.GUID('{'+ text3_s + '}')
+        self.assertEquals(text3_s, str(guid))
+
 
 class PolicyHandleTests(samba.tests.TestCase):
 
-- 
2.14.1


From 9119709c0ad81ec8d83953ac3d0854d78c509036 Mon Sep 17 00:00:00 2001
From: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Fri, 16 Mar 2018 16:33:44 +1300
Subject: [PATCH 5/5] tests/dcerpc/misc.GUID: test that long-form py3 bytes
 works

Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
---
 python/samba/tests/dcerpc/misc.py | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/python/samba/tests/dcerpc/misc.py b/python/samba/tests/dcerpc/misc.py
index a66f6c25bd0..cf3dcbf3bb4 100644
--- a/python/samba/tests/dcerpc/misc.py
+++ b/python/samba/tests/dcerpc/misc.py
@@ -24,7 +24,8 @@ from samba.compat import PY3
 text1 = "76f53846-a7c2-476a-ae2c-20e2b80d7b34"
 text2 = "344edffa-330a-4b39-b96e-2c34da52e8b1"
 text3_s = "00112233-4455-6677-8899-aabbccddeeff"
-text3_b = b"\x33\x22\x11\x00\x55\x44\x77\x66\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
+text3_b = b"00112233-4455-6677-8899-aabbccddeeff"
+text3_b16 = b"\x33\x22\x11\x00\x55\x44\x77\x66\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
 text3_h = "33221100554477668899aabbccddeeff"
 
 
@@ -58,10 +59,14 @@ class GUIDTests(samba.tests.TestCase):
         self.assertEquals(guid1, guid2)
         self.assertEquals(0, cmp(guid1, guid2))
 
-    def test_binary_format(self):
+    def test_bytes_equals_string(self):
         guid = misc.GUID(text3_b)
         self.assertEquals(text3_s, str(guid))
 
+    def test_binary_format(self):
+        guid = misc.GUID(text3_b16)
+        self.assertEquals(text3_s, str(guid))
+
     def test_strhex_format(self):
         guid = misc.GUID(text3_h)
         self.assertEquals(text3_s, str(guid))
-- 
2.14.1



More information about the samba-technical mailing list