1eb4b9
From b272ff74ae319a82e4d3e3de1348b2a6115f6501 Mon Sep 17 00:00:00 2001
1eb4b9
From: Paul Ivanov <pivanov5@bloomberg.net>
1eb4b9
Date: Wed, 30 Jan 2019 14:22:44 -0800
1eb4b9
Subject: [PATCH] BUG: load fails when using pickle without allow_pickle=True
1eb4b9
1eb4b9
a partial mitigation of #12759.
1eb4b9
1eb4b9
see also https://nvd.nist.gov/vuln/detail/CVE-2019-6446
1eb4b9
---
1eb4b9
 numpy/core/tests/test_regression.py |  2 +-
1eb4b9
 numpy/lib/format.py                 |  8 ++++++--
1eb4b9
 numpy/lib/npyio.py                  | 17 ++++++++++++-----
1eb4b9
 numpy/lib/tests/test_format.py      | 15 +++++++++------
1eb4b9
 numpy/lib/tests/test_io.py          |  2 +-
1eb4b9
 5 files changed, 29 insertions(+), 15 deletions(-)
1eb4b9
1eb4b9
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
1eb4b9
index 52793d453..b144aec17 100644
1eb4b9
--- a/numpy/core/tests/test_regression.py
1eb4b9
+++ b/numpy/core/tests/test_regression.py
1eb4b9
@@ -96,7 +96,7 @@ class TestRegression(object):
1eb4b9
         ca = np.char.array(np.arange(1000, 1010), itemsize=4)
1eb4b9
         ca.dump(f)
1eb4b9
         f.seek(0)
1eb4b9
-        ca = np.load(f)
1eb4b9
+        ca = np.load(f, allow_pickle=True)
1eb4b9
         f.close()
1eb4b9
 
1eb4b9
     def test_noncontiguous_fill(self):
1eb4b9
diff --git a/numpy/lib/format.py b/numpy/lib/format.py
1eb4b9
index 363bb2101..e6144b3a6 100644
1eb4b9
--- a/numpy/lib/format.py
1eb4b9
+++ b/numpy/lib/format.py
1eb4b9
@@ -602,7 +602,7 @@ def write_array(fp, array, version=None, allow_pickle=True, pickle_kwargs=None):
1eb4b9
                 fp.write(chunk.tobytes('C'))
1eb4b9
 
1eb4b9
 
1eb4b9
-def read_array(fp, allow_pickle=True, pickle_kwargs=None):
1eb4b9
+def read_array(fp, allow_pickle=False, pickle_kwargs=None):
1eb4b9
     """
1eb4b9
     Read an array from an NPY file.
1eb4b9
 
1eb4b9
@@ -612,7 +612,11 @@ def read_array(fp, allow_pickle=True, pickle_kwargs=None):
1eb4b9
         If this is not a real file object, then this may take extra memory
1eb4b9
         and time.
1eb4b9
     allow_pickle : bool, optional
1eb4b9
-        Whether to allow reading pickled data. Default: True
1eb4b9
+        Whether to allow writing pickled data. Default: False
1eb4b9
+
1eb4b9
+        .. versionchanged:: 1.14.3
1eb4b9
+            Made default False in response to CVE-2019-6446.
1eb4b9
+
1eb4b9
     pickle_kwargs : dict
1eb4b9
         Additional keyword arguments to pass to pickle.load. These are only
1eb4b9
         useful when loading object arrays saved on Python 2 when using
1eb4b9
diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py
1eb4b9
index 76b135cc2..ef84d68fd 100644
1eb4b9
--- a/numpy/lib/npyio.py
1eb4b9
+++ b/numpy/lib/npyio.py
1eb4b9
@@ -130,7 +130,11 @@ class NpzFile(object):
1eb4b9
         An object on which attribute can be performed as an alternative
1eb4b9
         to getitem access on the `NpzFile` instance itself.
1eb4b9
     allow_pickle : bool, optional
1eb4b9
-        Allow loading pickled data. Default: True
1eb4b9
+        Allow loading pickled data. Default: False
1eb4b9
+
1eb4b9
+        .. versionchanged:: 1.14.3
1eb4b9
+            Made default False in response to CVE-2019-6446.
1eb4b9
+
1eb4b9
     pickle_kwargs : dict, optional
1eb4b9
         Additional keyword arguments to pass on to pickle.load.
1eb4b9
         These are only useful when loading object arrays saved on
1eb4b9
@@ -166,7 +170,7 @@ class NpzFile(object):
1eb4b9
 
1eb4b9
     """
1eb4b9
 
1eb4b9
-    def __init__(self, fid, own_fid=False, allow_pickle=True,
1eb4b9
+    def __init__(self, fid, own_fid=False, allow_pickle=False,
1eb4b9
                  pickle_kwargs=None):
1eb4b9
         # Import is postponed to here since zipfile depends on gzip, an
1eb4b9
         # optional component of the so-called standard library.
1eb4b9
@@ -265,7 +269,7 @@ class NpzFile(object):
1eb4b9
         return self.files.__contains__(key)
1eb4b9
 
1eb4b9
 
1eb4b9
-def load(file, mmap_mode=None, allow_pickle=True, fix_imports=True,
1eb4b9
+def load(file, mmap_mode=None, allow_pickle=False, fix_imports=True,
1eb4b9
          encoding='ASCII'):
1eb4b9
     """
1eb4b9
     Load arrays or pickled objects from ``.npy``, ``.npz`` or pickled files.
1eb4b9
@@ -287,8 +291,11 @@ def load(file, mmap_mode=None, allow_pickle=True, fix_imports=True,
1eb4b9
         Allow loading pickled object arrays stored in npy files. Reasons for
1eb4b9
         disallowing pickles include security, as loading pickled data can
1eb4b9
         execute arbitrary code. If pickles are disallowed, loading object
1eb4b9
-        arrays will fail.
1eb4b9
-        Default: True
1eb4b9
+        arrays will fail. Default: False
1eb4b9
+
1eb4b9
+        .. versionchanged:: 1.14.3
1eb4b9
+            Made default False in response to CVE-2019-6446.
1eb4b9
+
1eb4b9
     fix_imports : bool, optional
1eb4b9
         Only useful when loading Python 2 generated pickled files on Python 3,
1eb4b9
         which includes npy/npz files containing object arrays. If `fix_imports`
1eb4b9
diff --git a/numpy/lib/tests/test_format.py b/numpy/lib/tests/test_format.py
1eb4b9
index 2d2b4cea2..04e090ca7 100644
1eb4b9
--- a/numpy/lib/tests/test_format.py
1eb4b9
+++ b/numpy/lib/tests/test_format.py
1eb4b9
@@ -426,7 +426,7 @@ def roundtrip(arr):
1eb4b9
     f = BytesIO()
1eb4b9
     format.write_array(f, arr)
1eb4b9
     f2 = BytesIO(f.getvalue())
1eb4b9
-    arr2 = format.read_array(f2)
1eb4b9
+    arr2 = format.read_array(f2, allow_pickle=True)
1eb4b9
     return arr2
1eb4b9
 
1eb4b9
 
1eb4b9
@@ -553,7 +553,7 @@ def test_pickle_python2_python3():
1eb4b9
         path = os.path.join(data_dir, fname)
1eb4b9
 
1eb4b9
         for encoding in ['bytes', 'latin1']:
1eb4b9
-            data_f = np.load(path, encoding=encoding)
1eb4b9
+            data_f = np.load(path, allow_pickle=True, encoding=encoding)
1eb4b9
             if fname.endswith('.npz'):
1eb4b9
                 data = data_f['x']
1eb4b9
                 data_f.close()
1eb4b9
@@ -575,16 +575,19 @@ def test_pickle_python2_python3():
1eb4b9
         if sys.version_info[0] >= 3:
1eb4b9
             if fname.startswith('py2'):
1eb4b9
                 if fname.endswith('.npz'):
1eb4b9
-                    data = np.load(path)
1eb4b9
+                    data = np.load(path, allow_pickle=True)
1eb4b9
                     assert_raises(UnicodeError, data.__getitem__, 'x')
1eb4b9
                     data.close()
1eb4b9
-                    data = np.load(path, fix_imports=False, encoding='latin1')
1eb4b9
+                    data = np.load(path, allow_pickle=True, fix_imports=False,
1eb4b9
+                                   encoding='latin1')
1eb4b9
                     assert_raises(ImportError, data.__getitem__, 'x')
1eb4b9
                     data.close()
1eb4b9
                 else:
1eb4b9
-                    assert_raises(UnicodeError, np.load, path)
1eb4b9
+                    assert_raises(UnicodeError, np.load, path,
1eb4b9
+                                  allow_pickle=True)
1eb4b9
                     assert_raises(ImportError, np.load, path,
1eb4b9
-                                  encoding='latin1', fix_imports=False)
1eb4b9
+                                  allow_pickle=True, fix_imports=False,
1eb4b9
+                                  encoding='latin1')
1eb4b9
 
1eb4b9
 
1eb4b9
 def test_pickle_disallow():
1eb4b9
diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py
1eb4b9
index 2daa0153b..bde256741 100644
1eb4b9
--- a/numpy/lib/tests/test_io.py
1eb4b9
+++ b/numpy/lib/tests/test_io.py
1eb4b9
@@ -87,7 +87,7 @@ class RoundtripTest(object):
1eb4b9
 
1eb4b9
         """
1eb4b9
         save_kwds = kwargs.get('save_kwds', {})
1eb4b9
-        load_kwds = kwargs.get('load_kwds', {})
1eb4b9
+        load_kwds = kwargs.get('load_kwds', {"allow_pickle": True})
1eb4b9
         file_on_disk = kwargs.get('file_on_disk', False)
1eb4b9
 
1eb4b9
         if file_on_disk:
1eb4b9
-- 
1eb4b9
2.21.0
1eb4b9