Skip to content

Source slice length (1548) does not match destination slice length (774) in JpegDecoder #1854

@anfedotoff

Description

@anfedotoff

This happens when I do some fuzzing with AFL++.

Expected

I suppose we don't want to panic

Actual behaviour

I was doing fuzzing with AFL++ using this wrapper. And I found this error: source slice length (1548) does not match destination slice length (774). Here is the stacktrace:

#0  0x00007ffff7c7700b in raise () from /lib/x86_64-linux-gnu/libc.so.6                                                                                                                                     
#1  0x00007ffff7c56859 in abort () from /lib/x86_64-linux-gnu/libc.so.6                                                                                                                                     
#2  0x0000555555695d77 in panic_abort::__rust_start_panic::abort () at /rustc/270c94e484e19764a2832ef918c95224eb3f17c7/library/panic_abort/src/lib.rs:42                                                    
#3  0x0000555555695d66 in panic_abort::__rust_start_panic () at /rustc/270c94e484e19764a2832ef918c95224eb3f17c7/library/panic_abort/src/lib.rs:37                                                           
#4  0x000055555568a76c in std::panicking::rust_panic () at /rustc/270c94e484e19764a2832ef918c95224eb3f17c7/library/std/src/panicking.rs:736                                                                 
#5  0x000055555568a61a in std::panicking::rust_panic_with_hook () at /rustc/270c94e484e19764a2832ef918c95224eb3f17c7/library/std/src/panicking.rs:706,                                                       
#6  0x000055555568a359 in std::panicking::begin_panic_handler::{closure#0} () at /rustc/270c94e484e19764a2832ef918c95224eb3f17c7/library/std/src/panicking.rs:579",                                           
#7  0x0000555555688fec in std::sys_common::backtrace::__rust_end_short_backtrace<std::panicking::begin_panic_handler::{closure_env#0}, !> () at /rustc/270c94e484e19764a2832ef918c95224eb3f17c7/library/std/src/sys_common/backtrace.rs:137                                                                                                                                                                                    
#8  0x000055555568a062 in std::panicking::begin_panic_handler () at /rustc/270c94e484e19764a2832ef918c95224eb3f17c7/library/std/src/panicking.rs:575                                                        
#9  0x0000555555579f43 in core::panicking::panic_fmt () at /rustc/270c94e484e19764a2832ef918c95224eb3f17c7/library/core/src/panicking.rs:64                                                                 
#10 0x000055555557a4d2 in core::slice::{impl#0}::copy_from_slice::len_mismatch_fail () at /rustc/270c94e484e19764a2832ef918c95224eb3f17c7/library/core/src/slice/mod.rs:3289                                
#11 0x00005555555dbe95 in core::slice::{impl#0}::copy_from_slice<u8> (self=..., src=...) at /rustc/270c94e484e19764a2832ef918c95224eb3f17c7/library/core/src/slice/mod.rs:3296                              
#12 image::codecs::jpeg::decoder::{impl#2}::read_image<std::io::cursor::Cursor<&[u8]>> (self=..., buf=...) at /image/src/codecs/jpeg/decoder.rs:115
#13 0x00005555555f31cf in image::image::decoder_to_vec<u8, image::codecs::jpeg::decoder::JpegDecoder<std::io::cursor::Cursor<&[u8]>>> (decoder=...) at /image/src/image.rs:608
#14 0x00005555555d8f9d in image::dynimage::decoder_to_image<image::codecs::jpeg::decoder::JpegDecoder<std::io::cursor::Cursor<&[u8]>>> (decoder=...) at /image/src/dynimage.rs:1030
#15 image::dynimage::DynamicImage::from_decoder<image::codecs::jpeg::decoder::JpegDecoder<std::io::cursor::Cursor<&[u8]>>> (decoder=...) at /image/src/dynimage.rs:177
#16 0x00005555555e3147 in image::io::free_functions::load_inner::{impl#0}::visit_decoder<image::codecs::jpeg::decoder::JpegDecoder<std::io::cursor::Cursor<&[u8]>>> (decoder=..., self=<error reading variable: Cannot access memory at address 0x10>) at /image/src/io/free_functions.rs:109
#17 image::io::free_functions::load_decoder<std::io::cursor::Cursor<&[u8]>, image::io::free_functions::load_inner::LoadVisitor> (format=<optimized out>, limits=..., r=..., visitor=<error reading variable: Cannot access memory at address 0x10>) at /image/src/io/free_functions.rs:61
#18 image::io::free_functions::load_inner<std::io::cursor::Cursor<&[u8]>> (limits=..., format=<optimized out>, r=...) at /image/src/io/free_functions.rs:113
#19 image::io::free_functions::load<std::io::cursor::Cursor<&[u8]>> (r=..., format=<optimized out>) at /image/src/io/free_functions.rs:37
#20 0x00005555555d41a9 in image::dynimage::load_from_memory_with_format () at /image/src/dynimage.rs:1215
#21 sydr_script_jpeg::main () at /image/fuzz/fuzzers/sydr_script_jpeg.rs:15

I've also done a small investigation. As we could see crash is occurred at decoder.rs:115. But before we've got a vector with wrong size at decoder.rs:109. This buffer is constructed here:

 let mut decoded: Vec<u16> =
            vec![0u16; ncomp * output_size.width as usize * output_size.height as usize];

some gdb output at this point:

(gdb) p ncomp
$4 = 3
(gdb) p frame.output_size 
$5 = jpeg_decoder::parser::Dimensions {width: 86, height: 3}

We could see here that decoded.len() is equal to 774, but it has Vec<u16> type. So, after conversion to Vec<u8> here we've got the wrong 1548 size of buffer . Maybe we could add some size checks to in read_image for that? I could do a PR.

Reproduction steps

If you want to reproduce this, I could provide a crash input and you could follow this instructions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions