Skip to content

Commit 6a8de89

Browse files
Ensure map stride is at least one full row of pixels (#9719)
Co-authored-by: GameZoneHacker <devanshshah2003@hotmail.com>
1 parent de20fb9 commit 6a8de89

2 files changed

Lines changed: 35 additions & 8 deletions

File tree

Tests/test_file_mcidas.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from __future__ import annotations
22

3+
import struct
4+
from pathlib import Path
5+
36
import pytest
47

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

1619

20+
def test_undersized_stride(tmp_path: Path) -> None:
21+
# A crafted area descriptor declares a row stride far smaller than a full
22+
# row of pixels. Memory mapping must not lay out row pointers at that
23+
# stride, which would read past the mapped buffer; the image is rejected
24+
# instead of leaking memory or crashing.
25+
words = [0] * 65
26+
words[2] = 4 # magic: 00 00 00 00 00 00 00 04
27+
words[9] = 1 # ysize
28+
words[10] = 200000 # xsize -> a full row is 200000 bytes (mode "L")
29+
words[11] = 1 # mode "L"
30+
words[14] = 0 # zeroes the xsize term of the stride
31+
words[15] = 1 # stride = 1 (much smaller than a row)
32+
data = struct.pack("!64i", *words[1:65])
33+
34+
path = tmp_path / "undersized_stride.area"
35+
path.write_bytes(data)
36+
37+
with Image.open(path) as im:
38+
with pytest.raises(ValueError, match="buffer is not large enough"):
39+
im.load()
40+
41+
1742
def test_valid_file() -> None:
1843
# Arrange
1944
# https://ghrc.nsstc.nasa.gov/hydro/details/cmx3g8

src/map.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,16 @@ PyImaging_MapBuffer(PyObject *self, PyObject *args) {
8484

8585
const ModeID mode = findModeID(mode_name);
8686

87-
if (stride <= 0) {
88-
if (mode == IMAGING_MODE_L || mode == IMAGING_MODE_P) {
89-
stride = xsize;
90-
} else if (isModeI16(mode)) {
91-
stride = xsize * 2;
92-
} else {
93-
stride = xsize * 4;
94-
}
87+
int pixelsize;
88+
if (mode == IMAGING_MODE_L || mode == IMAGING_MODE_P) {
89+
pixelsize = 1;
90+
} else if (isModeI16(mode)) {
91+
pixelsize = 2;
92+
} else {
93+
pixelsize = 4;
94+
}
95+
if (stride <= xsize * pixelsize) {
96+
stride = xsize * pixelsize;
9597
}
9698

9799
if (stride > 0 && ysize > PY_SSIZE_T_MAX / stride) {

0 commit comments

Comments
 (0)