From c29b1c2cb9b50f11cfe3b3bd6a9d59ff0fd8488d Mon Sep 17 00:00:00 2001 From: Guldoman Date: Mon, 26 Dec 2022 18:49:07 +0100 Subject: [PATCH] Use Lua string length instead of relying on `strlen` (#1262) This allows us to render `NULL` byte sequences and not truncate strings that contain them. --- src/api/renderer.c | 10 +++++++--- src/rencache.c | 10 ++++++---- src/rencache.h | 2 +- src/renderer.c | 8 ++++---- src/renderer.h | 4 ++-- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/api/renderer.c b/src/api/renderer.c index 9e69dffb..261fc26a 100644 --- a/src/api/renderer.c +++ b/src/api/renderer.c @@ -193,7 +193,10 @@ static int f_font_gc(lua_State *L) { static int f_font_get_width(lua_State *L) { RenFont* fonts[FONT_FALLBACK_MAX]; font_retrieve(L, fonts, 1); - lua_pushnumber(L, ren_font_group_get_width(fonts, luaL_checkstring(L, 2))); + size_t len; + const char *text = luaL_checklstring(L, 2, &len); + + lua_pushnumber(L, ren_font_group_get_width(fonts, text, len)); return 1; } @@ -338,11 +341,12 @@ static int f_draw_text(lua_State *L) { } lua_pop(L, 1); - const char *text = luaL_checkstring(L, 2); + size_t len; + const char *text = luaL_checklstring(L, 2, &len); float x = luaL_checknumber(L, 3); int y = luaL_checknumber(L, 4); RenColor color = checkcolor(L, 5, 255); - x = rencache_draw_text(fonts, text, x, y, color); + x = rencache_draw_text(fonts, text, len, x, y, color); lua_pushnumber(L, x); return 1; } diff --git a/src/rencache.c b/src/rencache.c index aa882617..c9b1885a 100644 --- a/src/rencache.c +++ b/src/rencache.c @@ -39,6 +39,7 @@ typedef struct { RenColor color; RenFont *fonts[FONT_FALLBACK_MAX]; float text_x; + size_t len; char text[]; } Command; @@ -145,12 +146,12 @@ void rencache_draw_rect(RenRect rect, RenColor color) { } } -float rencache_draw_text(RenFont **fonts, const char *text, float x, int y, RenColor color) +float rencache_draw_text(RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { - float width = ren_font_group_get_width(fonts, text); + float width = ren_font_group_get_width(fonts, text, len); RenRect rect = { x, y, (int)width, ren_font_group_get_height(fonts) }; if (rects_overlap(screen_rect, rect)) { - int sz = strlen(text) + 1; + int sz = len + 1; Command *cmd = push_command(DRAW_TEXT, COMMAND_BARE_SIZE + sz); if (cmd) { memcpy(cmd->text, text, sz); @@ -158,6 +159,7 @@ float rencache_draw_text(RenFont **fonts, const char *text, float x, int y, RenC memcpy(cmd->fonts, fonts, sizeof(RenFont*)*FONT_FALLBACK_MAX); cmd->rect = rect; cmd->text_x = x; + cmd->len = len; cmd->tab_size = ren_font_group_get_tab_size(fonts); } } @@ -266,7 +268,7 @@ void rencache_end_frame() { break; case DRAW_TEXT: ren_font_group_set_tab_size(cmd->fonts, cmd->tab_size); - ren_draw_text(cmd->fonts, cmd->text, cmd->text_x, cmd->rect.y, cmd->color); + ren_draw_text(cmd->fonts, cmd->text, cmd->len, cmd->text_x, cmd->rect.y, cmd->color); break; } } diff --git a/src/rencache.h b/src/rencache.h index fedbada6..49ca9135 100644 --- a/src/rencache.h +++ b/src/rencache.h @@ -8,7 +8,7 @@ void rencache_show_debug(bool enable); void rencache_set_clip_rect(RenRect rect); void rencache_draw_rect(RenRect rect, RenColor color); -float rencache_draw_text(RenFont **font, const char *text, float x, int y, RenColor color); +float rencache_draw_text(RenFont **font, const char *text, size_t len, float x, int y, RenColor color); void rencache_invalidate(void); void rencache_begin_frame(); void rencache_end_frame(); diff --git a/src/renderer.c b/src/renderer.c index 710df92a..c93569ce 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -358,9 +358,9 @@ int ren_font_group_get_height(RenFont **fonts) { return fonts[0]->height; } -float ren_font_group_get_width(RenFont **fonts, const char *text) { +float ren_font_group_get_width(RenFont **fonts, const char *text, size_t len) { float width = 0; - const char* end = text + strlen(text); + const char* end = text + len; GlyphMetric* metric = NULL; GlyphSet* set = NULL; while (text < end) { unsigned int codepoint; @@ -374,7 +374,7 @@ float ren_font_group_get_width(RenFont **fonts, const char *text) { return width / surface_scale; } -float ren_draw_text(RenFont **fonts, const char *text, float x, int y, RenColor color) { +float ren_draw_text(RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { SDL_Surface *surface = renwin_get_surface(&window_renderer); const RenRect clip = window_renderer.clip; @@ -382,7 +382,7 @@ float ren_draw_text(RenFont **fonts, const char *text, float x, int y, RenColor float pen_x = x * surface_scale; y *= surface_scale; int bytes_per_pixel = surface->format->BytesPerPixel; - const char* end = text + strlen(text); + const char* end = text + len; uint8_t* destination_pixels = surface->pixels; int clip_end_x = clip.x + clip.width, clip_end_y = clip.y + clip.height; diff --git a/src/renderer.h b/src/renderer.h index 6cae1e6f..c1b80f51 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -28,8 +28,8 @@ int ren_font_group_get_height(RenFont **font); float ren_font_group_get_size(RenFont **font); void ren_font_group_set_size(RenFont **font, float size); void ren_font_group_set_tab_size(RenFont **font, int n); -float ren_font_group_get_width(RenFont **font, const char *text); -float ren_draw_text(RenFont **font, const char *text, float x, int y, RenColor color); +float ren_font_group_get_width(RenFont **font, const char *text, size_t len); +float ren_draw_text(RenFont **font, const char *text, size_t len, float x, int y, RenColor color); void ren_draw_rect(RenRect rect, RenColor color);