From eab5eb075df37ad7a8ed9af9aa7edf94b65582de Mon Sep 17 00:00:00 2001 From: kichikuou Date: Wed, 11 Dec 2024 16:30:42 +0900 Subject: [PATCH] Fix out-of-bounds memory access in text rendering This fixes SEGV in Hashiri Onna II when custom font is used. (#32) --- src/sys/ags.cpp | 11 ++++++++--- src/sys/ags_text.cpp | 5 +++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/sys/ags.cpp b/src/sys/ags.cpp index 1b3ca3b..276e7d8 100644 --- a/src/sys/ags.cpp +++ b/src/sys/ags.cpp @@ -520,10 +520,15 @@ void AGS::flush_screen(bool update) void AGS::draw_screen(int sx, int sy, int width, int height) { - for(int y = sy; y < (sy + height) && y < 480; y++) { + SDL_Rect rect = {sx, sy, width, height}; + SDL_Rect screen = {0, 0, screen_width, screen_height}; + SDL_Rect clip; + SDL_IntersectRect(&rect, &screen, &clip); + + for (int y = clip.y; y < clip.y + clip.h; y++) { uint32* src = vram[0][y]; uint32* dest = surface_line(hBmpDest, y); - for(int x = sx; x < (sx + width) && x < 640; x++) { + for(int x = clip.x; x < clip.x + clip.w; x++) { uint32 a=src[x]; if (game_id.sys_ver == 3 && src[x] & 0x80000000) { // あゆみちゃん物語 フルカラー実写版 @@ -533,7 +538,7 @@ void AGS::draw_screen(int sx, int sy, int width, int height) } } } - invalidate_screen(sx, sy, width, height); + invalidate_screen(clip.x, clip.y, clip.w, clip.h); } void AGS::invalidate_screen(int sx, int sy, int width, int height) diff --git a/src/sys/ags_text.cpp b/src/sys/ags_text.cpp index 2b47968..328cf78 100644 --- a/src/sys/ags_text.cpp +++ b/src/sys/ags_text.cpp @@ -4,6 +4,7 @@ [ AGS - text ] */ +#include #include #include "ags.h" #include "nact.h" @@ -440,7 +441,7 @@ void AGS::draw_char(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* fon SDL_Surface* fs = TTF_RenderGlyph_Solid(font, code, white); // パターン出力 - for(int y = 0; y < fs->h && dest_y + y < 480; y++) { + for (int y = std::max(0, -dest_y); y < fs->h && dest_y + y < 480; y++) { uint8 *pattern = (uint8*)surface_line(fs, y); // FIXME: do not assume 8bpp for(int x = 0; x < fs->w && dest_x + x < 640; x++) { if(pattern[x] != 0) { @@ -475,7 +476,7 @@ void AGS::draw_char_antialias(int dest, int dest_x, int dest_y, uint16 code, TTF SDL_Surface* fs = TTF_RenderGlyph_Shaded(font, code, white, black); // パターン出力 - for(int y = 0; y < fs->h && dest_y + y < 480; y++) { + for (int y = std::max(0, -dest_y); y < fs->h && dest_y + y < 480; y++) { uint8 *pattern = (uint8*)surface_line(fs, y); uint32 *dp = &vram[dest][dest_y + y][dest_x]; for(int x = 0; x < fs->w && dest_x + x < 640; x++, dp++) {