Giter VIP home page Giter VIP logo

gift's People

Contributors

douglau avatar douglau-mnit avatar niklasf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

niklasf

gift's Issues

Color table building

Add enum of color table building methods:
Maybe Lab of Lch with octree clusering and dithering.
Check out exoquant.

[wip] Four issues I've run into while using`gift`.

Thanks for your work on this crate.

I'm creating this issue with a brief overview of some issues I've run into during use. (Which would be better to be created as individual issues but currently the most likely alternative is not to write them up at all, so hopefully this format is better than nothing. :) )

  • 1. Add note to docs/README to items that are still todo! e.g. full color to indexed & the binary sub commands.
  • 2. Add tag/release for 0.9.1 which is listed on crates.io but not tagged in repo.
  • 3. Both v0.9.1 and current master handle min_code_bits incorrectly for the values 4 & 8 when encoding. (see below)
  • 4. current master does not encode images of dimensions such as 2x2 or 3x3 successfully. (8x8 appears to work.) I haven't investigated why but my guess is it's related to the new lzw implementation.
  • 5. More validity/regression tests would be helpful.

3. More on min_code_bits

For the value 4 min_code_size is set to 2 instead of 3 this results in the colour index being encoded as 0 and the incorrect colour appearing.

This occurs here:

gift/src/encode.rs

Lines 212 to 213 in 102f3b5

let min_code_bits =
next_high_bit(self.data().iter().copied().max().unwrap_or(0));

[TODO: Provide more details, examples & code.]

Patch/workaround

This patch/workaround "fixed" the issue for me but strictly speaking probably isn't entirely specification compliant[1]:

diff --git a/src/encode.rs b/src/encode.rs
index be410e7..8de1a9a 100644
--- a/src/encode.rs
+++ b/src/encode.rs
@@ -210,7 +210,7 @@ impl ImageData {
     /// Format an image data block
     fn format<W: Write>(&self, w: &mut W) -> io::Result<()> {
         let min_code_bits =
-            next_high_bit(self.data().iter().copied().max().unwrap_or(0));
+            next_high_bit(self.data().iter().copied().max().unwrap_or(0)+1);
         // minimum code bits must be between 2 and 12
         let min_code_bits = 2.max(min_code_bits).min(12);
         w.write_all(&[min_code_bits])?;

[1] Because AFAICT the value is intended to be related to the bit-depth.

Example animated GIF exported with workaround in place:

output16

Related tools

Edited: Added additional content.

c.add_comment(b"") breaks image

Because the encoding will contain one 0 for the empty string (but it already ends the block), followed by another 0 to end the block. Perhaps there should be a non-empty assertion similar to the max length, or maybe empty comments should be skipped.

index out of bounds in decode.rs:754:27 on crafted gif

Test file:

crash-0936c048a8348fa57649ab0066c53bacac228cc6

Test case:

for frame in Decoder::new_unbuffered(Cursor::new(data)) {
    if frame.is_err() {
        return;
    }
}
RUST_BACKTRACE=1 cargo +nightly fuzz run decode artifacts/decode/crash-0936c048a8348fa57649ab0066c53bacac228cc6
       Fresh cc v1.0.50
       Fresh cfg-if v0.1.10
       Fresh lzw v0.10.0
       Fresh pix v0.7.0
       Fresh arbitrary v0.4.0
       Fresh log v0.4.8
       Fresh gift v0.4.0 (/home/niklas/Projekte/gift)
       Fresh libfuzzer-sys v0.3.0
       Fresh gift-fuzz v0.0.0 (/home/niklas/Projekte/gift/fuzz)
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
       Fresh cc v1.0.50
       Fresh cfg-if v0.1.10
       Fresh arbitrary v0.4.0
       Fresh pix v0.7.0
       Fresh lzw v0.10.0
       Fresh log v0.4.8
       Fresh gift v0.4.0 (/home/niklas/Projekte/gift)
       Fresh libfuzzer-sys v0.3.0
       Fresh gift-fuzz v0.0.0 (/home/niklas/Projekte/gift/fuzz)
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/x86_64-unknown-linux-gnu/debug/decode -artifact_prefix=/home/niklas/Projekte/gift/fuzz/artifacts/decode/ artifacts/decode/crash-0936c048a8348fa57649ab0066c53bacac228cc6`
INFO: Seed: 1877210147
INFO: Loaded 1 modules   (26284 inline 8-bit counters): 26284 [0x560749144642, 0x56074914acee), 
INFO: Loaded 1 PC tables (26284 PCs): 26284 [0x56074914acf0,0x5607491b17b0), 
target/x86_64-unknown-linux-gnu/debug/decode: Running 1 inputs 1 time(s) each.
Running: artifacts/decode/crash-0936c048a8348fa57649ab0066c53bacac228cc6
thread '<unnamed>' panicked at 'index out of bounds: the len is 114 but the index is 1686', /home/niklas/Projekte/gift/src/decode.rs:754:27
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/libunwind.rs:86
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print_fmt
             at src/libstd/sys_common/backtrace.rs:78
   3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
             at src/libstd/sys_common/backtrace.rs:59
   4: core::fmt::write
             at src/libcore/fmt/mod.rs:1052
   5: std::io::Write::write_fmt
             at src/libstd/io/mod.rs:1428
   6: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:62
   7: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:49
   8: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:204
   9: std::panicking::default_hook
             at src/libstd/panicking.rs:224
  10: <alloc::boxed::Box<F> as core::ops::function::Fn<A>>::call
             at /rustc/8aa9d2014f4e5258f83b907e8431c59a33acdae7/src/liballoc/boxed.rs:1031
  11: libfuzzer_sys::initialize::{{closure}}
             at /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/src/lib.rs:50
  12: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:474
  13: rust_begin_unwind
             at src/libstd/panicking.rs:378
  14: core::panicking::panic_fmt
             at src/libcore/panicking.rs:85
  15: core::panicking::panic_bounds_check
             at src/libcore/panicking.rs:63
  16: gift::decode::update_raster
             at /home/niklas/Projekte/gift/src/decode.rs:754
  17: gift::decode::Rasters<R>::apply_frame
             at /home/niklas/Projekte/gift/src/decode.rs:716
  18: gift::decode::Rasters<R>::next_raster
             at /home/niklas/Projekte/gift/src/decode.rs:702
  19: <gift::decode::Rasters<R> as core::iter::traits::iterator::Iterator>::next
             at /home/niklas/Projekte/gift/src/decode.rs:670
  20: rust_fuzzer_test_input
             at fuzz_targets/decode.rs:11
  21: libfuzzer_sys::test_input_wrap::{{closure}}
             at /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/src/lib.rs:27
  22: std::panicking::try::do_call
             at /rustc/8aa9d2014f4e5258f83b907e8431c59a33acdae7/src/libstd/panicking.rs:303
  23: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:86
  24: std::panicking::try
             at /rustc/8aa9d2014f4e5258f83b907e8431c59a33acdae7/src/libstd/panicking.rs:281
  25: std::panic::catch_unwind
             at /rustc/8aa9d2014f4e5258f83b907e8431c59a33acdae7/src/libstd/panic.rs:394
  26: LLVMFuzzerTestOneInput
             at /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/src/lib.rs:25
  27: _ZN6fuzzer6Fuzzer15ExecuteCallbackEPKhm
             at libfuzzer/FuzzerLoop.cpp:553
  28: _ZN6fuzzer10RunOneTestEPNS_6FuzzerEPKcm
  29: _ZN6fuzzer12FuzzerDriverEPiPPPcPFiPKhmE
  30: main
             at libfuzzer/FuzzerMain.cpp:19
  31: __libc_start_main
  32: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
==140456== ERROR: libFuzzer: deadly signal
    #0 0x560748c202f1  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x14f2f1)
    #1 0x560748dfe371  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x32d371)
    #2 0x560748dedb1e  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x31cb1e)
    #3 0x560748ded9bf  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x31c9bf)
    #4 0x560748dead95  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x319d95)
    #5 0x7f48b227b7ff  (/usr/lib/libpthread.so.0+0x147ff)
    #6 0x7f48b20c2ce4  (/usr/lib/libc.so.6+0x3bce4)
    #7 0x7f48b20ac856  (/usr/lib/libc.so.6+0x25856)
    #8 0x560748ffba26  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x52aa26)
    #9 0x560748fe3ce5  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x512ce5)
    #10 0x560748dd3c68  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x302c68)
    #11 0x560748feb184  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x51a184)
    #12 0x560748feac9a  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x519c9a)
    #13 0x56074901ae70  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x549e70)
    #14 0x56074901ae34  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x549e34)
    #15 0x560748ccf826  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x1fe826)
    #16 0x560748c7adbd  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x1a9dbd)
    #17 0x560748c7dad3  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x1acad3)
    #18 0x560748c80663  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x1af663)
    #19 0x560748c9ef45  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x1cdf45)
    #20 0x560748dd3662  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x302662)
    #21 0x560748e19634  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x348634)
    #22 0x560748ffca36  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x52ba36)
    #23 0x560748e19025  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x348025)
    #24 0x560748dd4e7c  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x303e7c)
    #25 0x560748dd2fa9  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x301fa9)
    #26 0x560748def68e  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x31e68e)
    #27 0x560748dbdfe1  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x2ecfe1)
    #28 0x560748dc2484  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x2f1484)
    #29 0x560748dbb8b7  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0x2ea8b7)
    #30 0x7f48b20ae022  (/usr/lib/libc.so.6+0x27022)
    #31 0x560748b9fb2d  (/home/niklas/Projekte/gift/fuzz/target/x86_64-unknown-linux-gnu/debug/decode+0xceb2d)

NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
────────────────────────────────────────────────────────────────────────────────

Error: Fuzz target exited with exit code: 77

error should end iterator

The iterator would be safer to use if it would end after an error (i.e. if next returns None at least once after an error).

Example that loops forever:

fn main() {
    for frame in gift::Decoder::new(std::io::Cursor::new(b"")).into_frames() {
        println!("{:?}", frame);
    }
}
Err(UnexpectedEndOfFile)
Err(UnexpectedEndOfFile)
Err(UnexpectedEndOfFile)
[...]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.