Skip to content

Commit 7100ff6

Browse files
committed
Interpret invalid glyphs as zero-width placeholder
As some variations of Path of Building let UTF-8 into strings there is the possibility of reading out of bounds in the array of glyphs for string measurement as characters larger than 128 are either after or before the array of glyphs. To satisfy the Unicode detection logic recently added to the Lua app this needs to either produce placeholder widths of zero or greater than 100. This implementation makes the conservative choice of zero width.
1 parent 9bdbbf2 commit 7100ff6

File tree

1 file changed

+28
-15
lines changed

1 file changed

+28
-15
lines changed

engine/render/r_font.cpp

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ struct f_fontHeight_s {
3232
int height;
3333
int numGlyph;
3434
f_glyph_s glyphs[128];
35+
f_glyph_s defGlyph{0.0, 0.0, 0.0, 0.0, 0, 0, 0};
36+
37+
f_glyph_s const& Glyph(char ch) const {
38+
if ((unsigned char)ch >= numGlyph) {
39+
return defGlyph;
40+
}
41+
return glyphs[(unsigned char)ch];
42+
}
3543
};
3644

3745
// ===========
@@ -126,11 +134,13 @@ int r_font_c::StringWidthInternal(f_fontHeight_s* fh, const char* str)
126134
if (escLen) {
127135
str+= escLen;
128136
} else if (*str == '\t') {
129-
int spWidth = fh->glyphs[' '].width + fh->glyphs[' '].spLeft + fh->glyphs[' '].spRight;
130-
width+= spWidth << 2;
137+
auto& glyph = fh->Glyph(' ');
138+
int spWidth = glyph.width + glyph.spLeft + glyph.spRight;
139+
width += spWidth << 2;
131140
str++;
132141
} else {
133-
width+= fh->glyphs[*str].width + fh->glyphs[*str].spLeft + fh->glyphs[*str].spRight;
142+
auto& glyph = fh->Glyph(*str);
143+
width+= glyph.width + glyph.spLeft + glyph.spRight;
134144
str++;
135145
}
136146
}
@@ -165,15 +175,17 @@ const char* r_font_c::StringCursorInternal(f_fontHeight_s* fh, const char* str,
165175
if (escLen) {
166176
str+= escLen;
167177
} else if (*str == '\t') {
168-
int spWidth = fh->glyphs[' '].width + fh->glyphs[' '].spLeft + fh->glyphs[' '].spRight;
178+
auto& glyph = fh->Glyph(' ');
179+
int spWidth = glyph.width + glyph.spLeft + glyph.spRight;
169180
x+= spWidth << 1;
170181
if (curX <= x) {
171182
break;
172183
}
173184
x+= spWidth << 1;
174185
str++;
175186
} else {
176-
x+= fh->glyphs[*str].width + fh->glyphs[*str].spLeft + fh->glyphs[*str].spRight;
187+
auto& glyph = fh->Glyph(*str);
188+
x+= glyph.width + glyph.spLeft + glyph.spRight;
177189
if (curX <= x) {
178190
break;
179191
}
@@ -274,28 +286,29 @@ void r_font_c::DrawTextLine(scp_t pos, int align, int height, col4_t col, const
274286

275287
// Handle tabs
276288
if (*str == '\t') {
277-
int spWidth = fh->glyphs[' '].width + fh->glyphs[' '].spLeft + fh->glyphs[' '].spRight;
289+
auto& glyph = fh->Glyph(' ');
290+
int spWidth = glyph.width + glyph.spLeft + glyph.spRight;
278291
x+= (spWidth << 2) * scale;
279292
str++;
280293
continue;
281294
}
282295

283296
// Draw glyph
284-
f_glyph_s* glyph = fh->glyphs + *(str++);
285-
x+= glyph->spLeft * scale;
286-
if (glyph->width) {
287-
double w = glyph->width * scale;
297+
auto& glyph = fh->Glyph(*str++);
298+
x+= glyph.spLeft * scale;
299+
if (glyph.width) {
300+
double w = glyph.width * scale;
288301
if (x + w >= 0 && x < renderer->VirtualScreenWidth()) {
289302
renderer->curLayer->Quad(
290-
glyph->tcLeft, glyph->tcTop, x, y,
291-
glyph->tcRight, glyph->tcTop, x + w, y,
292-
glyph->tcRight, glyph->tcBottom, x + w, y + height,
293-
glyph->tcLeft, glyph->tcBottom, x, y + height
303+
glyph.tcLeft, glyph.tcTop, x, y,
304+
glyph.tcRight, glyph.tcTop, x + w, y,
305+
glyph.tcRight, glyph.tcBottom, x + w, y + height,
306+
glyph.tcLeft, glyph.tcBottom, x, y + height
294307
);
295308
}
296309
x+= w;
297310
}
298-
x+= glyph->spRight * scale;
311+
x+= glyph.spRight * scale;
299312
}
300313
}
301314

0 commit comments

Comments
 (0)