Possible bug in librsvg

Hello,

I encountered a bug in librsvg (or at least, rsvg-convert) today. Unfortuntately, I don’t have access to current binaries for my platforms (Ubuntu or Windows, tested on 2.58.0), and setting up a build environment for librsvg is rather cumbersome by my standards. The GitLab repo pointed me here for questions. Could someone verify that it works on current versions and report the bug if so?

I encountered this bug while investigating why this file on Wikimedia Commons fails to render. Inkscape and Firefox display it fine. It appears that very small values in linear gradient matrix transforms can cause an error, preventing the image from rendering. A small example is provided below. When using rsvg-convert, even with logging enabled, I only get this error:

Error rendering SVG librsvg_test.svg: rendering error: NoMemory

Changing the value in the reproduction file from 3e-5 to 4e-5 allows librsvg to render the file.

<svg width="1" height="1" version="1.1">
 <defs>
  <linearGradient id="a" x1="0" x2="1" y1="0" y2="1" gradientTransform="matrix(3e-5 0 0 1 0 0)"><stop stop-color="white" offset="0"/><stop stop-color="black" offset="1"/></linearGradient>
 </defs>
 <g>
  <rect x="0" y="0" width="1" height="1" fill="url(#a)"/>
 </g>
</svg>

I think you are running into this bug in librsvg - Cairo has trouble with very small gradients or patterns. And due to the way the code is structured, an internal CAIRO_STATUS_INVALID_MATRIX error gets translated into a NULL, which the calling code interprets as out-of-memory.

I have not investigated this very deeply in Cairo. If I remember correctly, at some point it decides the size of the Pixman surface to create for a pattern, and it ends up being too big for Pixman’s limits - even if the gradient or pattern are tiny.

A few unrelated notes:

  • The original SVG from Wikimedia Commons renders correctly for me at the default size with rsvg-convert 2.58.1, or 2.61.0, either with Cairo 1.18.2.
  • The minimal SVG you posted is too small to get anything out of it - it’s 1x1 pixels. How are you rendering it to exhibit the bug?
  • Setting up a build environment for librsvg is pretty reliable… are you having trouble with those instructions? Maybe there’s something I can improve there.

I think you are running into this bug in librsvg

I looked at that bug, but the error message is different (and does not mention Cairo). It’s possible that it’s actually the same bug under the hood though, I don’t know enough to say.

This is all I’m doing to render the files.

$ rsvg-convert -v
rsvg-convert version 2.58.0
$ rsvg-convert Pyramide_des_âges_Kourou_1999.svg
Error rendering SVG Pyramide_des_âges_Kourou_1999.svg: rendering error: NoMemory
$ rsvg-convert librsvg_test.svg
Error rendering SVG librsvg_test.svg: rendering error: NoMemory
$ rsvg-convert librsvg_test2.svg
�PNG
␦
IHDĉbKGD�������
               IDA�cbU2�IEND�B�

(librsvg_test2.svg has the value changed to 4e-5). The actual appearance of the test file is inconsequential - it’s just to see whether rsvg will produce an output or not. Is there something else I’m missing?

As for the build environment, I’ll have to look at those directions again. I think last time I skipped over the podman option and was trying to install everything manually, which had some conflicting dependencies with other parts of my system.

Podman was indeed much easier to get working! Although I did need to edit ci/pull-container-image.sh slightly to use bash rather than sh, as my sh’s set (which should just be the default Ubuntu 24.04 binary) doesn’t have the pipefail option. In any case, I was able to verify the same behavior with the 2.61.0 debug binary build by cargo.

Well, now you’ve got me really puzzled. My test in the container image works fine, both with the wikimedia image and your reduced case. In theory we are running exactly the same code!

Can you run RSVG_LOG=1 rsvg-convert foo.svg and paste the output? hopefully it lets me see the names of the objects that caused it to fail.

Ah, I notice you mentioned testing in the container image. When I built it before, I was then calling the built executable outside the container, back in Ubuntu. When I run it from inside the container, it works as expected! I’m guessing this is a difference in dependencies that don’t get bundled or some such?

It seems like this is probably resolved, but in case it helps, here’s the output for the sample file, when running with RSVG_LOG=1 in Ubuntu:

(svg id=None
(defs id=None
)
(g id=None
(rect id=None
)
)
)
Error rendering SVG librsvg/librsvg_test.svg: rendering error: NoMemory

And the Wikimedia file:

Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 120 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 120 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 120 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 120 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 137 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
Invalid declaration; ignoring: (ParseError { kind: Custom(UnknownProperty), location: SourceLocation { line: 0, column: 122 } }, "text-align:start;")
(svg id=svg2
(defs id=defs4
)
(namedview id=base
)
(metadata id=metadata7
)
(g id=layer1
(rect id=rect2358
)
(rect id=rect4314
)
(rect id=rect4318
)
(rect id=rect4322
)
(rect id=rect4326
)
(rect id=rect4330
)
(rect id=rect4334
)
(rect id=rect4338
)
(rect id=rect4342
)
(rect id=rect4346
)
(rect id=rect4350
)
(rect id=rect4372
)
(rect id=rect4376
)
(rect id=rect4380
)
(rect id=rect4384
)
(rect id=rect4388
)
(rect id=rect4392
)
(rect id=rect4396
)
(rect id=rect4400
)
(rect id=rect4404
)
(rect id=rect4408
)
)
)
Error rendering SVG librsvg/Pyramide_des_âges_Kourou_1999.svg: rendering error: NoMemory

Ah, I notice you mentioned testing in the container image. When I built it before, I was then calling the built executable outside the container, back in Ubuntu. When I run it from inside the container, it works as expected! I’m guessing this is a difference in dependencies that don’t get bundled or some such?

Yes, exactly. The container image has specific versions of the shared libraries that librsvg and rsvg-convert depend on: cairo, pango, freetype, etc. The versions inside the container are defined here.

If the binary happens to run outside the container (lucky you; I didn’t quite expect that to work!), then the system’s libraries will be used instead. Can you please confirm your versions of cairo and pixman? My suspicion is that your system’s Cairo is a bit old - the “out of memory” bug for gradients was fixed in Cairo 1.18.2.

Thanks for noticing this; I’ll fix it. We are not running shellcheck on the CI scripts and maybe we should :thinking:

(Bug filed)

Yep, Cairo 1.18.0 and Pixman 0.42.2. Thanks for your help!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.