diff --git a/crates/typst-library/src/layout/enum.rs b/crates/typst-library/src/layout/enum.rs index c505f189d..436aacb91 100644 --- a/crates/typst-library/src/layout/enum.rs +++ b/crates/typst-library/src/layout/enum.rs @@ -269,6 +269,7 @@ impl Layout for EnumElem { &cells, regions, styles, + self.span(), ); Ok(layouter.layout(vt)?.fragment) diff --git a/crates/typst-library/src/layout/flow.rs b/crates/typst-library/src/layout/flow.rs index 432ab5e8f..1feee4b85 100644 --- a/crates/typst-library/src/layout/flow.rs +++ b/crates/typst-library/src/layout/flow.rs @@ -29,6 +29,12 @@ impl Layout for FlowElem { styles: StyleChain, regions: Regions, ) -> SourceResult { + if !regions.size.x.is_finite() && regions.expand.x { + bail!(error!(self.span(), "cannot expand into infinite width")); + } + if !regions.size.y.is_finite() && regions.expand.y { + bail!(error!(self.span(), "cannot expand into infinite height")); + } let mut layouter = FlowLayouter::new(regions, styles); for mut child in &self.children() { diff --git a/crates/typst-library/src/layout/grid.rs b/crates/typst-library/src/layout/grid.rs index 134bdc7c3..8d0157823 100644 --- a/crates/typst-library/src/layout/grid.rs +++ b/crates/typst-library/src/layout/grid.rs @@ -114,6 +114,7 @@ impl Layout for GridElem { &cells, regions, styles, + self.span(), ); // Measure the columns and layout the grid row-by-row. @@ -161,6 +162,8 @@ pub struct GridLayouter<'a> { initial: Size, /// Frames for finished regions. finished: Vec, + /// The span of the grid element. + span: Span, } /// The resulting sizes of columns and rows in a grid. @@ -202,6 +205,7 @@ impl<'a> GridLayouter<'a> { cells: &'a [Content], regions: Regions<'a>, styles: StyleChain<'a>, + span: Span, ) -> Self { let mut cols = vec![]; let mut rows = vec![]; @@ -272,6 +276,7 @@ impl<'a> GridLayouter<'a> { lrows: vec![], initial: regions.size, finished: vec![], + span, } } @@ -563,6 +568,10 @@ impl<'a> GridLayouter<'a> { height: Abs, y: usize, ) -> SourceResult { + if !height.is_finite() { + bail!(error!(self.span, "cannot create grid with infinite height")); + } + let mut output = Frame::soft(Size::new(self.width, height)); let mut pos = Point::zero(); diff --git a/crates/typst-library/src/layout/list.rs b/crates/typst-library/src/layout/list.rs index a9dad85b6..34e0e6fbe 100644 --- a/crates/typst-library/src/layout/list.rs +++ b/crates/typst-library/src/layout/list.rs @@ -162,6 +162,7 @@ impl Layout for ListElem { &cells, regions, styles, + self.span(), ); Ok(layouter.layout(vt)?.fragment) diff --git a/crates/typst-library/src/layout/table.rs b/crates/typst-library/src/layout/table.rs index 339b8b259..1b84a616b 100644 --- a/crates/typst-library/src/layout/table.rs +++ b/crates/typst-library/src/layout/table.rs @@ -163,6 +163,7 @@ impl Layout for TableElem { &cells, regions, styles, + self.span(), ); // Measure the columns and layout the grid row-by-row. diff --git a/crates/typst-library/src/visualize/line.rs b/crates/typst-library/src/visualize/line.rs index 6837caf1c..da497cf43 100644 --- a/crates/typst-library/src/visualize/line.rs +++ b/crates/typst-library/src/visualize/line.rs @@ -75,6 +75,9 @@ impl Layout for LineElem { let size = start.max(start + delta).max(Size::zero()); let target = regions.expand.select(regions.size, size); + if !target.is_finite() { + bail!(error!(self.span(), "cannot create line with infinite length")); + } let mut frame = Frame::soft(target); let shape = Geometry::Line(delta.to_point()).stroked(stroke); frame.push(start.to_point(), FrameItem::Shape(shape, self.span())); diff --git a/crates/typst-library/src/visualize/polygon.rs b/crates/typst-library/src/visualize/polygon.rs index 1d19a94d9..b1ed9eaa4 100644 --- a/crates/typst-library/src/visualize/polygon.rs +++ b/crates/typst-library/src/visualize/polygon.rs @@ -130,6 +130,9 @@ impl Layout for PolygonElem { .collect(); let size = points.iter().fold(Point::zero(), |max, c| c.max(max)).to_size(); + if !size.is_finite() { + bail!(error!(self.span(), "cannot create polygon with infinite size")); + } let mut frame = Frame::hard(size); // Only create a path if there are more than zero points. diff --git a/tests/typ/bugs/layout-infinite-lengths.typ b/tests/typ/bugs/layout-infinite-lengths.typ new file mode 100644 index 000000000..501e517ed --- /dev/null +++ b/tests/typ/bugs/layout-infinite-lengths.typ @@ -0,0 +1,25 @@ +// Test that passing infinite lengths to drawing primitives does not crash Typst. + +--- +#set page(width: auto, height: auto) + +// Error: cannot expand into infinite width +#layout(size => grid(columns: (size.width, size.height))[a][b][c][d]) + +--- +#set page(width: auto, height: auto) + +// Error: 17-66 cannot create grid with infinite height +#layout(size => grid(rows: (size.width, size.height))[a][b][c][d]) + +--- +#set page(width: auto, height: auto) + +// Error: 17-41 cannot create line with infinite length +#layout(size => line(length: size.width)) + +--- +#set page(width: auto, height: auto) + +// Error: 17-54 cannot create polygon with infinite size +#layout(size => polygon((0pt,0pt), (0pt, size.width)))