Security
Headlines
HeadlinesLatestCVEs

Headline

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 · Issue #1224 · nothings/stb

An issue was discovered in stb stb_image.h 1.33 through 2.27. The HDR loader parsed truncated end-of-file RLE scanlines as an infinite sequence of zero-length runs. An attacker could potentially have caused denial of service in applications using stb_image by submitting crafted HDR files.

CVE
#windows#microsoft#dos#git

Summary
stb_image’s HDR loader in versions 1.33 to and including v2.27 parsed truncated end-of-file RLE scanlines as an infinite sequence of zero-length runs. An attacker could potentially have caused denial of service in applications using stb_image by submitting specially constructed HDR files.

CVE number: CVE-2021-42715

Describe the bug
In stb_image’s HDR reader, loading a specially constructed invalid HDR file can
result in an infinite loop within the RLE decoder.

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.

The issue occurs in this loop within stbi__hdr_load():

while ((nleft = width - i) > 0) {
   count = stbi__get8(s);
   if (count > 128) {
      // Run
      value = stbi__get8(s);
      count -= 128;
      if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
      for (z = 0; z < count; ++z)
         scanline[i++ * 4 + k] = value;
   } else {
      // Dump
      if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
      for (z = 0; z < count; ++z)
         scanline[i++ * 4 + k] = stbi__get8(s);
   }
}

The proof of concept file manages to get this part of the decoder into a state
where:

  • nleft is equal to 11;
  • s is at the end of the file.

Because s is at the end of the file, stbi__get8() always returns 0, since
s->img_buffer == s->img_buffer_end here:

stbi_inline static stbi_uc stbi__get8(stbi__context *s)
{
   if (s->img_buffer < s->img_buffer_end)
      return *s->img_buffer++;
   if (s->read_from_callbacks) {
      stbi__refill_buffer(s);
      return *s->img_buffer++;
   }
   return 0;
}

This means that count is always set to 0; this passes the error check, but
doesn’t affect any program state, meaning that the loop runs forever, an
availability issue.

To Reproduce
This .zip contains a 222 KB .hdr file, rle_iloop_poc.hdr, which reproduces this issue:
rle_iloop_poc.zip

Calling stbi_load() with a path to this file never returns. 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 found using the Radamsa fuzzer.
I think this particular file works by setting the RLE flags on the last scanline
in the file and being truncated in just the right place, but I’m not 100% sure.

Expected behavior
stbi_load should eventually return.

Based on Bruce Walter’s
https://www.graphics.cornell.edu/~bjw/rgbe/rgbe.c HDR reader,
it seems like the intended behavior is that a run length of 0 should be treated
as invalid, which is the approach the pull request takes. However, other
solutions are possible (e.g. detecting when the end of the file has been reached) - I don’t have any preference either way.

Thanks!

Related news

Gentoo Linux Security Advisory 202409-15

Gentoo Linux Security Advisory 202409-15 - Multiple vulnerabilities have been discovered in stb, the worst of which lead to a denial of service. Versions greater than or equal to 20240201 are affected.

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907