From 1d6f92abdd8d92500533b56392fe0e9ba42d54cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Costa?= Date: Tue, 17 Mar 2026 14:35:49 +0100 Subject: [PATCH] fix(tiny_ttf): stream position and file read race condition (#9862) --- src/libs/tiny_ttf/lv_tiny_ttf.c | 17 ++++++++++++ src/libs/tiny_ttf/stb_truetype_htcw.h | 39 ++++++++++++--------------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/libs/tiny_ttf/lv_tiny_ttf.c b/src/libs/tiny_ttf/lv_tiny_ttf.c index 09f1e87622..8c72a3517f 100644 --- a/src/libs/tiny_ttf/lv_tiny_ttf.c +++ b/src/libs/tiny_ttf/lv_tiny_ttf.c @@ -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); diff --git a/src/libs/tiny_ttf/stb_truetype_htcw.h b/src/libs/tiny_ttf/stb_truetype_htcw.h index d2dc388be0..8017ca38cd 100644 --- a/src/libs/tiny_ttf/stb_truetype_htcw.h +++ b/src/libs/tiny_ttf/stb_truetype_htcw.h @@ -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")) {