Skip to content

Commit

Permalink
Merge pull request #412 from a740g/main
Browse files Browse the repository at this point in the history
Avoid segfault on bogus SVG data
  • Loading branch information
a740g authored Dec 13, 2023
2 parents f3fb398 + 71b5ddd commit f8576b2
Show file tree
Hide file tree
Showing 8 changed files with 1,547 additions and 9 deletions.
55 changes: 50 additions & 5 deletions internal/c/parts/video/image/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
// We need 'qbs' and 'image' structs stuff from here
// This should eventually change when things are moved to smaller, logical and self-contained files
#include "../../../libqb.h"
#include "filepath.h"
#include <cctype>
#include <string>
#include <unordered_map>
#include <vector>
Expand Down Expand Up @@ -178,11 +180,48 @@ static uint32_t *image_svg_load(NSVGimage *image, int32_t *xOut, int32_t *yOut,
/// @param isVG Out: vector graphics? Always set to true
/// @return A pointer to the raw pixel data in RGBA format or NULL on failure
static uint32_t *image_svg_load_from_file(const char *fileName, int32_t *xOut, int32_t *yOut, ImageScaler scaler, int *components, bool *isVG) {
auto image = nsvgParseFromFile(fileName, "px", 96.0f);
if (!image)
if (!filepath_has_extension(fileName, "svg"))
return nullptr;

return image_svg_load(image, xOut, yOut, scaler, components, isVG);
auto fp = fopen(fileName, "rb");
if (!fp)
return nullptr;

fseek(fp, 0, SEEK_END);
auto size = ftell(fp);
fseek(fp, 0, SEEK_SET);

auto svgString = (char *)malloc(size + 1);
if (!svgString) {
fclose(fp);
return nullptr;
}

if (fread(svgString, 1, size, fp) != size) {
free(svgString);
fclose(fp);
return nullptr;
}
svgString[size] = '\0'; // must be null terminated

fclose(fp);

// Check if it has a valid SVG start tag
if (!strstr(svgString, "<svg")) {
free(svgString);
return nullptr;
}

auto image = nsvgParse(svgString, "px", 96.0f); // important note: changes the string
if (!image) {
free(svgString);
return nullptr;
}

auto pixels = image_svg_load(image, xOut, yOut, scaler, components, isVG); // this is where everything else is freed
free(svgString);

return pixels;
}

/// @brief Loads an SVG image file from memory
Expand All @@ -200,15 +239,21 @@ static uint32_t *image_svg_load_from_memory(const uint8_t *buffer, size_t size,
return nullptr;

memcpy(svgString, buffer, size);
svgString[size] = '\0';
svgString[size] = '\0'; // must be null terminated

// Check if it has a valid SVG start tag
if (!strstr(svgString, "<svg")) {
free(svgString);
return nullptr;
}

auto image = nsvgParse(svgString, "px", 96.0f); // important note: changes the string
if (!image) {
free(svgString);
return nullptr;
}

auto pixels = image_svg_load(image, xOut, yOut, scaler, components, isVG);
auto pixels = image_svg_load(image, xOut, yOut, scaler, components, isVG); // this is where everything else is freed
free(svgString);

return pixels;
Expand Down
9 changes: 5 additions & 4 deletions internal/c/parts/video/image/nanosvg/nanosvgrast.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ static float nsvg__normalize(float *x, float* y)
}

static float nsvg__absf(float x) { return x < 0 ? -x : x; }
static float nsvg__roundf(float x) { return (x >= 0) ? floorf(x + 0.5) : ceilf(x - 0.5); }

static void nsvg__flattenCubicBez(NSVGrasterizer* r,
float x1, float y1, float x2, float y2,
Expand Down Expand Up @@ -872,10 +873,10 @@ static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float sta
// STBTT_assert(e->y0 <= start_point);
// round dx down to avoid going too far
if (dxdy < 0)
z->dx = (int)(-floorf(NSVG__FIX * -dxdy));
z->dx = (int)(-nsvg__roundf(NSVG__FIX * -dxdy));
else
z->dx = (int)floorf(NSVG__FIX * dxdy);
z->x = (int)floorf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0)));
z->dx = (int)nsvg__roundf(NSVG__FIX * dxdy);
z->x = (int)nsvg__roundf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0)));
// z->x -= off_x * FIX;
z->ey = e->y1;
z->next = 0;
Expand Down Expand Up @@ -1282,7 +1283,7 @@ static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opac
if (grad->nstops == 0) {
for (i = 0; i < 256; i++)
cache->colors[i] = 0;
} if (grad->nstops == 1) {
} else if (grad->nstops == 1) {
for (i = 0; i < 256; i++)
cache->colors[i] = nsvg__applyOpacity(grad->stops[i].color, opacity);
} else {
Expand Down
1 change: 1 addition & 0 deletions tests/compile_tests/image/bogus1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/compile_tests/image/bogus2.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit f8576b2

Please sign in to comment.