From bb6c11fb889e6c11b0ee122b828132ee763b5856 Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Thu, 11 Mar 2021 22:12:35 +0100 Subject: [PATCH] Fix FLI DOS -- CVE-2021-28676 * FliDecode did not properly check that the block advance was non-zero, potentally leading to an infinite loop on load. * This dates to the PIL Fork * Found with oss-fuzz --- ...-9139147ce93e20eb14088fe238e541443ffd64b3.fli | Bin 0 -> 200 bytes ...-bff0a9dc7243a8e6ede2408d2ffa6a9964698b87.fli | Bin 0 -> 159 bytes Tests/test_file_fli.py | 15 +++++++++++++++ src/libImaging/FliDecode.c | 5 +++++ 4 files changed, 20 insertions(+) create mode 100644 Tests/images/timeout-9139147ce93e20eb14088fe238e541443ffd64b3.fli create mode 100644 Tests/images/timeout-bff0a9dc7243a8e6ede2408d2ffa6a9964698b87.fli diff --git a/Tests/images/timeout-9139147ce93e20eb14088fe238e541443ffd64b3.fli b/Tests/images/timeout-9139147ce93e20eb14088fe238e541443ffd64b3.fli new file mode 100644 index 0000000000000000000000000000000000000000..ce4607d2dd083a923db2d6326e5b6cb34edd0702 GIT binary patch literal 200 zcmXwyJqp4=6okhm_!AK#S{V>qkC4L7);m~u4$UR3QhET7U>C8`6NsQ~KrD1!$?o_f z?!bdLAH&SWVbk4)s713L;WfRs?&f^rjbH($2=O8(RIXr?StL24^!a$mm34*ztOEHI zPNn;?;{vpx5n#!EK1%YGNr|@KscMMNgL>^6V^2HPbNIWZWZrUq>?l&21IIabHemf% Go_zsZc2frc literal 0 HcmV?d00001 diff --git a/Tests/images/timeout-bff0a9dc7243a8e6ede2408d2ffa6a9964698b87.fli b/Tests/images/timeout-bff0a9dc7243a8e6ede2408d2ffa6a9964698b87.fli new file mode 100644 index 0000000000000000000000000000000000000000..77a94b87a3ade935e707f3d89c9fbff801a1e976 GIT binary patch literal 159 zcmXwyF$%&!6hz0xLL-qC>;mF7(n^lvLG~UgJ%G1}r6&+U+km7{iDdV=TkI?5!(*6# z4?1nmg=SV3WtzwGHQuf~5xsCK^nnE?^f6l-duYo2Y6m_H%;k;X9X;l|tpZ2k#TbQW bed+df=cp&G@}D$=e#5~fLnPfYMS}JZYT!X? literal 0 HcmV?d00001 diff --git a/Tests/test_file_fli.py b/Tests/test_file_fli.py index 0d9748a95..1c1abf2b1 100644 --- a/Tests/test_file_fli.py +++ b/Tests/test_file_fli.py @@ -123,3 +123,18 @@ def test_seek(): im.seek(50) assert_image_equal_tofile(im, "Tests/images/a_fli.png") + + +@pytest.mark.parametrize( + "test_file", + [ + "Tests/images/timeout-9139147ce93e20eb14088fe238e541443ffd64b3.fli", + "Tests/images/timeout-bff0a9dc7243a8e6ede2408d2ffa6a9964698b87.fli", + ], +) +@pytest.mark.timeout(timeout=3) +def test_timeouts(test_file): + with open(test_file, "rb") as f: + with Image.open(f) as im: + with pytest.raises(OSError): + im.load() diff --git a/src/libImaging/FliDecode.c b/src/libImaging/FliDecode.c index e9000fc99..35a6ccccc 100644 --- a/src/libImaging/FliDecode.c +++ b/src/libImaging/FliDecode.c @@ -243,6 +243,11 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t byt return -1; } advance = I32(ptr); + if (advance == 0 ) { + // If there's no advance, we're in in infinite loop + state->errcode = IMAGING_CODEC_BROKEN; + return -1; + } if (advance < 0 || advance > bytes) { state->errcode = IMAGING_CODEC_OVERRUN; return -1;