Skip to content

Commit 8367aba

Browse files
authored
[rtext] Fix GetCodepointNext() to return default value on invalid input with size=0 (#2997)
* Fix GetCodepointNext to return default value with size=0 on invalid input. Modify LoadCodepoints to work when GetCodepointNext returns a size of 0. All internal use of GetCodepointNext and GetCodepointPrev checked. This fix may break external code dealing with invalid input as the old code erroneously never returned a size of 0, external code that doesn't properly check for size=0 may endlessly loop or overflow a buffer on invalid input. * Change default behaviour of GetCodepointNext to return a size of 1 instead of 0. This matches existing prod behaviour and guarantees size 1..4 is returned. Simplify internal code that uses GetCodepointNext that previously had to account for size=0. * Simplified progressing through a UTF-8 string in ImageTextEx and MeasureTextEx. This change matches existing precedent in DrawTextEx * GetCodepointNext: Add 10xxxxxx checks to multibyte encodings. --------- Co-authored-by: anon <anon>
1 parent 17c443e commit 8367aba

File tree

2 files changed

+10
-19
lines changed

2 files changed

+10
-19
lines changed

src/rtext.c

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,10 +1071,6 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
10711071
int codepoint = GetCodepointNext(&text[i], &codepointByteCount);
10721072
int index = GetGlyphIndex(font, codepoint);
10731073

1074-
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
1075-
// but we need to draw all the bad bytes using the '?' symbol moving one byte
1076-
if (codepoint == 0x3f) codepointByteCount = 1;
1077-
10781074
if (codepoint == '\n')
10791075
{
10801076
// NOTE: Fixed line spacing of 1.5 line-height
@@ -1205,18 +1201,15 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
12051201
int letter = 0; // Current character
12061202
int index = 0; // Index position in sprite font
12071203

1208-
for (int i = 0; i < size; i++)
1204+
for (int i = 0; i < size;)
12091205
{
12101206
byteCounter++;
12111207

12121208
int next = 0;
12131209
letter = GetCodepointNext(&text[i], &next);
12141210
index = GetGlyphIndex(font, letter);
12151211

1216-
// NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
1217-
// but we need to draw all the bad bytes using the '?' symbol so to not skip any we set next = 1
1218-
if (letter == 0x3f) next = 1;
1219-
i += next - 1;
1212+
i += next;
12201213

12211214
if (letter != '\n')
12221215
{
@@ -1734,8 +1727,7 @@ int GetCodepointCount(const char *text)
17341727
int next = 0;
17351728
int letter = GetCodepointNext(ptr, &next);
17361729

1737-
if (letter == 0x3f) ptr += 1;
1738-
else ptr += next;
1730+
ptr += next;
17391731

17401732
length++;
17411733
}
@@ -1896,28 +1888,31 @@ int GetCodepointNext(const char *text, int *codepointSize)
18961888
{
18971889
const char *ptr = text;
18981890
int codepoint = 0x3f; // Codepoint (defaults to '?')
1899-
*codepointSize = 0;
1891+
*codepointSize = 1;
19001892

19011893
// Get current codepoint and bytes processed
19021894
if (0xf0 == (0xf8 & ptr[0]))
19031895
{
19041896
// 4 byte UTF-8 codepoint
1897+
if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
19051898
codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);
19061899
*codepointSize = 4;
19071900
}
19081901
else if (0xe0 == (0xf0 & ptr[0]))
19091902
{
19101903
// 3 byte UTF-8 codepoint */
1904+
if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
19111905
codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
19121906
*codepointSize = 3;
19131907
}
19141908
else if (0xc0 == (0xe0 & ptr[0]))
19151909
{
19161910
// 2 byte UTF-8 codepoint
1911+
if((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks
19171912
codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
19181913
*codepointSize = 2;
19191914
}
1920-
else
1915+
else if (0x00 == (0x80 & ptr[0]))
19211916
{
19221917
// 1 byte UTF-8 codepoint
19231918
codepoint = ptr[0];

src/rtextures.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,17 +1266,13 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
12661266
// Create image to store text
12671267
imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
12681268

1269-
for (int i = 0; i < size; i++)
1269+
for (int i = 0; i < size;)
12701270
{
12711271
// Get next codepoint from byte string and glyph index in font
12721272
int codepointByteCount = 0;
12731273
int codepoint = GetCodepointNext(&text[i], &codepointByteCount); // WARNING: Module required: rtext
12741274
int index = GetGlyphIndex(font, codepoint); // WARNING: Module required: rtext
12751275

1276-
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
1277-
// but we need to draw all the bad bytes using the '?' symbol moving one byte
1278-
if (codepoint == 0x3f) codepointByteCount = 1;
1279-
12801276
if (codepoint == '\n')
12811277
{
12821278
// NOTE: Fixed line spacing of 1.5 line-height
@@ -1296,7 +1292,7 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
12961292
else textOffsetX += font.glyphs[index].advanceX + (int)spacing;
12971293
}
12981294

1299-
i += (codepointByteCount - 1); // Move text bytes counter to next codepoint
1295+
i += codepointByteCount; // Move text bytes counter to next codepoint
13001296
}
13011297

13021298
// Scale image depending on text size

0 commit comments

Comments
 (0)