RazrFalcon / tiny-skia

A tiny Skia subset ported to Rust
BSD 3-Clause "New" or "Revised" License
1.05k stars 67 forks source link

Panic : stroke_path hair line (specific path values) #47

Closed Wardenfar closed 2 years ago

Wardenfar commented 2 years ago

With tiny-skia = "0.6.3"

This code crash, i think it is related to "hair line" because the same path with 1.0 for width works :

use tiny_skia::{Pixmap, PathBuilder, Transform, Stroke, Paint};

fn main() {
    let mut pixmap = Pixmap::new(512, 512).unwrap();

    let mut builder = PathBuilder::default();
    builder.move_to(338.80466, 545.2891);
    builder.line_to(369.26462, 577.8069);
    builder.line_to(488.0846, 471.04388);
    let path = builder.finish().unwrap();

    let stroke = Stroke {
        width: 0.0, // with 1.0 : it runs fine
        ..Default::default()
    };

    pixmap.stroke_path(&path, &Paint::default(), &stroke, Transform::identity(), None);
}

Stacktrace :

thread 'main' panicked at 'range end index 262588 out of range for slice of length 262144', ~\.cargo\registry\src\github.com-1ecc6299db9ec823\tiny-skia-0.6.3\src\pipeline\blitter.rs:259:17
stack backtrace:
   0: std::panicking::begin_panic_handler
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\/library\std\src\panicking.rs:584
   1: core::panicking::panic_fmt
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\/library\core\src\panicking.rs:143
   2: core::slice::index::slice_end_index_len_fail
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\/library\core\src\slice\index.rs:43
   3: core::slice::index::impl$3::index_mut<tiny_skia::color::PremultipliedColorU8>
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\library\core\src\slice\index.rs:256
   4: core::slice::index::impl$1::index_mut<tiny_skia::color::PremultipliedColorU8,core::ops::range::Range<usize> >
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\library\core\src\slice\index.rs:26
   5: tiny_skia::pipeline::blitter::impl$1::blit_rect
             at ~\.cargo\registry\src\github.com-1ecc6299db9ec823\tiny-skia-0.6.3\src\pipeline\blitter.rs:259
   6: tiny_skia::pipeline::blitter::impl$1::blit_h
             at ~\.cargo\registry\src\github.com-1ecc6299db9ec823\tiny-skia-0.6.3\src\pipeline\blitter.rs:180
   7: tiny_skia::scan::hairline::hair_line_rgn
             at ~\.cargo\registry\src\github.com-1ecc6299db9ec823\tiny-skia-0.6.3\src\scan\hairline.rs:102
   8: tiny_skia::scan::hairline::stroke_path_impl
             at ~\.cargo\registry\src\github.com-1ecc6299db9ec823\tiny-skia-0.6.3\src\scan\hairline.rs:205
   9: tiny_skia::scan::hairline::stroke_path
             at ~\.cargo\registry\src\github.com-1ecc6299db9ec823\tiny-skia-0.6.3\src\scan\hairline.rs:36
  10: tiny_skia::pixmap::PixmapMut::stroke_hairline
             at ~\.cargo\registry\src\github.com-1ecc6299db9ec823\tiny-skia-0.6.3\src\painter.rs:384
  11: tiny_skia::pixmap::PixmapMut::stroke_path
             at ~\.cargo\registry\src\github.com-1ecc6299db9ec823\tiny-skia-0.6.3\src\painter.rs:359
  12: tiny_skia::pixmap::Pixmap::stroke_path
             at ~\.cargo\registry\src\github.com-1ecc6299db9ec823\tiny-skia-0.6.3\src\painter.rs:143
  13: crash::main
             at .\src\main.rs:17
  14: core::ops::function::FnOnce::call_once<void (*)(),tuple$<> >
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\library\core\src\ops\function.rs:227
RazrFalcon commented 2 years ago

I must say you have hit an extreme edge case. No only non-aliases hairlines are useless in most cases, but also the line angle must be perfect to trigger the overflow.

Wardenfar commented 2 years ago

I used your crate to do intensive drawing on millions of tiny images, I guess this has the same effect as fuzzing ;)

Thank you for the fix

RazrFalcon commented 2 years ago

Yes, you have indeed need this random magic to hit such sweet spot.

Published a new version too.