diff --git a/lib/matplotlib/testing/conftest.py b/lib/matplotlib/testing/conftest.py index 04f6e7048b26..a93f705af092 100644 --- a/lib/matplotlib/testing/conftest.py +++ b/lib/matplotlib/testing/conftest.py @@ -26,6 +26,8 @@ def mpl_test_settings(request): assert len(backend_marker.args) == 1, \ "Marker 'backend' must specify 1 backend." backend, = backend_marker.args + skip_on_importerror = backend_marker.kwargs.get( + 'skip_on_importerror', False) prev_backend = matplotlib.get_backend() style = '_classic_test' # Default of cleanup and image_comparison too. @@ -45,7 +47,7 @@ def mpl_test_settings(request): except ImportError as exc: # Should only occur for the cairo backend tests, if neither # pycairo nor cairocffi are installed. - if 'cairo' in backend.lower(): + if 'cairo' in backend.lower() or skip_on_importerror: pytest.skip("Failed to switch to backend {} ({})." .format(backend, exc)) else: diff --git a/lib/matplotlib/tests/test_backend_tk.py b/lib/matplotlib/tests/test_backend_tk.py new file mode 100644 index 000000000000..18ffcb40a0b1 --- /dev/null +++ b/lib/matplotlib/tests/test_backend_tk.py @@ -0,0 +1,28 @@ +import pytest +import numpy as np +from matplotlib import pyplot as plt + + +@pytest.mark.backend('TkAgg', skip_on_importerror=True) +def test_blit(): + from matplotlib.backends import _tkagg + def evil_blit(photoimage, aggimage, offsets, bboxptr): + data = np.asarray(aggimage) + height, width = data.shape[:2] + dataptr = (height, width, data.ctypes.data) + _tkagg.blit( + photoimage.tk.interpaddr(), str(photoimage), dataptr, offsets, + bboxptr) + + fig, ax = plt.subplots() + for bad_boxes in ((-1, 2, 0, 2), + (2, 0, 0, 2), + (1, 6, 0, 2), + (0, 2, -1, 2), + (0, 2, 2, 0), + (0, 2, 1, 6)): + with pytest.raises(ValueError): + evil_blit(fig.canvas._tkphoto, + np.ones((4, 4, 4)), + (0, 1, 2, 3), + bad_boxes) diff --git a/src/_tkagg.cpp b/src/_tkagg.cpp index 760b4b0efd84..2e5167ac8ff5 100644 --- a/src/_tkagg.cpp +++ b/src/_tkagg.cpp @@ -67,6 +67,11 @@ static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) PyErr_SetString(PyExc_ValueError, "Failed to extract Tk_PhotoHandle"); goto exit; } + if (0 > y1 || y1 > y2 || y2 > height || 0 > x1 || x1 > x2 || x2 > width) { + PyErr_SetString(PyExc_ValueError, "Attempting to draw out of bounds"); + goto exit; + } + block.pixelPtr = data_ptr + 4 * ((height - y2) * width + x1); block.width = x2 - x1; block.height = y2 - y1;
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: