2
0
Эх сурвалжийг харах

[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>
chocolate42 2 жил өмнө
parent
commit
8367abad1a
2 өөрчлөгдсөн 10 нэмэгдсэн , 19 устгасан
  1. 8 13
      src/rtext.c
  2. 2 6
      src/rtextures.c

+ 8 - 13
src/rtext.c

@@ -1071,10 +1071,6 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
         int codepoint = GetCodepointNext(&text[i], &codepointByteCount);
         int index = GetGlyphIndex(font, codepoint);
 
-        // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
-        // but we need to draw all the bad bytes using the '?' symbol moving one byte
-        if (codepoint == 0x3f) codepointByteCount = 1;
-
         if (codepoint == '\n')
         {
             // NOTE: Fixed line spacing of 1.5 line-height
@@ -1205,7 +1201,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
     int letter = 0;                 // Current character
     int index = 0;                  // Index position in sprite font
 
-    for (int i = 0; i < size; i++)
+    for (int i = 0; i < size;)
     {
         byteCounter++;
 
@@ -1213,10 +1209,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
         letter = GetCodepointNext(&text[i], &next);
         index = GetGlyphIndex(font, letter);
 
-        // NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
-        // but we need to draw all the bad bytes using the '?' symbol so to not skip any we set next = 1
-        if (letter == 0x3f) next = 1;
-        i += next - 1;
+        i += next;
 
         if (letter != '\n')
         {
@@ -1734,8 +1727,7 @@ int GetCodepointCount(const char *text)
         int next = 0;
         int letter = GetCodepointNext(ptr, &next);
 
-        if (letter == 0x3f) ptr += 1;
-        else ptr += next;
+        ptr += next;
 
         length++;
     }
@@ -1896,28 +1888,31 @@ int GetCodepointNext(const char *text, int *codepointSize)
 {
     const char *ptr = text;
     int codepoint = 0x3f;       // Codepoint (defaults to '?')
-    *codepointSize = 0;
+    *codepointSize = 1;
 
     // Get current codepoint and bytes processed
     if (0xf0 == (0xf8 & ptr[0]))
     {
         // 4 byte UTF-8 codepoint
+        if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
         codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);
         *codepointSize = 4;
     }
     else if (0xe0 == (0xf0 & ptr[0]))
     {
         // 3 byte UTF-8 codepoint */
+        if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
         codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
         *codepointSize = 3;
     }
     else if (0xc0 == (0xe0 & ptr[0]))
     {
         // 2 byte UTF-8 codepoint
+        if((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks
         codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
         *codepointSize = 2;
     }
-    else
+    else if (0x00 == (0x80 & ptr[0]))
     {
         // 1 byte UTF-8 codepoint
         codepoint = ptr[0];

+ 2 - 6
src/rtextures.c

@@ -1266,17 +1266,13 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
     // Create image to store text
     imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
 
-    for (int i = 0; i < size; i++)
+    for (int i = 0; i < size;)
     {
         // Get next codepoint from byte string and glyph index in font
         int codepointByteCount = 0;
         int codepoint = GetCodepointNext(&text[i], &codepointByteCount);    // WARNING: Module required: rtext
         int index = GetGlyphIndex(font, codepoint);                         // WARNING: Module required: rtext
 
-        // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
-        // but we need to draw all the bad bytes using the '?' symbol moving one byte
-        if (codepoint == 0x3f) codepointByteCount = 1;
-
         if (codepoint == '\n')
         {
             // 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
             else textOffsetX += font.glyphs[index].advanceX + (int)spacing;
         }
 
-        i += (codepointByteCount - 1);   // Move text bytes counter to next codepoint
+        i += codepointByteCount;   // Move text bytes counter to next codepoint
     }
 
     // Scale image depending on text size