jrmuizel / raqote

Rust 2D graphics library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Panic using transform on filled rect with negative origin

jdm opened this issue · comments

    #[test]
    fn wat() {
        let mut dt = DrawTarget::new(100, 50);
        let options = DrawOptions::new();

        let img = Image {
            width: 100,
            height: 50,
            data: &vec![0xffff0000; 100*50],
        };

        let identity = Transform::identity();

        let img_src = Source::Image(img, ExtendMode::Repeat, FilterMode::Nearest, identity);
        let transform = dt.get_transform();
        dt.set_transform(&transform.pre_translate(euclid::vec2(0., 1.)));
        dt.fill_rect(0., -1., 100., 50., &img_src, &options);
    }

This yields:

---- tests::tests::wat stdout ----
thread 'tests::tests::wat' panicked at 'attempt to add with overflow', src/blitter.rs:350:49
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/libunwind.rs:86
   1: backtrace::backtrace::trace_unsynchronized
             at /Users/runner/.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:1053
   5: std::io::Write::write_fmt
             at /rustc/96bb8b31c81dc2394317f2f083c3acf8087efea1/src/libstd/io/mod.rs:1428
   6: std::io::impls::<impl std::io::Write for alloc::boxed::Box<W>>::write_fmt
             at src/libstd/io/impls.rs:156
   7: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:62
   8: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:49
   9: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:204
  10: std::panicking::default_hook
             at src/libstd/panicking.rs:221
  11: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:470
  12: rust_begin_unwind
             at src/libstd/panicking.rs:378
  13: core::panicking::panic_fmt
             at src/libcore/panicking.rs:85
  14: core::panicking::panic
             at src/libcore/panicking.rs:52
  15: <raqote::blitter::ImageRepeatAlphaShader as raqote::blitter::Shader>::shade_span
             at src/blitter.rs:350
  16: <raqote::blitter::ShaderMaskBlitter as raqote::blitter::Blitter>::blit_span
             at src/blitter.rs:464
  17: raqote::draw_target::DrawTarget::composite
             at src/draw_target.rs:923
  18: raqote::draw_target::DrawTarget::fill
             at src/draw_target.rs:671
  19: raqote::draw_target::DrawTarget::fill_rect
             at src/draw_target.rs:647
  20: raqote::tests::tests::wat
             at src/tests.rs:759
  21: raqote::tests::tests::wat::{{closure}}
             at src/tests.rs:744
  22: core::ops::function::FnOnce::call_once
             at /rustc/96bb8b31c81dc2394317f2f083c3acf8087efea1/src/libcore/ops/function.rs:232
  23: <alloc::boxed::Box<F> as core::ops::function::FnOnce<A>>::call_once
             at /rustc/96bb8b31c81dc2394317f2f083c3acf8087efea1/src/liballoc/boxed.rs:1017
  24: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:86
  25: std::panicking::try
             at /rustc/96bb8b31c81dc2394317f2f083c3acf8087efea1/src/libstd/panicking.rs:281
  26: std::panic::catch_unwind
             at /rustc/96bb8b31c81dc2394317f2f083c3acf8087efea1/src/libstd/panic.rs:394
  27: test::run_test_in_process
             at src/libtest/lib.rs:542
  28: test::run_test::run_test_inner::{{closure}}
             at src/libtest/lib.rs:451

If I change the 1. to 2. and -1. to -2., I get this panic instead:

---- tests::tests::wat stdout ----
thread 'tests::tests::wat' panicked at 'index 18446744073709551516 out of range for slice of length 5000', src/libcore/slice/mod.rs:2739:5
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/libunwind.rs:86
   1: backtrace::backtrace::trace_unsynchronized
             at /Users/runner/.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:1053
   5: std::io::Write::write_fmt
             at /rustc/96bb8b31c81dc2394317f2f083c3acf8087efea1/src/libstd/io/mod.rs:1428
   6: std::io::impls::<impl std::io::Write for alloc::boxed::Box<W>>::write_fmt
             at src/libstd/io/impls.rs:156
   7: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:62
   8: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:49
   9: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:204
  10: std::panicking::default_hook
             at src/libstd/panicking.rs:221
  11: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:470
  12: rust_begin_unwind
             at src/libstd/panicking.rs:378
  13: core::panicking::panic_fmt
             at src/libcore/panicking.rs:85
  14: core::slice::slice_index_len_fail
             at src/libcore/slice/mod.rs:2739
  15: <core::ops::range::Range<usize> as core::slice::SliceIndex<[T]>>::index
             at /rustc/96bb8b31c81dc2394317f2f083c3acf8087efea1/src/libcore/slice/mod.rs:2903
  16: core::slice::<impl core::ops::index::Index<I> for [T]>::index
             at /rustc/96bb8b31c81dc2394317f2f083c3acf8087efea1/src/libcore/slice/mod.rs:2721
  17: <raqote::blitter::ImageRepeatAlphaShader as raqote::blitter::Shader>::shade_span
             at src/blitter.rs:350
  18: <raqote::blitter::ShaderMaskBlitter as raqote::blitter::Blitter>::blit_span
             at src/blitter.rs:464
  19: raqote::draw_target::DrawTarget::composite
             at src/draw_target.rs:923
  20: raqote::draw_target::DrawTarget::fill
             at src/draw_target.rs:671
  21: raqote::draw_target::DrawTarget::fill_rect
             at src/draw_target.rs:647
  22: raqote::tests::tests::wat
             at src/tests.rs:759
  23: raqote::tests::tests::wat::{{closure}}
             at src/tests.rs:744
  24: core::ops::function::FnOnce::call_once
             at /rustc/96bb8b31c81dc2394317f2f083c3acf8087efea1/src/libcore/ops/function.rs:232
  25: <alloc::boxed::Box<F> as core::ops::function::FnOnce<A>>::call_once
             at /rustc/96bb8b31c81dc2394317f2f083c3acf8087efea1/src/liballoc/boxed.rs:1017
  26: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:86
  27: std::panicking::try
             at /rustc/96bb8b31c81dc2394317f2f083c3acf8087efea1/src/libstd/panicking.rs:281
  28: std::panic::catch_unwind
             at /rustc/96bb8b31c81dc2394317f2f083c3acf8087efea1/src/libstd/panic.rs:394
  29: test::run_test_in_process
             at src/libtest/lib.rs:542
  30: test::run_test::run_test_inner::{{closure}}
             at src/libtest/lib.rs:451
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
frame #5: 0x000000010001fa19 raqote-f498050c0c333afe`_$LT$raqote..blitter..ImageRepeatAlphaShader$u20$as$u20$raqote..blitter..Shader$GT$::shade_span::hbc0fee0ed44fbc43(self=0x000070000fe71d90, x=0, y=-1, dest=&mut [u32] @ 0x000070000fe71918, count=100) at blitter.rs:350:48
   347 	            let len = count.min((self.image.width - x) as usize);
   348 	            let d = &mut dest[dest_x..dest_x + len];
   349 	            let src_start = (self.image.width * y + x) as usize;
-> 350 	            let s = &self.image.data[src_start..src_start + len];
   351
   352 	            for (d, s) in d.iter_mut().zip(s) {
   353 	                *d = alpha_mul(*s, self.alpha);
(lldb) p src_start
(unsigned long) $0 = 18446744073709551516
(lldb) p len
(unsigned long) $1 = 100
(lldb) p self->image.width
(int) $2 = 100
  Fix-it applied, fixed expression was:
    self->image->width
(lldb) p y
(int) $3 = -1
(lldb) p x
(int) $4 = 0
(lldb)

When we create the ImageRepeatAlphaShader we pass in a negative y offset, which ends up being used in ImageRepeatAlphaShader::shade_span to yield negative y values, which are used to calculate an array index by casting to usize.