heap-buffer-overflow in nsvgRasterize
- create example.c
#include <stdio.h>
#include <string.h>
#include <float.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
#define NANOSVG_IMPLEMENTATION
#include "nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvgrast.h"
int main(int argc, char* argv[])
{
NSVGimage *image = NULL;
NSVGrasterizer *rast = NULL;
NSVGshape* shape;
NSVGpath *path;
unsigned char* img = NULL;
int w, h;
if(argc<2){
return 0;
}
const char* filename = argv[1];
printf("parsing %s\n", filename);
image = nsvgParseFromFile(filename, "px", 96.0f);
if (image == NULL) {
printf("Could not open SVG image.\n");
goto error;
}
printf("size: %f x %f\n", image->width, image->height);
float res = 0;
for (shape = image->shapes; shape != NULL; shape = shape->next) {
for (path = shape->paths; path != NULL; path = path->next) {
for (int i = 0; i < path->npts-1; i += 3) {
float* p = &path->pts[i*2];
res = p[0] + p[1] +p[2] +p[3] +p[4] +p[5] +p[6] +p[7];
res = res / 8;
}
}
}
printf("res %f", res);
w = (int)image->width;
h = (int)image->height;
rast = nsvgCreateRasterizer();
if (rast == NULL) {
printf("Could not init rasterizer.\n");
goto error;
}
img = malloc(w*h*4);
if (img == NULL) {
printf("Could not alloc image buffer.\n");
goto error;
}
printf("rasterizing image %d x %d\n", w, h);
nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4);
printf("writing svg.png\n");
stbi_write_png("svg.png", w, h, 4, img, w*4);
error:
nsvgDeleteRasterizer(rast);
nsvgDelete(image);
return 0;
}
- build nanosvg
clang example.c -g -fsanitize=address
- create crash.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="02a32 32 0 1>< 384Hm License - https://fontawesome.com/license/free (Icons: CC BY 4.0, F0 onts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M64 64c0-17.7-14.3-32-32-32S0 46.3 0 64V448888888<feTi@e88ÿ88 32s32-14.3 32-32V64zm128 0c0-17.7-14.3-32-32-32s-32 14.3-32 32V448c0 17.7 14E3>32 32 32s32-14.3 32-32V64z"/></svg>
-
run with args
a.out crash.svg -
heap-buffer-overflow
This heap buffer overflow is a result of invalid memory allocation in the example program.
The (completely malformed) crash.svg creates an image with size 192 x 448888864.
The malloc(w*h*4) call does not detect an integer multiplication overflow (192*448888864*4 = 344746647552 bytes), resulting in much less memory (only 1149263872 bytes) allocated than needed, hence the buffer overflow later in nsvgRasterize() https://github.com/memononen/nanosvg/blob/93ce879dc4c04a3ef1758428ec80083c38610b1f/src/nanosvgrast.h#L1390().
Replacing the malloc() in the example program with:
size_t stride = w * 4;
image = calloc(h, stride);
will immediately result in an an error Could not alloc image buffer..