According to the C standard, pointer arithmetic on a NULL pointer is undefined behavior. LunaSVG can trigger this issue using valid SVG files. Clang's UB sanitiser confirms this. This could cause portability and security issues while changing compilers or compilation flags.
lunasvg/3rdparty/plutovg/plutovg-ft-stroker.c:656:47: runtime error: applying zero offset to null pointer
#0 0x788046 in ft_stroke_border_export lunasvg/3rdparty/plutovg/plutovg-ft-stroker.c:656:47
#1 0x786d57 in PVG_FT_Stroker_ExportBorder lunasvg/3rdparty/plutovg/plutovg-ft-stroker.c:1750:29
#2 0x788890 in PVG_FT_Stroker_Export lunasvg/3rdparty/plutovg/plutovg-ft-stroker.c:1758:5
#3 0x720bca in plutovg_rle_rasterize lunasvg/3rdparty/plutovg/plutovg-rle.c:243:9
#4 0x6d6065 in plutovg_stroke_preserve lunasvg/3rdparty/plutovg/plutovg.c:470:5
#5 0x6d5c24 in plutovg_stroke lunasvg/3rdparty/plutovg/plutovg.c:429:5
#6 0x638fa3 in lunasvg::Canvas::stroke(lunasvg::Path const&, lunasvg::Transform const&, double, lunasvg::LineCap, lunasvg::LineJoin, double, lunasvg::DashData const&, lunasvg::BlendMode, double) lunasvg/source/canvas.cpp:116:5
#7 0x5fa0c4 in lunasvg::StrokeData::stroke(lunasvg::RenderState&, lunasvg::Path const&) const lunasvg/source/layoutcontext.cpp:344:19
#8 0x5fc73b in lunasvg::LayoutShape::render(lunasvg::RenderState&) const lunasvg/source/layoutcontext.cpp:409:20
#9 0x5ed612 in lunasvg::LayoutContainer::renderChildren(lunasvg::RenderState&) const lunasvg/source/layoutcontext.cpp:88:16
#10 0x5f10b6 in lunasvg::LayoutSymbol::render(lunasvg::RenderState&) const lunasvg/source/layoutcontext.cpp:159:5
#11 0x50232e in lunasvg::Document::render(lunasvg::Bitmap, lunasvg::Matrix const&) const lunasvg/source/lunasvg.cpp:343:11
#12 0x503c1a in lunasvg::Document::renderToBitmap(unsigned int, unsigned int, unsigned int) const lunasvg/source/lunasvg.cpp:368:5
#13 0x4f44b3 in main lunasvg/example/svg2png.cpp:54:29
#14 0x7f3d8c7c4082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
#15 0x430bbd in _start (lunasvg/build/example/svg2png+0x430bbd)
Clone: git clone https://github.com/sammycage/lunasvg.git && cd lunasvg
Build with sanitisers: mkdir build && cd build && CXX=clang++ CC=clang cmake -DLUNASVG_BUILD_EXAMPLES=ON -DCMAKE_CXX_FLAGS="-g -O0 -fsanitize=undefined,address -fno-sanitize-recover=all" -DCMAKE_C_FLAGS="-g -O0 -fsanitize=undefined,address -fno-sanitize-recover=all" ../ && make -j4
Download SVGs (this is just for one): wget -O example.svg https://user-images.githubusercontent.com/3461126/225989850-39e47b2f-fb16-4163-a193-ff3ea2801c1b.svg
Run with sanitisers: UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 ASAN_OPTIONS=halt_on_error=1 ./example/svg2png example.svg
Fix
Add checks to prevent pointer arithmetic on NULL pointers.
Hi :wave:
Issue
According to the C standard, pointer arithmetic on a NULL pointer is undefined behavior. LunaSVG can trigger this issue using valid SVG files. Clang's UB sanitiser confirms this. This could cause portability and security issues while changing compilers or compilation flags.
Test Cases
Steps
git clone https://github.com/sammycage/lunasvg.git && cd lunasvg
mkdir build && cd build && CXX=clang++ CC=clang cmake -DLUNASVG_BUILD_EXAMPLES=ON -DCMAKE_CXX_FLAGS="-g -O0 -fsanitize=undefined,address -fno-sanitize-recover=all" -DCMAKE_C_FLAGS="-g -O0 -fsanitize=undefined,address -fno-sanitize-recover=all" ../ && make -j4
wget -O example.svg https://user-images.githubusercontent.com/3461126/225989850-39e47b2f-fb16-4163-a193-ff3ea2801c1b.svg
UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 ASAN_OPTIONS=halt_on_error=1 ./example/svg2png example.svg
Fix
Add checks to prevent pointer arithmetic on NULL pointers.