bug:Out-of-bounds read in SgiInput::uncompress_rle_channel (bpc==1 RLE "run" branch lacks an input bounds check)
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 80/100
Hướng nghiên cứu
Bắt đầu tại src/sgi.imageio/sgiinput.cpp, trong SgiInput::uncompress_rle_channel(), tập trung vào nhánh chạy RLE cho bpc==1 và so sánh nó với kiểm tra giới hạn của nhánh literal. Chạy poc.sgi đính kèm bằng oiiotool dưới ASAN, sau đó xác minh rằng đầu vào không hợp lệ bị từ chối mà không xảy ra thao tác đọc ngoài giới hạn và các công cụ hình ảnh bị ảnh hưởng không còn bị abort hoặc báo cáo lỗi của sanitizer.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
While fuzzing oiiotool with AFL++ + ASAN we found that a malformed SGI
(.sgi) file triggers a span out-of-bounds read inside
SgiInput::uncompress_rle_channel(). In builds with contract assertions
enforced (the OIIO 3.x default) the violation aborts the process; in builds
compiled with hardening NONE + NDEBUG the same access is a 1-byte
heap-buffer-overflow read past the rle_scanline allocation.
Still reproduces on current main (dc87b17ab, 2026-09-27).
Reproducer
SGI file, RLE storage, dimension=3, 100x63, 4 channels, bpc=1: poc.sgi
attached (20 KB).
$ oiiotool -i poc.sgi --printinfo
Any of oiiotool / iconvert / iinfo / maketx reading the file hits it;
the crash is in the reader, independent of the tool.
Output
Build: clang 16, -g -O1 -fno-omit-frame-pointer, ASAN, contract
assertions at default (ENFORCE).
src/include/OpenImageIO/span.h:221 (operator[]): Contract assertion failed: idx < m_size
[abort]
With ASAN_OPTIONS=handle_abort=1, the aborting thread stack:
#5 SgiInput::uncompress_rle_channel(long, long, span<unsigned char>) src/sgi.imageio/sgiinput.cpp
#6 SgiInput::read_native_scanline(...) src/sgi.imageio/sgiinput.cpp:211:18
#7 ImageInput::read_native_scanlines(...) src/libOpenImageIO/imageinput.cpp:521:19
Root cause
Current main, src/sgi.imageio/sgiinput.cpp, bpc==1 branch of
uncompress_rle_channel():
while (i < scanline_len) {
unsigned char value = rle_scanline[i++]; // count byte (i < scanline_len OK)
int count = value & 0x7F;
if (!count) break;
if (value & 0x80) { // literal copy
while (count--) {
if (i >= scanline_len || limit <= 0) { // <-- input bound IS checked here (line 286)
errorfmt("Corrupt RLE data"); return false;
}
outbuf[iout++] = rle_scanline[i++];
--limit;
}
} else { // run: repeat next value
value = rle_scanline[i++]; // <-- line 296: NO `i >= scanline_len` check!
while (count--) { ... }
}
}
If the RLE count byte is the last byte of the scanline chunk
(i == scanline_len - 1 at loop top), consuming it advances i to
scanline_len, and the "run" branch then reads rle_scanline[i] one past
the end. The literal branch checks i >= scanline_len (line 286) but the
run branch was missed. The final i != scanline_len sanity check at the end
of the function would have rejected this data — but the OOB read happens
before it.
A minimal fix is mirroring the literal-branch check before line 296:
if (i >= scanline_len) { errorfmt("Corrupt RLE data"); return false; }
value = rle_scanline[i++];
Impact
- Contract assertions enforced (OIIO 3.x default): process abort on a
malformed file — denial of service for CLI tools (oiiotool,iconvert,
iinfo,maketx) and any app using the SGI reader on untrusted input. OIIO_HARDENING_NONE+NDEBUGbuilds: 1-byte heap-buffer-overflow read
past thenew unsigned char[scanline_len]allocation.
Related work
This is in the same function as GHSA-jg3q-vm3q-2j35 / CVE-2026-43903
(fixed in 3.0.18.0 / 3.1.13.0) and #5321 (16-bit odd byte counts), but the
access above is still reachable on current main — it is an
incomplete fix, leaving a remaining unchecked read in the bpc==1 run branch.
Meta
Found by a coverage-guided AFL++ fuzzing campaign (569-file multi-format
seed corpus from the OIIO testsuite) run during verification of #4552 /
CVE-2024-55194. 19 of the campaign's saved crash inputs reproduce this one
bug; the attached PoC is a readily-reproducible one.
Happy to send additional crash inputs or a minimized PoC if useful.
- Ngôn ngữ chính
- C++
- Star
- 2.4k
- Fork
- 718
- Merge trung bình
- 2 ngày 10 giờ
- Pull request đã merge (30 ngày)
- 89
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của AcademySoftwareFoundation/OpenImageIO
-
bug: deep paste wraps into the next scanline instead of clipping, and ignores chbeginCó thể đã có người làm @lgritz đã nhận 1 ngày trước. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
AcademySoftwareFoundation/OpenImageIO#5649 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug: make_kernel("binomial", ...) indexes its tap arrays past their allocation for even or fractional extentsCó thể đã có người làm @lgritz đã nhận hôm nay. Đang mở
Độ khó 3/5 Nửa ngày Mức phù hợp với người mới 62/100
AcademySoftwareFoundation/OpenImageIO#5648 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
AcademySoftwareFoundation/OpenImageIO#5619 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 10/100
AcademySoftwareFoundation/OpenImageIO#5570 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
AcademySoftwareFoundation/OpenImageIO#5558 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của AcademySoftwareFoundation/OpenImageIO
Issue tương tự
-
bug module:nodes tests
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
rocketride-org/rocketride-server#3020 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
pocoproject/poco#5636 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
microsoft/cppwinrt#1646 · 7 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày