Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions modules/svg/svg_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ void SVGUtils::add_font_face(const String &family, const void *font_data, int le

{
MutexLock lock(svg_font_registry_mutex);
if (svg_named_font_faces.has(family)) {
return;
}
svg_named_font_faces.insert(family, font_bytes);
svg_font_registry_serial++;
}
Expand Down
12 changes: 12 additions & 0 deletions thirdparty/lunasvg/include/plutovg.h
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,18 @@ PLUTOVG_API void plutovg_font_face_get_metrics(const plutovg_font_face_t* face,
*/
PLUTOVG_API void plutovg_font_face_get_glyph_metrics(plutovg_font_face_t* face, float size, plutovg_codepoint_t codepoint, float* advance_width, float* left_side_bearing, plutovg_rect_t* extents);

/**
* @brief Retrieves embedded SVG glyph data for a specified codepoint when available.
*
* @param face A pointer to a `plutovg_font_face_t` object.
* @param codepoint The Unicode code point of the glyph.
* @param svg Pointer that receives the embedded SVG document owned by the font face.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing lifetime constraint in API doc: The @param svg line says "owned by the font face" but the pointer is actually an interior pointer into the raw font binary (returned by stbtt_GetGlyphSVG). Callers must not free it, must not modify it, and it becomes invalid once face is destroyed. The current wording does not convey the raw-interior-pointer nature. Suggested addition:

The pointer points directly into the font face's internal data and is valid only for the lifetime of face. The caller must not free or modify it.

* The returned pointer refers to the font face's internal storage, remains valid only for the
* lifetime of `face`, and must not be modified or freed by the caller.
* @return The SVG document length in bytes, or 0 if no embedded SVG glyph exists.
*/
PLUTOVG_API int plutovg_font_face_get_glyph_svg(plutovg_font_face_t* face, plutovg_codepoint_t codepoint, const char** svg);

/**
* @brief Retrieves the path of a glyph and its advance width.
*
Expand Down
25 changes: 25 additions & 0 deletions thirdparty/lunasvg/source/plutovg-font.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,11 +256,15 @@ static glyph_t* plutovg_font_face_get_glyph(plutovg_font_face_t* face, plutovg_c
unsigned int msb = (codepoint >> 8) & 0xFF;
if(face->glyphs[msb] == NULL) {
face->glyphs[msb] = calloc(GLYPH_CACHE_SIZE, sizeof(glyph_t*));
if(face->glyphs[msb] == NULL)
return NULL;
}

unsigned int lsb = codepoint & 0xFF;
if(face->glyphs[msb][lsb] == NULL) {
glyph_t* glyph = malloc(sizeof(glyph_t));
if(glyph == NULL)
return NULL;
glyph->index = stbtt_FindGlyphIndex(&face->info, codepoint);
glyph->nvertices = stbtt_GetGlyphShape(&face->info, glyph->index, &glyph->vertices);
stbtt_GetGlyphHMetrics(&face->info, glyph->index, &glyph->advance_width, &glyph->left_side_bearing);
Expand All @@ -276,6 +280,13 @@ void plutovg_font_face_get_glyph_metrics(plutovg_font_face_t* face, float size,
{
float scale = plutovg_font_face_get_scale(face, size);
glyph_t* glyph = plutovg_font_face_get_glyph(face, codepoint);
if(glyph == NULL) {
if(advance_width) *advance_width = 0.f;
if(left_side_bearing) *left_side_bearing = 0.f;
if(extents)
extents->x = extents->y = extents->w = extents->h = 0.f;
return;
}
if(advance_width) *advance_width = glyph->advance_width * scale;
if(left_side_bearing) *left_side_bearing = glyph->left_side_bearing * scale;
if(extents) {
Expand All @@ -286,6 +297,18 @@ void plutovg_font_face_get_glyph_metrics(plutovg_font_face_t* face, float size,
}
}

int plutovg_font_face_get_glyph_svg(plutovg_font_face_t* face, plutovg_codepoint_t codepoint, const char** svg)
{
if(svg)
*svg = NULL;
if(face == NULL || svg == NULL)
return 0;
glyph_t* glyph = plutovg_font_face_get_glyph(face, codepoint);
if(glyph == NULL)
return 0;
return stbtt_GetGlyphSVG(&face->info, glyph->index, svg);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Null pointer dereference: plutovg_font_face_get_glyph can return NULL if malloc or calloc fails inside the cache-fill path. glyph->index is then dereferenced unconditionally, causing a crash. The existing plutovg_font_face_get_glyph_metrics callers share this pattern (pre-existing), but adding a new public API is a good opportunity to fix it:

glyph_t* glyph = plutovg_font_face_get_glyph(face, codepoint);
if(glyph == NULL)
    return 0;
return stbtt_GetGlyphSVG(&face->info, glyph->index, svg);

}
Comment on lines +300 to +310

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If plutovg_font_face_get_glyph returns NULL (e.g., when the codepoint is not supported by the font face), dereferencing glyph->index will cause a null pointer dereference and crash the application. A null check should be added for glyph.

int plutovg_font_face_get_glyph_svg(plutovg_font_face_t* face, plutovg_codepoint_t codepoint, const char** svg)
{
    if(svg)
        *svg = NULL;
    if(face == NULL || svg == NULL)
        return 0;
    glyph_t* glyph = plutovg_font_face_get_glyph(face, codepoint);
    if(glyph == NULL)
        return 0;
    return stbtt_GetGlyphSVG(&face->info, glyph->index, svg);
}


static void glyph_traverse_func(void* closure, plutovg_path_command_t command, const plutovg_point_t* points, int npoints)
{
plutovg_path_t* path = (plutovg_path_t*)(closure);
Expand Down Expand Up @@ -319,6 +342,8 @@ float plutovg_font_face_traverse_glyph_path(plutovg_font_face_t* face, float siz
plutovg_point_t points[3];
plutovg_point_t current_point = {0, 0};
glyph_t* glyph = plutovg_font_face_get_glyph(face, codepoint);
if(glyph == NULL)
return 0.f;
for(int i = 0; i < glyph->nvertices; i++) {
switch(glyph->vertices[i].type) {
case STBTT_vmove:
Expand Down
Loading
Loading