◐ Shell
clean mode source ↗

check transform mesh shape in _get_transform_mesh by uwezkhan · Pull Request #31894 · matplotlib/matplotlib

PR summary

_get_transform_mesh builds an input mesh sized to the output image, hands it to the supplied transform's inverted().transform(), and forwards whatever comes back to the resampler as a flat table of out_h * out_w coordinate pairs. The only check on the returned array is ndim == 2. A non-affine transform whose inverse returns fewer rows than requested, or a trailing dimension other than 2, leaves lookup_distortion in _image_resample.h indexing past the end of that buffer.

Before: an undersized mesh produces an out-of-bounds read during resampling, and with a large output array it segfaults. After: the row and column counts are checked against the requested size and a RuntimeError is raised, alongside the existing ndim check directly above it. The tradeoff is two integer comparisons per non-affine resample; keeping the check next to the mesh construction lets the resampler keep treating the buffer as exactly sized.

Minimal repro on the current tree:

import numpy as np
import matplotlib._image as _image
from matplotlib.transforms import Transform

class Bad(Transform):
    input_dims = output_dims = 2
    def inverted(self): return self
    def transform(self, v): return np.zeros((1, 2))  # should be out_h*out_w rows

_image.resample(np.zeros((10, 10, 4), np.uint8),
                np.zeros((2000, 2000, 4), np.uint8), Bad(),
                interpolation=_image._InterpolationType.NEAREST)  # SIGSEGV

AI Disclosure

PR checklist