Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Tests/test_file_mcidas.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from __future__ import annotations

import struct
from pathlib import Path

import pytest

from PIL import Image, McIdasImagePlugin
Expand All @@ -14,6 +17,28 @@ def test_invalid_file() -> None:
McIdasImagePlugin.McIdasImageFile(invalid_file)


def test_undersized_stride(tmp_path: Path) -> None:
# A crafted area descriptor declares a row stride far smaller than a full
# row of pixels. Memory mapping must not lay out row pointers at that
# stride, which would read past the mapped buffer; the image is rejected
# instead of leaking memory or crashing.
words = [0] * 65
words[2] = 4 # magic: 00 00 00 00 00 00 00 04
words[9] = 1 # ysize
words[10] = 200000 # xsize -> a full row is 200000 bytes (mode "L")
words[11] = 1 # mode "L"
words[14] = 0 # zeroes the xsize term of the stride
words[15] = 1 # stride = 1 (much smaller than a row)
data = struct.pack("!64i", *words[1:65])

path = tmp_path / "undersized_stride.area"
path.write_bytes(data)

with Image.open(path) as im:
with pytest.raises(ValueError, match="buffer is not large enough"):
im.load()


def test_valid_file() -> None:
# Arrange
# https://ghrc.nsstc.nasa.gov/hydro/details/cmx3g8
Expand Down
18 changes: 10 additions & 8 deletions src/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,16 @@ PyImaging_MapBuffer(PyObject *self, PyObject *args) {

const ModeID mode = findModeID(mode_name);

if (stride <= 0) {
if (mode == IMAGING_MODE_L || mode == IMAGING_MODE_P) {
stride = xsize;
} else if (isModeI16(mode)) {
stride = xsize * 2;
} else {
stride = xsize * 4;
}
int pixelsize;
if (mode == IMAGING_MODE_L || mode == IMAGING_MODE_P) {
pixelsize = 1;
} else if (isModeI16(mode)) {
pixelsize = 2;
} else {
pixelsize = 4;
}
if (stride <= xsize * pixelsize) {
stride = xsize * pixelsize;
}

if (stride > 0 && ysize > PY_SSIZE_T_MAX / stride) {
Expand Down
Loading