Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

heap-buffer-overflow in nsvgRasterize #253

Open
msxfXF opened this issue Jan 23, 2024 · 1 comment
Open

heap-buffer-overflow in nsvgRasterize #253

msxfXF opened this issue Jan 23, 2024 · 1 comment

Comments

@msxfXF
Copy link

msxfXF commented Jan 23, 2024

  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
@wcout
Copy link
Contributor

wcout commented Jan 27, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants