Panic using transform on filled rect with negative origin
jdm opened this issue · comments
Josh Matthews commented
#[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.
Josh Matthews commented
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)
Josh Matthews commented
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.