Skip to content
Open
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
23 changes: 23 additions & 0 deletions Tests/test_file_jpeg2k.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,29 @@ def test_oversized_box_length(tbox: bytes) -> None:
Jpeg2KImagePlugin.Jpeg2KImageFile(BytesIO(data))


def test_large_skipped_box() -> None:
# A box larger than the stream buffer reaches the skip callback
xml = b" " * 2 * 1024 * 1024
box = _binary.o32be(8 + len(xml)) + b"xml " + xml
with open("Tests/images/test-card-lossless.jp2", "rb") as fp:
data = fp.read()
data = data[:326] + box + data[326:]

with Image.open(BytesIO(data)) as im:
assert_image_equal_tofile(im, "Tests/images/test-card-lossless.jp2")

class FailingSeek(BytesIO):
def seek(self, offset: int, whence: int = os.SEEK_SET) -> int:
if whence == os.SEEK_CUR and offset > 512 * 1024:
msg = "seek refused"
raise OSError(msg)
return super().seek(offset, whence)

with Image.open(FailingSeek(data)) as im:
with pytest.raises(OSError, match="seek refused"):
im.load()


def test_layers_type(card: ImageFile.ImageFile, tmp_path: Path) -> None:
outfile = tmp_path / "temp_layers.jp2"
for quality_layers in [[100, 50, 10], (100, 50, 10), None]:
Expand Down
3 changes: 3 additions & 0 deletions src/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ _decode(ImagingDecoderObject *decoder, PyObject *args) {
}

PyBuffer_Release(&buffer);
if (PyErr_Occurred()) {
return NULL;
}
return Py_BuildValue("ii", status, decoder->state.errcode);
}

Expand Down
8 changes: 4 additions & 4 deletions src/libImaging/Jpeg2KDecode.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ j2k_read(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) {

static OPJ_OFF_T
j2k_skip(OPJ_OFF_T p_nb_bytes, void *p_user_data) {
off_t pos;
ImagingCodecState state = (ImagingCodecState)p_user_data;

_imaging_seek_pyFd(state->fd, p_nb_bytes, SEEK_CUR);
pos = _imaging_tell_pyFd(state->fd);
if (_imaging_seek_pyFd(state->fd, p_nb_bytes, SEEK_CUR) == -1) {
return (OPJ_OFF_T)-1;
}

return pos ? pos : (OPJ_OFF_T)-1;
return p_nb_bytes;
}

/* -------------------------------------------------------------------- */
Expand Down
Loading