Skip to content

FIX: segfault on truncated png #9257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 13, 2017
Merged

Conversation

tacaswell
Copy link
Member

@tacaswell tacaswell commented Oct 1, 2017

PR Summary

  • be more paranoid in _read_png_data about failed reads and check for
    exceptions after both calls to it
  • in read_png_data kick the png error handling
  • only override the exception in the body of setjmp handler if
    there is not already one set

closes #9256

PR Checklist

  • Has Pytest style unit tests

OP has a test case, just need to add it.

 - be more paranoid in _read_png_data about failed reads and check for
   exceptions after both calls to it
 - in read_png_data kick the png error handling
 - only override the exception in the body of `setjmp` handler if
   there is not already one set

closes matplotlib#9256
@tacaswell tacaswell added this to the 2.1.1 (next bug fix release) milestone Oct 1, 2017
Copy link
Member

@QuLogic QuLogic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly small stylistic warts.

src/_png.cpp Outdated
PyErr_SetString(PyExc_IOError, "read past end of file");
}
}
if (result) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the code uses some mixed tab/space indent. It should be 4-space indent even in the C code, I believe.

src/_png.cpp Outdated
} else {
PyErr_SetString(PyExc_IOError, "Failed to copy buffer");
}
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird tab in the middle there.

src/_png.cpp Outdated
@@ -424,6 +432,11 @@ static void read_png_data(png_structp png_ptr, png_bytep data, png_size_t length
{
PyObject *py_file_obj = (PyObject *)png_get_io_ptr(png_ptr);
_read_png_data(py_file_obj, data, length);
if (PyErr_Occurred())
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brace goes on if line.

src/_png.cpp Outdated
@@ -481,6 +494,9 @@ static PyObject *_read_png(PyObject *filein, bool float_result)
}
Py_XDECREF(read_method);
_read_png_data(py_file, header, 8);
if (PyErr_Occurred()){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space before brace.

src/_png.cpp Outdated
@@ -503,7 +519,10 @@ static PyObject *_read_png(PyObject *filein, bool float_result)
}

if (setjmp(png_jmpbuf(png_ptr))) {
PyErr_SetString(PyExc_RuntimeError, "Error setting jump");
if (!PyErr_Occurred())
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brace goes on if line.

src/_png.cpp Outdated
@@ -424,6 +432,11 @@ static void read_png_data(png_structp png_ptr, png_bytep data, png_size_t length
{
PyObject *py_file_obj = (PyObject *)png_get_io_ptr(png_ptr);
_read_png_data(py_file_obj, data, length);
if (PyErr_Occurred())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-Wmisleading-indentation :-) (here and below)

@tacaswell
Copy link
Member Author

I do not do a lot of c-code and the auto-formatter in emacs was fighting back....

@@ -46,3 +47,30 @@ def test_imread_png_uint16():

assert (img.dtype == np.uint16)
assert np.sum(img.flatten()) == 134184960


def test_truncated_file():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need to test both filenames and streams? (or rather, there doesn't seem to be a test of successfully reading from a stream (as opposed to a filename), which seems something more valuable to check...)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because they go through different code paths.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but not in the erroring part right? (at that point every possible input has been converted to an object with a read method)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐑 Yup, I was confused be the _read_png_data in the first if / else block and thought that was reading the whole file, but is just pulling off the first 8 bytes.

Copy link
Member

@QuLogic QuLogic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably ok, I think.

with pytest.raises(Exception):
plt.imread(fname_t)

shutil.rmtree(d)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in finally, or maybe use the tempdir pytest fixture.

@tacaswell
Copy link
Member Author

@antongulikov why?

@anntzer
Copy link
Contributor

anntzer commented Oct 2, 2017

If anything, error messages should start with a lower case letter and not have final dots for consistency with CPython itself IMO... (e.g., list index out of range, type object 'Foo' has no attribute 'bar)

@hulikau
Copy link

hulikau commented Oct 2, 2017

@tacaswell I wanted to say that the style for error messages should be the same for different exceptions.

Copy link
Contributor

@dopplershift dopplershift left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good pending CI.

@tacaswell
Copy link
Member Author

@antongulikov That makes sense, I think we have made the all consistent now.

@anntzer anntzer merged commit 080d0f8 into matplotlib:v2.1.x Nov 13, 2017
@tacaswell tacaswell deleted the fix_png_segfault branch November 13, 2017 19:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants