Skip to content

Commit daadf7e

Browse files
committed
Add SGI Image (.rgb) decoder
1 parent bf20247 commit daadf7e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+786
-1
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ publish = false
88
include = ["src", "tests/reference.rs"]
99

1010
[features]
11-
default = ["ora", "otb", "pcx", "xbm", "xpm", "wbmp"]
11+
default = ["ora", "otb", "pcx", "sgi", "xbm", "xpm", "wbmp"]
1212

1313
# Each feature below is the file extention for the file format decoder it
1414
# enables.
1515
ora = ["image/png", "dep:zip", "dep:ouroboros"]
1616
otb = []
17+
sgi = []
1718
pcx = ["dep:pcx"]
1819
wbmp = ["dep:wbmp"]
1920
xbm = []

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Decoding support for additional image formats beyond those provided by the
1111
| PCX | [Wikipedia](https://en.wikipedia.org/wiki/PCX#PCX_file_format) |
1212
| WBMP | [Specification](https://www.wapforum.org/what/technical/SPEC-WAESpec-19990524.pdf) |
1313
| OTB | [Specification](https://www.wapforum.org/what/technical/SPEC-WAESpec-19990524.pdf) |
14+
| RGB | [Wikipedia](https://en.wikipedia.org/wiki/Silicon_Graphics_Image) |
1415
| XBM | [Specification](https://www.x.org/releases/X11R7.7/doc/libX11/libX11/libX11.html#Manipulating_Bitmaps) |
1516
| XPM | [Specification](https://www.x.org/docs/XPM/xpm.pdf) |
1617

fuzz/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,7 @@ path = "fuzzers/fuzzer_script_xpm.rs"
3737
[[bin]]
3838
name = "fuzzer_script_ora"
3939
path = "fuzzers/fuzzer_script_ora.rs"
40+
41+
[[bin]]
42+
name = "fuzzer_script_sgi"
43+
path = "fuzzers/fuzzer_script_sgi.rs"

fuzz/fuzzers/fuzzer_script_sgi.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![no_main]
2+
#[macro_use]
3+
extern crate libfuzzer_sys;
4+
5+
use image::ImageDecoder;
6+
use std::io::Cursor;
7+
8+
fuzz_target!(|data: &[u8]| {
9+
let reader = Cursor::new(data);
10+
let Ok(mut decoder) = image_extras::sgi::SgiDecoder::new(reader) else {
11+
return;
12+
};
13+
let mut limits = image::Limits::default();
14+
limits.max_alloc = Some(1024 * 1024); // 1 MiB
15+
if limits.reserve(decoder.total_bytes()).is_err() {
16+
return;
17+
}
18+
if decoder.set_limits(limits).is_err() {
19+
return;
20+
}
21+
let _ = std::hint::black_box(image::DynamicImage::from_decoder(decoder));
22+
});

src/lib.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ pub mod otb;
2626
#[cfg(feature = "pcx")]
2727
pub mod pcx;
2828

29+
#[cfg(feature = "sgi")]
30+
pub mod sgi;
31+
2932
#[cfg(feature = "wbmp")]
3033
pub mod wbmp;
3134

@@ -70,6 +73,50 @@ pub fn register() {
7073
register_format_detection_hook("pcx".into(), &[0x0a, 0x0], Some(b"\xFF\xF8"));
7174
}
7275

76+
// SGI RGB images generally show up with a .rgb ending (whether or not they
77+
// have 3 channels), and sometimes .bw (when grayscale) and .rgba. The
78+
// extensions .sgi and .iris, while unambiguous, do not seem to have been
79+
// used much. The extension .rgb is also used for a variety of other files,
80+
// including bare image data, so to be sure it would be best to check both
81+
// extension and leading bytes
82+
#[cfg(feature = "sgi")]
83+
{
84+
let hook: for<'a> fn(
85+
image::hooks::GenericReader<'a>,
86+
)
87+
-> image::ImageResult<Box<dyn image::ImageDecoder + 'a>> =
88+
|r| Ok(Box::new(sgi::SgiDecoder::new(r)?));
89+
image::hooks::register_decoding_hook("bw".into(), Box::new(hook));
90+
image::hooks::register_decoding_hook("rgb".into(), Box::new(hook));
91+
image::hooks::register_decoding_hook("rgba".into(), Box::new(hook));
92+
image::hooks::register_decoding_hook("iris".into(), Box::new(hook));
93+
if image::hooks::register_decoding_hook("sgi".into(), Box::new(hook)) {
94+
// The main signature bytes are technically just 01 da, but this is short
95+
// and the following storage and bpc fields are constrained well enough to
96+
// efficiently match them as well
97+
image::hooks::register_format_detection_hook(
98+
"sgi".into(),
99+
b"\x01\xda\x00\x01",
100+
None,
101+
);
102+
image::hooks::register_format_detection_hook(
103+
"sgi".into(),
104+
b"\x01\xda\x01\x01",
105+
None,
106+
);
107+
image::hooks::register_format_detection_hook(
108+
"sgi".into(),
109+
b"\x01\xda\x00\x02",
110+
None,
111+
);
112+
image::hooks::register_format_detection_hook(
113+
"sgi".into(),
114+
b"\x01\xda\x01\x02",
115+
None,
116+
);
117+
}
118+
}
119+
73120
#[cfg(feature = "wbmp")]
74121
image::hooks::register_decoding_hook(
75122
"wbmp".into(),

0 commit comments

Comments
 (0)