Test rejection of incorrect modes

This commit is contained in:
wiredfool 2025-01-25 15:12:41 +00:00
parent dbe0304bb3
commit 388da5c4a4
3 changed files with 41 additions and 9 deletions

View File

@ -68,6 +68,26 @@ def test_to_array(mode: str, dtype: Any, mask: Any) -> None:
assert_image_equal(img, reloaded) assert_image_equal(img, reloaded)
@pytest.mark.parametrize(
"mode, dest_modes",
(
("L", ["I", "F", "LA", "RGB", "RGBA", "RGBX", "CMYK", "YCbCr", "HSV"]),
("I", ["L", "F"]), # Technically I32 can work for any 4x8bit storage.
("F", ["I", "L", "LA", "RGB", "RGBA", "RGBX", "CMYK", "YCbCr", "HSV"]),
("LA", ["L", "F"]),
("RGB", ["L", "F"]),
("RGBA", ["L", "F"]),
("RGBX", ["L", "F"]),
("CMYK", ["L", "F"]),
("YCbCr", ["L", "F"]),
("HSV", ["L", "F"]),
),
)
def test_invalid_array_type(mode: str, dest_modes: List[str]) -> None:
img = hopper(mode)
for dest_mode in dest_modes:
with pytest.raises(ValueError):
Image.fromarrow(img, dest_mode, img.size)
def test_lifetime(): def test_lifetime():
# valgrind shouldn't error out here. # valgrind shouldn't error out here.

View File

@ -290,6 +290,7 @@ _new_arrow(PyObject *self, PyObject *args) {
if (!ret && array->release) { if (!ret && array->release) {
array->release(array); array->release(array);
array->release = NULL; array->release = NULL;
return ImagingError_ValueError("Invalid arrow array mode or size mismatch");
} }
return ret; return ret;
} }

View File

@ -705,25 +705,36 @@ ImagingNewArrow(
int64_t pixels = (int64_t)xsize * (int64_t)ysize; int64_t pixels = (int64_t)xsize * (int64_t)ysize;
if (((strcmp(schema->format, "i") == 0 && im->pixelsize == 4) || // fmt:off // don't reformat this
(strcmp(schema->format, im->arrow_band_format) == 0 && im->bands == 1)) && if (((strcmp(schema->format, "I") == 0
pixels == external_array->length) { && im->pixelsize == 4
&& im->bands >= 2) // INT32 into any INT32 Storage mode
||
(strcmp(schema->format, im->arrow_band_format) == 0
&& im->bands == 1)) // Single band match
&& pixels == external_array->length) {
// one arrow element per, and it matches a pixelsize*char // one arrow element per, and it matches a pixelsize*char
if (ImagingAllocateArrow(im, external_array)) { if (ImagingAllocateArrow(im, external_array)) {
return im; return im;
} }
} }
if (strcmp(schema->format, "+w:4") == 0 && im->pixelsize == 4 && // linter: don't mess with the formatting here
schema->n_children > 0 && schema->children && if (strcmp(schema->format, "+w:4") == 0 // 4 up array
strcmp(schema->children[0]->format, "C") == 0 && && im->pixelsize == 4 // storage as 32 bpc
pixels == external_array->length && external_array->n_children == 1 && && schema->n_children > 0 // make sure schema is well formed.
external_array->children && 4 * pixels == external_array->children[0]->length) { && schema->children // make sure schema is well formed
&& strcmp(schema->children[0]->format, "C") == 0 // Expected format
&& strcmp(im->arrow_band_format, "C") == 0 // Expected Format
&& pixels == external_array->length // expected length
&& external_array->n_children == 1 // array is well formed
&& external_array->children // array is well formed
&& 4 * pixels == external_array->children[0]->length) {
// 4 up element of char into pixelsize == 4 // 4 up element of char into pixelsize == 4
if (ImagingAllocateArrow(im, external_array)) { if (ImagingAllocateArrow(im, external_array)) {
return im; return im;
} }
} }
// fmt: on
ImagingDelete(im); ImagingDelete(im);
return NULL; return NULL;
} }