mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-28 12:36:56 -06:00
Model: an exhausted id space refuses growth instead of duplicating ids (#407)
alloc_id bumped next_id with saturating_add: a presentation whose next_id reached u32::MAX (a hostile file can arrive that way; fix_next_id imports it) handed out that same id to every new slide, shape, layout and media - duplicate ids, ambiguous references, silent corruption on every later insert. alloc_id now returns Option<u32> via checked_add, and every caller refuses: the engine's insert/duplicate/media/layout commands answer with a clear error naming the command, paste and duplicate re-id helpers propagate it, media addition is fallible, and a fresh slide is Option. The pptx export's synthesized blank layout is guarded the same way. Loading keeps such a deck viewable: repair re-ids duplicate slides while it can, and a duplicate it cannot re-id stays as it is - growth is refused, and only that duplicate keeps its ambiguous id. Renumbering the loaded graph was rejected: it needs the cross-document reference remapping that issue #406 tracks. Tests: model exhaustion (alloc_id None, fresh media refused, a new slide refused), engine (slide.new, shape.insert, slide.duplicate and edit.duplicate all refuse; the document holds no duplicate ids), format repair (an unre-id-able duplicate stays visible).
This commit is contained in:
@@ -284,7 +284,7 @@ fn fill(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
} else if p.get("picture").is_some() {
|
||||
let (name, bytes) = super::insert::media_bytes(&with_param(p, "data", p.get("picture").cloned().unwrap_or_default()), "shape.fill")?;
|
||||
let ct = super::insert::content_type(&name, &bytes);
|
||||
let media = s.edit(|doc, _| Ok(doc.add_media(&name, ct, bytes)))?;
|
||||
let media = s.edit(|doc, _| doc.add_media(&name, ct, bytes).ok_or_else(|| bad("shape.fill", NO_ID_SPACE)))?;
|
||||
Some(Some(Fill::Picture(PictureFill { media, ..Default::default() })))
|
||||
} else {
|
||||
None
|
||||
@@ -674,7 +674,7 @@ fn picture_reset(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
fn picture_change(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let (name, bytes) = super::insert::media_bytes(p, "picture.change")?;
|
||||
let ct = super::insert::content_type(&name, &bytes);
|
||||
let media = s.edit(|doc, _| Ok(doc.add_media(&name, ct, bytes)))?;
|
||||
let media = s.edit(|doc, _| doc.add_media(&name, ct, bytes).ok_or_else(|| bad("picture.change", NO_ID_SPACE)))?;
|
||||
edit_shapes(s, p, "picture.change", |sh| {
|
||||
if let deckcraft_model::ShapeKind::Picture { fill } = &mut sh.kind {
|
||||
fill.media = media;
|
||||
|
||||
Reference in New Issue
Block a user