nanosvg icon indicating copy to clipboard operation
nanosvg copied to clipboard

heap-buffer-overflow in nsvgRasterize

Open msxfXF opened this issue 1 year ago • 1 comments

  1. 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;
}
  1. build nanosvg
clang example.c -g -fsanitize=address
  1. 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>
  1. run with args a.out crash.svg

  2. heap-buffer-overflow image

msxfXF avatar Jan 23 '24 15:01 msxfXF

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..

wcout avatar Jan 27 '24 14:01 wcout