Skip to content

Commit aaf584b

Browse files
committed
Prevent huge memory allocations from bad data
If we get bad width/height data for the image bail out instead of doing a huge allocation that will crash the program. This was caught using afl-fuzz
1 parent b134a6a commit aaf584b

File tree

16 files changed

+33
-21
lines changed

16 files changed

+33
-21
lines changed

src/decoders/arw.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ impl<'a> ArwDecoder<'a> {
141141

142142
fn decode_arw1(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
143143
let mut pump = BitPumpMSB::new(buf);
144-
let mut out: Vec<u16> = vec![0; width*height];
144+
let mut out: Vec<u16> = alloc_image!(width, height);
145145

146146
let mut sum: i32 = 0;
147147
for x in 0..width {

src/decoders/basics.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub static LITTLE_ENDIAN: Endian = Endian{big: false};
8383
pub fn decode_threaded<F>(width: usize, height: usize, closure: &F) -> Vec<u16>
8484
where F : Fn(&mut [u16], usize)+Sync {
8585

86-
let mut out: Vec<u16> = vec![0; width*height];
86+
let mut out: Vec<u16> = alloc_image!(width, height);
8787
out.par_chunks_mut(width).enumerate().for_each(|(row, line)| {
8888
closure(line, row);
8989
});
@@ -93,7 +93,7 @@ pub fn decode_threaded<F>(width: usize, height: usize, closure: &F) -> Vec<u16>
9393
pub fn decode_threaded_multiline<F>(width: usize, height: usize, lines: usize, closure: &F) -> Vec<u16>
9494
where F : Fn(&mut [u16], usize)+Sync {
9595

96-
let mut out: Vec<u16> = vec![0; width*height];
96+
let mut out: Vec<u16> = alloc_image!(width, height);
9797
out.par_chunks_mut(width*lines).enumerate().for_each(|(row, line)| {
9898
closure(line, row*lines);
9999
});

src/decoders/cr2.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl<'a> Decoder for Cr2Decoder<'a> {
4444
let mut width = ljpegwidth;
4545
let mut height = decompressor.height();
4646
let cpp = if decompressor.super_h() == 2 {3} else {1};
47-
let mut ljpegout = vec![0 as u16; width*height];
47+
let mut ljpegout = alloc_image!(width, height);
4848
try!(decompressor.decode(&mut ljpegout, 0, width, width, height));
4949

5050
// Linearize the output (applies only to D2000 as far as I can tell)
@@ -87,7 +87,7 @@ impl<'a> Decoder for Cr2Decoder<'a> {
8787
if canoncol.get_usize(0) == 0 {
8888
(width, height, cpp, ljpegout)
8989
} else {
90-
let mut out = vec![0 as u16; width*height];
90+
let mut out = alloc_image!(width, height);
9191
let mut fieldwidths = Vec::new();
9292
for _ in 0..canoncol.get_usize(0) {
9393
fieldwidths.push(canoncol.get_usize(1));

src/decoders/crw.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ impl<'a> CrwDecoder<'a> {
189189
}
190190

191191
fn decode_compressed(&self, cam: &Camera, width: usize, height: usize) -> Result<Vec<u16>,String> {
192-
let mut out = vec![0 as u16; width*height];
192+
let mut out = alloc_image!(width, height);
193193

194194
let dectable = fetch_tag!(self.ciff, CiffTag::DecoderTable).get_usize(0);
195195
if dectable > 2 {

src/decoders/dcr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl<'a> DcrDecoder<'a> {
6161
}
6262

6363
fn decode_kodak65000(buf: &[u8], curve: &LookupTable, width: usize, height: usize) -> Vec<u16> {
64-
let mut out: Vec<u16> = vec![0; width*height];
64+
let mut out: Vec<u16> = alloc_image!(width, height);
6565
let mut input = ByteStream::new(buf, LITTLE_ENDIAN);
6666

6767
let mut random: u32 = 0;

src/decoders/dng.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ impl<'a> DngDecoder<'a> {
200200
}
201201
let offset = offsets.get_usize(0);
202202
let src = &self.buffer[offset..];
203-
let mut out = vec![0 as u16; width*height];
203+
let mut out = alloc_image!(width, height);
204204
let decompressor = try!(LjpegDecompressor::new(src));
205205
try!(decompressor.decode(&mut out, 0, width, width, height));
206206
Ok(out)

src/decoders/kdc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl<'a> KdcDecoder<'a> {
8282
}
8383

8484
fn decode_dc120(src: &[u8], width: usize, height: usize) -> Vec<u16> {
85-
let mut out = vec![0u16; width*height];
85+
let mut out = alloc_image!(width, height);
8686

8787
let mul: [usize;4] = [162, 192, 187, 92];
8888
let add: [usize;4] = [ 0, 636, 424, 212];

src/decoders/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ macro_rules! fetch_ifd {
2525
);
2626
}
2727

28+
macro_rules! alloc_image {
29+
($width:expr, $height:expr) => (
30+
{
31+
if $width * $height > 500000000 {
32+
panic!("rawloader: surely there's no such thing as a >500MP image!");
33+
}
34+
let mut out: Vec<u16> = vec![0; $width * $height];
35+
out
36+
}
37+
);
38+
}
39+
2840
extern crate toml;
2941
use self::toml::Value;
3042
mod image;

src/decoders/mos.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl<'a> MosDecoder<'a> {
8989
let decompressor = try!(LjpegDecompressor::new_full(src, true, true));
9090
let ljpegout = try!(decompressor.decode_leaf(width, height));
9191
if cam.find_hint("interlaced") {
92-
let mut out = vec![0 as u16; width*height];
92+
let mut out = alloc_image!(width, height);
9393
for (row,line) in ljpegout.chunks_exact(width).enumerate() {
9494
let orow = if row & 1 == 1 {height-1-row/2} else {row/2};
9595
out[orow*width .. (orow+1)*width].copy_from_slice(line);

src/decoders/nef.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ impl<'a> NefDecoder<'a> {
285285
}
286286
let curve = LookupTable::new(&points[0..max]);
287287

288-
let mut out = vec![0 as u16; width * height];
288+
let mut out = alloc_image!(width, height);
289289
let mut pump = BitPumpMSB::new(src);
290290
let mut random = pump.peek_bits(24);
291291

src/decoders/orf.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl<'a> OrfDecoder<'a> {
7777
*/
7878

7979
pub fn decode_compressed(buf: &'a [u8], width: usize, height: usize) -> Vec<u16> {
80-
let mut out: Vec<u16> = vec![0; width*height];
80+
let mut out: Vec<u16> = alloc_image!(width, height);
8181

8282
/* Build a table to quickly look up "high" value */
8383
let mut bittable: [u8; 4096] = [0; 4096];

src/decoders/packed.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ pub fn decode_12be(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
7474
}
7575

7676
pub fn decode_12be_msb16(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
77-
let mut out: Vec<u16> = vec![0; width*height];
77+
let mut out: Vec<u16> = alloc_image!(width, height);
7878

7979
for (o, i) in out.chunks_exact_mut(4).zip(buf.chunks_exact(6)) {
8080
let g1: u16 = i[ 0] as u16;
@@ -109,7 +109,7 @@ pub fn decode_12le_16bitaligned(buf: &[u8], width: usize, height: usize) -> Vec<
109109
}
110110

111111
pub fn decode_12be_msb32(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
112-
let mut out: Vec<u16> = vec![0; width*height];
112+
let mut out: Vec<u16> = alloc_image!(width, height);
113113

114114
for (o, i) in out.chunks_exact_mut(8).zip(buf.chunks_exact(12)) {
115115
let g1: u16 = i[ 0] as u16;

src/decoders/pef.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ impl<'a> PefDecoder<'a> {
121121
let mut pred_left1: i32;
122122
let mut pred_left2: i32;
123123

124-
let mut out = vec![0 as u16; width*height];
124+
let mut out = alloc_image!(width, height);
125125
for row in 0..height {
126126
pred_up1[row & 1] += try!(htable.huff_decode(&mut pump));
127127
pred_up2[row & 1] += try!(htable.huff_decode(&mut pump));

src/decoders/raf.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl<'a> RafDecoder<'a> {
110110
let rotatedwidth = cropheight + cropwidth/2;
111111
let rotatedheight = rotatedwidth-1;
112112

113-
let mut out: Vec<u16> = vec![0; rotatedwidth * rotatedheight];
113+
let mut out: Vec<u16> = alloc_image!(rotatedwidth, rotatedheight);
114114
for row in 0..cropheight {
115115
let inb = &src[(row+y)*width+x..];
116116
for col in 0..cropwidth {
@@ -125,7 +125,7 @@ impl<'a> RafDecoder<'a> {
125125
let rotatedwidth = cropwidth + cropheight/2;
126126
let rotatedheight = rotatedwidth-1;
127127

128-
let mut out: Vec<u16> = vec![0; rotatedwidth * rotatedheight];
128+
let mut out: Vec<u16> = alloc_image!(rotatedwidth, rotatedheight);
129129
for row in 0..cropheight {
130130
let inb = &src[(row+y)*width+x..];
131131
for col in 0..cropwidth {

src/decoders/srw.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ impl<'a> Decoder for SrwDecoder<'a> {
7474

7575
impl<'a> SrwDecoder<'a> {
7676
pub fn decode_srw1(buf: &[u8], loffsets: &[u8], width: usize, height: usize) -> Vec<u16> {
77-
let mut out: Vec<u16> = vec![0; width*height];
77+
let mut out: Vec<u16> = alloc_image!(width, height);
7878

7979
for row in 0..height {
8080
let mut len: [u32; 4] = [if row < 2 {7} else {4}; 4];
@@ -141,7 +141,7 @@ impl<'a> SrwDecoder<'a> {
141141
}
142142

143143
pub fn decode_srw2(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
144-
let mut out: Vec<u16> = vec![0; width*height];
144+
let mut out: Vec<u16> = alloc_image!(width, height);
145145

146146
// This format has a variable length encoding of how many bits are needed
147147
// to encode the difference between pixels, we use a table to process it
@@ -213,7 +213,7 @@ impl<'a> SrwDecoder<'a> {
213213
// and Loring von Palleske (Samsung) for pointing to the open-source code of
214214
// Samsung's DNG converter at http://opensource.samsung.com/
215215

216-
let mut out: Vec<u16> = vec![0; width*height];
216+
let mut out: Vec<u16> = alloc_image!(width, height);
217217
let mut pump = BitPumpMSB32::new(buf);
218218

219219
// Process the initial metadata bits, we only really use initVal, width and

src/decoders/tfr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl<'a> TfrDecoder<'a> {
4747
}
4848

4949
fn decode_compressed(&self, src: &[u8], width: usize, height: usize) -> Result<Vec<u16>,String> {
50-
let mut out = vec![0 as u16; width*height];
50+
let mut out = alloc_image!(width, height);
5151
let decompressor = try!(LjpegDecompressor::new_full(src, true, false));
5252
try!(decompressor.decode(&mut out, 0, width, width, height));
5353
Ok(out)

0 commit comments

Comments
 (0)