summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorPauli Virtanen <pav@iki.fi>2011-04-02 22:56:41 +0200
committerPauli Virtanen <pav@iki.fi>2011-04-02 23:40:58 +0200
commit7b39b9e5ef6d21a199ec95a27ed19b8b1a34bce1 (patch)
tree26f18b75d880bebb9895e9deb8b6bda4c97c0160 /numpy
parent4a43e7449e6251a62338f3b09dc65b568cc2674e (diff)
downloadnumpy-7b39b9e5ef6d21a199ec95a27ed19b8b1a34bce1.tar.gz
BUG: core/pickle: use only non-interned strings as buffer in unpickled arrays (#1708)
Using strings as mutable buffers is "evil" (since strings are immutable), but it should "work" for non-interned strings. On Python 3, bytes are never interned, and so should also work.
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/multiarray/methods.c6
-rw-r--r--numpy/core/tests/test_regression.py14
2 files changed, 20 insertions, 0 deletions
diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c
index e53177519..a4c92b2a1 100644
--- a/numpy/core/src/multiarray/methods.c
+++ b/numpy/core/src/multiarray/methods.c
@@ -1481,7 +1481,13 @@ array_setstate(PyArrayObject *self, PyObject *args)
if (!PyDataType_FLAGCHK(typecode, NPY_LIST_PICKLE)) {
int swap=!PyArray_ISNOTSWAPPED(self);
self->data = datastr;
+#ifndef NPY_PY3K
+ /* Check that the string is not interned */
+ if (!_IsAligned(self) || swap || PyString_CHECK_INTERNED(rawdata)) {
+#else
+ /* Bytes are never interned */
if (!_IsAligned(self) || swap) {
+#endif
intp num = PyArray_NBYTES(self);
self->data = PyDataMem_NEW(num);
if (self->data == NULL) {
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index bcb34d04e..867df6c9d 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -1580,5 +1580,19 @@ class TestRegression(TestCase):
y = np.array(x.flat)
assert_equal(x, [[1,3],[2,4]])
+ def test_pickle_string_overwrite(self):
+ import re
+
+ data = np.array([1], dtype='b')
+ blob = pickle.dumps(data, protocol=1)
+ data = pickle.loads(blob)
+
+ # Check that loads does not clobber interned strings
+ s = re.sub("a(.)", "\x01\\1", "a_")
+ assert_equal(s[0], "\x01")
+ data[0] = 0xbb
+ s = re.sub("a(.)", "\x01\\1", "a_")
+ assert_equal(s[0], "\x01")
+
if __name__ == "__main__":
run_module_suite()