Merge #2178: Reject malformed thumbnail text without crashing (#2135) (@Maokus)

This commit is contained in:
aiongg
2026-10-24 01:10:42 +00:00
2 changed files with 17 additions and 4 deletions
+8 -2
View File
@@ -486,10 +486,10 @@ pub fn encode_thumb(w: u32, h: u32, rgba: &[u8]) -> String {
/// Decode a thumbnail to RGB bytes (THUMB_W×THUMB_H×3).
pub fn decode_thumb(text: &str) -> Option<Vec<u8>> {
let t = text.trim();
if t.len() != THUMB_W * THUMB_H * 6 {
if t.len() != THUMB_W * THUMB_H * 6 || !t.is_ascii() {
return None;
}
(0..t.len()).step_by(2).map(|i| u8::from_str_radix(&t[i..i + 2], 16).ok()).collect()
(0..t.len()).step_by(2).map(|i| u8::from_str_radix(t.get(i..i + 2)?, 16).ok()).collect()
}
/// Render a project's main comp at its poster time into a thumbnail.
@@ -943,6 +943,12 @@ mod tests {
use super::*;
use crate::config::{DirConfig, MemoryConfig};
#[test]
fn non_ascii_thumbnail_is_rejected_without_panicking() {
let malformed = format!("aé{}", "0".repeat(THUMB_W * THUMB_H * 6 - 3));
assert!(decode_thumb(&malformed).is_none());
}
#[test]
fn every_builtin_builds_with_controls_and_renders() {
let s = Session::default();
+9 -2
View File
@@ -166,12 +166,13 @@ pub fn encode_thumb(img: &egui::ColorImage) -> String {
out
}
/// Decode a stored hex thumbnail, rejecting malformed or non-ASCII text.
pub fn decode_thumb(text: &str) -> Option<egui::ColorImage> {
let t = text.trim();
if t.len() != THUMB_W * THUMB_H * 6 {
if t.len() != THUMB_W * THUMB_H * 6 || !t.is_ascii() {
return None;
}
let b: Vec<u8> = (0..t.len()).step_by(2).map(|i| u8::from_str_radix(&t[i..i + 2], 16)).collect::<Result<_, _>>().ok()?;
let b: Vec<u8> = (0..t.len()).step_by(2).map(|i| u8::from_str_radix(t.get(i..i + 2)?, 16).ok()).collect::<Option<_>>()?;
let px = b.as_chunks::<3>().0.iter().map(|c| Color32::from_rgb(c[0], c[1], c[2])).collect();
Some(egui::ColorImage::new([THUMB_W, THUMB_H], px))
}
@@ -496,6 +497,12 @@ fn run_actions(app: &mut EffectcraftApp, ctx: &egui::Context, actions: Vec<(&str
mod tests {
use super::*;
#[test]
fn non_ascii_thumbnail_is_rejected_without_panicking() {
let malformed = format!("aé{}", "0".repeat(THUMB_W * THUMB_H * 6 - 3));
assert!(decode_thumb(&malformed).is_none());
}
#[test]
fn recent_list_comes_from_settings() {
let mut prefs = effectcraft_engine::prefs::Prefs::default();