Skip to content

Commit

Permalink
fix: 🐛 memory access out of range on resize (#76)
Browse files Browse the repository at this point in the history
  • Loading branch information
theashraf authored Feb 5, 2024
1 parent 629719d commit 443ae46
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 79 deletions.
5 changes: 3 additions & 2 deletions dotlottie-ffi/emscripten_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ EMSCRIPTEN_BINDINGS(DotLottiePlayer)
// .field("version", &Manifest::version);

class_<DotLottiePlayer>("DotLottiePlayer")
.smart_ptr<std::shared_ptr<DotLottiePlayer>>("DotLottiePlayer")
.constructor(&DotLottiePlayer::init, allow_raw_pointers())
.function("buffer", &buffer)
.function("clear", &DotLottiePlayer::clear)
Expand All @@ -98,7 +99,7 @@ EMSCRIPTEN_BINDINGS(DotLottiePlayer)
.function("setFrame", &DotLottiePlayer::set_frame)
.function("stop", &DotLottiePlayer::stop)
.function("totalFrames", &DotLottiePlayer::total_frames)
.function("subscribe", &DotLottiePlayer::subscribe)
.function("unsubscribe", &DotLottiePlayer::unsubscribe)
// .function("subscribe", &DotLottiePlayer::subscribe)
// .function("unsubscribe", &DotLottiePlayer::unsubscribe)
.function("isComplete", &DotLottiePlayer::is_complete);
}
94 changes: 47 additions & 47 deletions dotlottie-ffi/src/dotlottie_player_cpp.udl
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
namespace dotlottie_player {
};

[Trait]
interface Observer {
void on_load();
void on_load_error();
void on_play();
void on_pause();
void on_stop();
void on_frame(f32 frame_no);
void on_render(f32 frame_no);
void on_loop(u32 loop_count);
void on_complete();
};
///[Trait]
///interface Observer {
/// void on_load();
/// void on_load_error();
/// void on_play();
/// void on_pause();
/// void on_stop();
/// void on_frame(f32 frame_no);
/// void on_render(f32 frame_no);
/// void on_loop(u32 loop_count);
/// void on_complete();
///};

enum Mode {
"Forward",
Expand All @@ -31,49 +31,49 @@ dictionary Config {
u32 background_color;
};

dictionary ManifestTheme {
string id;
sequence<string> values;
};
///dictionary ManifestTheme {
/// string id;
/// sequence<string> values;
///};

dictionary ManifestThemes {
sequence<ManifestTheme>? value;
};
///dictionary ManifestThemes {
/// sequence<ManifestTheme>? value;
///};

dictionary ManifestAnimation {
boolean? autoplay;
string? defaultTheme;
i8? direction;
boolean? hover;
string id;
u32? intermission;
boolean? loop;
u32? loop_count;
string? playMode;
u32? speed;
string? themeColor;
};
///dictionary ManifestAnimation {
/// boolean? autoplay;
/// string? defaultTheme;
/// i8? direction;
/// boolean? hover;
/// string id;
/// u32? intermission;
/// boolean? loop;
/// u32? loop_count;
/// string? playMode;
/// u32? speed;
/// string? themeColor;
///};

dictionary Manifest {
string? active_animation_id;
sequence<ManifestAnimation> animations;
string? author;
string? description;
string? generator;
string? keywords;
u32? revision;
ManifestThemes? themes;
sequence<string>? states;
string? version;
};
///dictionary Manifest {
/// string? active_animation_id;
/// sequence<ManifestAnimation> animations;
/// string? author;
/// string? description;
/// string? generator;
/// string? keywords;
/// u32? revision;
/// ManifestThemes? themes;
/// sequence<string>? states;
/// string? version;
///};

interface DotLottiePlayer {
constructor(Config config);
boolean load_animation_data([ByRef] string animation_data, u32 width, u32 height);
boolean load_animation_path([ByRef] string animation_path, u32 width, u32 height);
boolean load_dotlottie_data([ByRef] bytes file_data, u32 width, u32 height);
boolean load_animation([ByRef] string animation_id, u32 width, u32 height);
Manifest? manifest();
/// Manifest? manifest();
string manifest_string();
u64 buffer_ptr();
u64 buffer_len();
Expand All @@ -95,7 +95,7 @@ interface DotLottiePlayer {
boolean render();
boolean resize(u32 width, u32 height);
void clear();
void subscribe(Observer observer);
void unsubscribe([ByRef] Observer observer);
/// void subscribe(Observer observer);
/// void unsubscribe([ByRef] Observer observer);
boolean is_complete();
};
51 changes: 22 additions & 29 deletions dotlottie-rs/src/lottie_renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub struct LottieRenderer {
thorvg_animation: Option<thorvg::Animation>,
thorvg_canvas: Option<thorvg::Canvas>,
thorvg_background_shape: Option<thorvg::Shape>,
thorvg_picture: Option<thorvg::Picture>,
picture_width: f32,
picture_height: f32,
pub width: u32,
Expand All @@ -37,6 +38,7 @@ impl LottieRenderer {
thorvg_animation: None,
thorvg_canvas: None,
thorvg_background_shape: None,
thorvg_picture: None,
buffer: vec![],
width: 0,
height: 0,
Expand All @@ -52,18 +54,16 @@ impl LottieRenderer {
width: u32,
height: u32,
) -> Result<(), LottieRendererError> {
self.thorvg_animation = Some(thorvg::Animation::new());
let thorvg_animation = thorvg::Animation::new();
self.thorvg_picture = thorvg_animation.new_picture();
self.thorvg_animation = Some(thorvg_animation);
self.thorvg_background_shape = Some(thorvg::Shape::new());
self.thorvg_canvas = Some(thorvg::Canvas::new(thorvg::TvgEngine::TvgEngineSw, 0));

self.buffer = vec![0; (width * height * 4) as usize];
self.width = width;
self.height = height;

let thorvg_animation = self
.thorvg_animation
.as_mut()
.ok_or(LottieRendererError::AnimationNotLoaded)?;
self.buffer
.resize((self.width * self.height * 4) as usize, 0);

let thorvg_canvas = self
.thorvg_canvas
Expand All @@ -85,7 +85,7 @@ impl LottieRenderer {
)
.map_err(LottieRendererError::ThorvgError)?;

if let Some(picture) = &mut thorvg_animation.get_picture() {
if let Some(picture) = &mut self.thorvg_picture {
picture.load(path)?;

let (pw, ph) = picture.get_size()?;
Expand Down Expand Up @@ -115,18 +115,16 @@ impl LottieRenderer {
height: u32,
copy: bool,
) -> Result<(), LottieRendererError> {
self.thorvg_animation = Some(thorvg::Animation::new());
let thorvg_animation = thorvg::Animation::new();
self.thorvg_picture = thorvg_animation.new_picture();
self.thorvg_animation = Some(thorvg_animation);
self.thorvg_background_shape = Some(thorvg::Shape::new());
self.thorvg_canvas = Some(thorvg::Canvas::new(thorvg::TvgEngine::TvgEngineSw, 0));

self.buffer = vec![0; (width * height * 4) as usize];
self.width = width;
self.height = height;

let thorvg_animation = self
.thorvg_animation
.as_mut()
.ok_or(LottieRendererError::AnimationNotLoaded)?;
self.buffer
.resize((self.width * self.height * 4) as usize, 0);

let thorvg_canvas = self
.thorvg_canvas
Expand All @@ -148,7 +146,7 @@ impl LottieRenderer {
)
.map_err(LottieRendererError::ThorvgError)?;

if let Some(picture) = &mut thorvg_animation.get_picture() {
if let Some(picture) = &mut self.thorvg_picture {
picture.load_data(data.as_bytes(), "lottie", copy)?;

let (pw, ph) = picture.get_size()?;
Expand Down Expand Up @@ -249,11 +247,6 @@ impl LottieRenderer {
.as_mut()
.ok_or(LottieRendererError::AnimationNotLoaded)?;

let thorvg_animation = self
.thorvg_animation
.as_mut()
.ok_or(LottieRendererError::AnimationNotLoaded)?;

if (width, height) == (self.width, self.height) {
return Ok(());
}
Expand All @@ -267,25 +260,25 @@ impl LottieRenderer {
self.width = width;
self.height = height;

let mut buffer = vec![0; (width * height * 4) as usize];
self.buffer
.resize((self.width * self.height * 4) as usize, 0);

thorvg_canvas
.set_target(
&mut buffer,
width,
width,
height,
&mut self.buffer,
self.width,
self.width,
self.height,
thorvg::TvgColorspace::ABGR8888,
)
.map_err(LottieRendererError::ThorvgError)?;

if let Some(picture) = &mut thorvg_animation.get_picture() {
if let Some(picture) = &mut self.thorvg_picture {
let (pw, ph) = picture.get_size()?;
let (scale, shift_x, shift_y) = calculate_scale_and_shift(pw, ph, width, height);

picture.scale(scale)?;
picture.translate(shift_x, shift_y)?;

self.buffer = buffer;
}

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion dotlottie-rs/src/thorvg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ impl Animation {
}
}

pub fn get_picture(&self) -> Option<Picture> {
pub fn new_picture(&self) -> Option<Picture> {
let raw_picture = unsafe { tvg_animation_get_picture(self.raw_animation) };

if raw_picture.is_null() {
Expand Down

0 comments on commit 443ae46

Please sign in to comment.