fix(tiny_ttf): stream position and file read race condition (#9862)

This commit is contained in:
André Costa
2026-03-17 14:35:49 +01:00
committed by GitHub
parent 5435384d49
commit 1d6f92abdd
2 changed files with 34 additions and 22 deletions

View File

@@ -32,17 +32,20 @@
#define STBTT_STREAM_TYPE ttf_cb_stream_t *
#define STBTT_STREAM_SEEK(s, x) ttf_cb_stream_seek(s, x);
#define STBTT_STREAM_READ(s, x, y) ttf_cb_stream_read(s, x, y);
#define STBTT_STREAM_SEEK_AND_READ(s, o, x, y) ttf_cb_stream_seek_and_read(s,o, x, y);
/* a hydra stream that can be in memory or from a file*/
typedef struct ttf_cb_stream {
lv_fs_file_t * file;
const void * data;
lv_mutex_t mutex;
size_t size;
size_t position;
} ttf_cb_stream_t;
static void ttf_cb_stream_read(ttf_cb_stream_t * stream, void * data, size_t to_read);
static void ttf_cb_stream_seek(ttf_cb_stream_t * stream, size_t position);
static void ttf_cb_stream_seek_and_read(ttf_cb_stream_t * stream, size_t position, void * data, size_t to_read);
#endif
#include "stb_rect_pack.h"
@@ -188,9 +191,12 @@ void lv_tiny_ttf_destroy(lv_font_t * font)
if(font->dsc != NULL) {
ttf_font_desc_t * ttf = (ttf_font_desc_t *)font->dsc;
#if LV_TINY_TTF_FILE_SUPPORT != 0
lv_mutex_lock(&ttf->stream.mutex);
if(ttf->stream.file != NULL) {
lv_fs_close(&ttf->file);
}
lv_mutex_unlock(&ttf->stream.mutex);
lv_mutex_delete(&ttf->stream.mutex);
#endif
lv_cache_destroy(ttf->glyph_cache, NULL);
lv_cache_destroy(ttf->draw_data_cache, NULL);
@@ -235,6 +241,16 @@ static void ttf_cb_stream_seek(ttf_cb_stream_t * stream, size_t position)
}
}
}
static void ttf_cb_stream_seek_and_read(ttf_cb_stream_t * stream, size_t position, void * data, size_t to_read)
{
lv_mutex_lock(&stream->mutex);
ttf_cb_stream_seek(stream, position);
ttf_cb_stream_read(stream, data, to_read);
lv_mutex_unlock(&stream->mutex);
}
#endif
static inline uint16_t ttf_calculate_kerning_width(float scale, uint16_t adv_w, int k)
@@ -446,6 +462,7 @@ static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size
return NULL;
}
#if LV_TINY_TTF_FILE_SUPPORT != 0
lv_mutex_init(&dsc->stream.mutex);
if(path != NULL) {
if(LV_FS_RES_OK != lv_fs_open(&dsc->file, path, LV_FS_MODE_RD)) {
lv_free(dsc);

View File

@@ -450,6 +450,12 @@ typedef char stbtt__check_size16[sizeof(stbtt_int16) == 2 ? 1 : -1];
#define STBTT_STREAM_TYPE FILE*
#define STBTT_STREAM_READ(s,x,y) fread(x,1,y,s);
#define STBTT_STREAM_SEEK(s,x) fseek(s,x,SEEK_SET);
#define STBTT_STREAM_SEEK_AND_READ(s,o,x,y) (fseek(s,o,SEEK_SET), fread(x,1,y,s))
#endif
#ifndef STBTT_STREAM_SEEK_AND_READ
#define STBTT_STREAM_SEEK_AND_READ(s,o,x,y) \
do { STBTT_STREAM_SEEK(s,o); STBTT_STREAM_READ(s,x,y); } while(0)
#endif
// heap factor sizes for various counts of objects
@@ -1190,9 +1196,8 @@ static stbtt_uint8 stbtt__buf_get8(stbtt__buf * b)
return 0;
#ifdef STBTT_STREAM_TYPE
long pos = (long)(b->cursor + b->offset);
STBTT_STREAM_SEEK(b->data, pos);
stbtt_uint8 result;
STBTT_STREAM_READ(b->data, &result, 1);
STBTT_STREAM_SEEK_AND_READ(b->data, pos, &result, 1);
++b->cursor;
return result;
#else
@@ -1207,9 +1212,8 @@ static stbtt_uint8 stbtt__buf_peek8(stbtt__buf * b)
return 0;
#ifdef STBTT_STREAM_TYPE
long pos = (long)(b->cursor + b->offset);
STBTT_STREAM_SEEK(b->data, pos);
stbtt_uint8 result;
STBTT_STREAM_READ(b->data, &result, 1);
STBTT_STREAM_SEEK_AND_READ(b->data, pos, &result, 1);
return result;
#else
return b->data[b->cursor];
@@ -1370,38 +1374,33 @@ static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
#ifdef STBTT_STREAM_TYPE
static stbtt_uint8 ttBYTE(STBTT_STREAM_TYPE s, stbtt_uint32 offset)
{
STBTT_STREAM_SEEK(s, offset);
stbtt_uint8 r;
STBTT_STREAM_READ(s, &r, 1);
STBTT_STREAM_SEEK_AND_READ(s, offset, &r, 1);
return r;
}
#define ttCHAR(s, offset) ((stbtt_int8)ttBYTE(s,offset))
static stbtt_uint16 ttUSHORT(STBTT_STREAM_TYPE s, stbtt_uint32 offset)
{
STBTT_STREAM_SEEK(s, offset);
stbtt_uint8 r[2];
STBTT_STREAM_READ(s, &r, 2);
STBTT_STREAM_SEEK_AND_READ(s, offset, r, 2);
return r[0] * 256 + r[1];
}
static stbtt_int16 ttSHORT(STBTT_STREAM_TYPE s, stbtt_uint32 offset)
{
STBTT_STREAM_SEEK(s, offset);
stbtt_uint8 r[2];
STBTT_STREAM_READ(s, &r, 2);
STBTT_STREAM_SEEK_AND_READ(s, offset, r, 2);
return r[0] * 256 + r[1];
}
static stbtt_uint32 ttULONG(STBTT_STREAM_TYPE s, stbtt_uint32 offset)
{
STBTT_STREAM_SEEK(s, offset);
stbtt_uint8 r[4];
STBTT_STREAM_READ(s, &r, 4);
STBTT_STREAM_SEEK_AND_READ(s, offset, r, 4);
return (r[0] << 24) + (r[1] << 16) + (r[2] << 8) + r[3];
}
static stbtt_int32 ttLONG(STBTT_STREAM_TYPE s, stbtt_uint32 offset)
{
STBTT_STREAM_SEEK(s, offset);
stbtt_uint8 r[4];
STBTT_STREAM_READ(s, &r, 4);
STBTT_STREAM_SEEK_AND_READ(s, offset, r, 4);
return (r[0] << 24) + (r[1] << 16) + (r[2] << 8) + r[3];
}
#else
@@ -1436,8 +1435,7 @@ static stbtt_int32 ttLONG(const stbtt_uint8 * p, stbtt_uint32 offset)
{
#ifdef STBTT_STREAM_TYPE
stbtt_uint8 font[4];
STBTT_STREAM_SEEK(stream, offs);
STBTT_STREAM_READ(stream, font, 4);
STBTT_STREAM_SEEK_AND_READ(stream, offs, font, 4);
#else
font += offs;
#endif
@@ -1464,8 +1462,7 @@ static stbtt_int32 ttLONG(const stbtt_uint8 * p, stbtt_uint32 offset)
stbtt_uint32 loc = tabledir + 16 * i;
#ifdef STBTT_STREAM_TYPE
stbtt_uint8 buf[4];
STBTT_STREAM_SEEK(data, loc + 0);
STBTT_STREAM_READ(data, buf, 4);
STBTT_STREAM_SEEK_AND_READ(data, loc, buf, 4);
if(stbtt_tag(buf, tag))
return ttULONG(data, loc + 8);
#else
@@ -1488,8 +1485,7 @@ static stbtt_int32 ttLONG(const stbtt_uint8 * p, stbtt_uint32 offset)
// check if it's a TTC
#ifdef STBTT_STREAM_TYPE
stbtt_uint8 buf[4];
STBTT_STREAM_SEEK(font_collection, 0);
STBTT_STREAM_READ(font_collection, buf, 4);
STBTT_STREAM_SEEK_AND_READ(font_collection, 0, buf, 4);
if(stbtt_tag(buf, "ttcf")) {
#else
if(stbtt_tag(font_collection, "ttcf")) {
@@ -1517,8 +1513,7 @@ static stbtt_int32 ttLONG(const stbtt_uint8 * p, stbtt_uint32 offset)
// check if it's a TTC
#ifdef STBTT_STREAM_TYPE
stbtt_uint8 buf[4];
STBTT_STREAM_SEEK(font_collection, 0);
STBTT_STREAM_READ(font_collection, buf, 4);
STBTT_STREAM_SEEK_AND_READ(font_collection, 0, buf, 4);
if(stbtt_tag(buf, "ttcf")) {
#else
if(stbtt_tag(font_collection, "ttcf")) {