gitlab#323 - Limit the number of instancings through the <use> element

A pathological SVG file can do this:

<svg>
  <defs>
    <rect id="foo" .../>

    <g id="foo1">
      <use xlink:href="#foo"/>
      ... repeat 10 times ...
    </g>

    <g id="foo2">
        <use xlink:href="#foo1"/>
        ... repeat 10 times ...
    </g>

    <g id="foo3">
        <use xlink:href="#foo2"/>
        ... repeat 10 times ...
    </g>

    ... etc ...
  </defs>

  <use xlink:href="#foo17"/>
</svg>

This would cause about 10^17 objects to be rendered.  While this does
not exhaust memory (the objects are not instanced in memory), it would
take a really long time to render that many objects.

So, we now have a limit on up to 500,000 objects instanced through
<use>.  We can tweak this limit later, or the way in which it is
computed; the point is that we can now detect this situation and
propagate an error upstream.

#323
parent a762912f
......@@ -734,6 +734,10 @@ impl<'a> DrawingCtx<'a> {
self.drawsub_stack.push(top);
}
if res.is_ok() {
res = self.check_limits();
}
res
}
......@@ -747,6 +751,14 @@ impl<'a> DrawingCtx<'a> {
pub fn increase_num_elements_rendered_through_use(&mut self, n: usize) {
self.num_elements_rendered_through_use += n;
}
fn check_limits(&self) -> Result<(), RenderingError> {
if self.num_elements_rendered_through_use > 500_000 {
Err(RenderingError::InstancingLimit)
} else {
Ok(())
}
}
}
// remove this binding once pangocairo-rs has ContextExt::set_resolution()
......
......@@ -87,6 +87,7 @@ impl<'a> From<BasicParseError<'a>> for AttributeError {
pub enum RenderingError {
Cairo(cairo::Status),
CircularReference,
InstancingLimit,
}
impl From<cairo::Status> for RenderingError {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment