diff options
| author | Simon Graham <simon.graham@seequent.com> | 2020-10-21 14:07:16 +1300 |
|---|---|---|
| committer | Simon Graham <simon.graham@seequent.com> | 2020-10-29 15:31:05 +1300 |
| commit | f2ca85a03dcaed0b2e2571c687bfd78a7901c2ed (patch) | |
| tree | 98c499d4d444884128e0a5efdfe7c1978f4d1cfb | |
| parent | ab22e0076608f4825bf9a3ca1b6a0a6a7a670d14 (diff) | |
| download | numpy-f2ca85a03dcaed0b2e2571c687bfd78a7901c2ed.tar.gz | |
BUG: Fixed file handle leak in array_tofile.
The dup-ed file handle created in array_tofile is now closed when PyArray_ToFile fails.
| -rw-r--r-- | numpy/core/src/multiarray/methods.c | 9 | ||||
| -rw-r--r-- | numpy/core/tests/test_multiarray.py | 8 |
2 files changed, 12 insertions, 5 deletions
diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c index e4421b41b..634dd9bc3 100644 --- a/numpy/core/src/multiarray/methods.c +++ b/numpy/core/src/multiarray/methods.c @@ -585,7 +585,7 @@ array_tostring(PyArrayObject *self, PyObject *args, PyObject *kwds) static PyObject * array_tofile(PyArrayObject *self, PyObject *args, PyObject *kwds) { - int own; + int own, res1, res2; PyObject *file; FILE *fd; char *sep = ""; @@ -619,10 +619,9 @@ array_tofile(PyArrayObject *self, PyObject *args, PyObject *kwds) if (fd == NULL) { goto fail; } - if (PyArray_ToFile(self, fd, sep, format) < 0) { - goto fail; - } - if (npy_PyFile_DupClose2(file, fd, orig_pos) < 0) { + res1 = PyArray_ToFile(self, fd, sep, format); + res2 = npy_PyFile_DupClose2(file, fd, orig_pos); + if (res1 < 0 || res2 < 0) { goto fail; } if (own && npy_PyFile_CloseFile(file) < 0) { diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index d46e4ce9b..3e8da66ed 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -5048,6 +5048,14 @@ class TestIO: s = f.read() assert_equal(s, '1.51,2.00,3.51,4.00') + def test_tofile_cleanup(self): + x = np.zeros((10), dtype=object) + with open(self.filename, 'wb') as f: + assert_raises(IOError, lambda: x.tofile(f, sep='')) + + # Dup-ed file handle should be closed or remove will fail. + os.remove(self.filename) + def test_locale(self): with CommaDecimalPointLocale(): self.test_numbers() |
