You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Summary
stb_image's PNM loader in version v2.27 incorrectly interpreted 16-bit PGM files as 8-bit when converting to RGBA, leading to buffer overflow when later reinterpreting the result as a 16-bit buffer. An attacker could potentially have crashed a service using stb_image, or read up to 1024 bytes of non-consecutive heap data without control over the read location.
Describe the bug
In stb_image's PNM reader, loading a valid 16-bit PGM file that is large enough
with the number of components set to 4 can cause a crash in stbi__convert_16_to_8() due to an out-of-bounds read.
This issue includes a fix in pull request #1223, and a proof of concept file that
can be used to reproduce the crash. We're reporting this on GitHub Issues
following the guidance in issue #1213.
This appears to be due to how when stbi__pnm_load() loads a 16-bit PGM file
with N bytes of data, it incorrectly calls stbi__convert_format() instead of stbi__convert_format16(), returning a buffer that is 2N bytes long instead of
4N bytes. Since ri.bits_per_channel is still 16 when control returns to stbi__load_and_postprocess_8bit(), stbi__convert_16_to_8() attempts to read img_len=4N bytes of data from this buffer, resulting in out-of-bounds reads.
When N is large enough, this results in an access violation.
To Reproduce
This .zip contains a 513 KB .pgm file, 16_to_8_oob_poc.pgm, which reproduces this issue: 16_to_8_oob_poc.zip
Calling stbi_load() with a path to this file and with a req_comp of 4 produces a
crash. I was able to verify this using tests/image_test.c (modified slightly in
order to build) on Windows version 20H2 with Microsoft Visual Studio 2019, and
I expect it should reproduce on other systems as well.
This file was generated using the following Python script, and should be a valid PGM file:
f = open('16_to_8_oob_poc.pgm', 'wb')
f.write(b'P5\n\n512 512\n65535\n')
f.write(bytearray([1]*512*512*2))
f.close()
It was derived from an example found using the Radamsa fuzzer.
Interestingly, tests/pbm/basi0g16.pgm is also a 16-bit PGM file, but reading it
doesn't cause a crash! I believe the reason is because this is a 32 x 32 image,
so it only includes N=2048 bytes of image data, and as a result the out-of-bounds
reads don't cross a page boundary that would result in an access violation.
Expected behavior
The example file should be loaded without crashing.
Screenshots
Here's a screenshot showing where the crash occurs and the call stack, when run
with the example file in image_test.c. (Note that the call in image_test.c may
be off by 2 lines; the specific callsite is stbi_load(argv[i], &w, &h, &n, 4).)
Thanks!
The text was updated successfully, but these errors were encountered:
Fixes a crash and an infinite loop in stb_image that could occur with
specially constructed PGM and HDR files
nothings/stb#1223
This is a candidate fix for:
https://nvd.nist.gov/vuln/detail/CVE-2021-42715
In stb_image's HDR reader, loading a specially constructed invalid HDR
file can result in an infinite loop within the RLE decoder
nothings/stb#1224
Additionally, this is a candidate fix for:
https://nvd.nist.gov/vuln/detail/CVE-2021-42716
stbi__pnm_load heap-buffer-overflow bug
nothings/stb#1166
In stb_image's PNM reader, loading a specially constructed valid
16-bit PGM file with 4 channels can cause a crash due to an
out-of-bounds read
nothings/stb#1225
Summary
stb_image's PNM loader in version v2.27 incorrectly interpreted 16-bit PGM files as 8-bit when converting to RGBA, leading to buffer overflow when later reinterpreting the result as a 16-bit buffer. An attacker could potentially have crashed a service using stb_image, or read up to 1024 bytes of non-consecutive heap data without control over the read location.
CVE number: CVE-2021-42716
Describe the bug
In stb_image's PNM reader, loading a valid 16-bit PGM file that is large enough
with the number of components set to 4 can cause a crash in
stbi__convert_16_to_8()due to an out-of-bounds read.This issue includes a fix in pull request #1223, and a proof of concept file that
can be used to reproduce the crash. We're reporting this on GitHub Issues
following the guidance in issue #1213.
This appears to be due to how when
stbi__pnm_load()loads a 16-bit PGM filewith N bytes of data, it incorrectly calls
stbi__convert_format()instead ofstbi__convert_format16(), returning a buffer that is 2N bytes long instead of4N bytes. Since
ri.bits_per_channelis still 16 when control returns tostbi__load_and_postprocess_8bit(),stbi__convert_16_to_8()attempts to readimg_len=4Nbytes of data from this buffer, resulting in out-of-bounds reads.When N is large enough, this results in an access violation.
To Reproduce
This .zip contains a 513 KB .pgm file, 16_to_8_oob_poc.pgm, which reproduces this issue:
16_to_8_oob_poc.zip
Calling
stbi_load()with a path to this file and with a req_comp of 4 produces acrash. I was able to verify this using tests/image_test.c (modified slightly in
order to build) on Windows version 20H2 with Microsoft Visual Studio 2019, and
I expect it should reproduce on other systems as well.
This file was generated using the following Python script, and should be a valid PGM file:
It was derived from an example found using the Radamsa fuzzer.
Interestingly, tests/pbm/basi0g16.pgm is also a 16-bit PGM file, but reading it
doesn't cause a crash! I believe the reason is because this is a 32 x 32 image,
so it only includes N=2048 bytes of image data, and as a result the out-of-bounds
reads don't cross a page boundary that would result in an access violation.
Expected behavior
The example file should be loaded without crashing.
Screenshots
Here's a screenshot showing where the crash occurs and the call stack, when run
with the example file in image_test.c. (Note that the call in image_test.c may
be off by 2 lines; the specific callsite is
stbi_load(argv[i], &w, &h, &n, 4).)Thanks!
The text was updated successfully, but these errors were encountered: