]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
make utf8 functions safer: give them a size limit in memory, to allow working with...
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 23 Dec 2009 12:15:47 +0000 (12:15 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 23 Dec 2009 12:15:47 +0000 (12:15 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9646 d7cf8633-e32d-0410-b094-e92efae38249

console.c
gl_draw.c
utf8lib.c
utf8lib.h

index 4d279b96c8406f71a14035f73f6415a611ff9d9e..6a59b970f4a1d72c830cd4017343ac7fc5ee1276 100644 (file)
--- a/console.c
+++ b/console.c
@@ -1464,7 +1464,7 @@ int Con_DisplayLineFunc(void *passthrough, const char *line, size_t length, floa
                if(isContinuation && *ti->continuationString)
                        x += (int) DrawQ_String_Font(x, ti->y, ti->continuationString, strlen(ti->continuationString), ti->fontsize, ti->fontsize, 1.0, 1.0, 1.0, 1.0, 0, NULL, false, ti->font);
                if(length > 0)
-                       DrawQ_String_Font(x, ti->y, line, u8_strnlen(line, length), ti->fontsize, ti->fontsize, 1.0, 1.0, 1.0, 1.0, 0, &(ti->colorindex), false, ti->font);
+                       DrawQ_String_Font(x, ti->y, line, length, ti->fontsize, ti->fontsize, 1.0, 1.0, 1.0, 1.0, 0, &(ti->colorindex), false, ti->font);
        }
 
        ti->y += ti->fontsize;
index 66b2b89ecea1454bd23908fc060ab39f644e7309..7f33797de48a4490897a4bc8d607332db0c6c493 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -1075,6 +1075,7 @@ static void DrawQ_GetTextColor(float color[4], int colorindex, float r, float g,
 
 float DrawQ_TextWidth_Font_UntilWidth_TrackColors_Size(const char *text, float w, float h, size_t *maxlen, int *outcolor, qboolean ignorecolorcodes, const dp_font_t *fnt, float maxwidth)
 {
+       const char *text_start = text;
        int colorindex = STRING_COLOR_DEFAULT;
        size_t i;
        float x = 0;
@@ -1083,6 +1084,7 @@ float DrawQ_TextWidth_Font_UntilWidth_TrackColors_Size(const char *text, float w
        int tempcolorindex;
        float kx;
        int map_index = 0;
+       size_t bytes_left;
        ft2_font_map_t *fontmap = NULL;
        ft2_font_map_t *map = NULL;
        ft2_font_map_t *prevmap = NULL;
@@ -1120,9 +1122,9 @@ float DrawQ_TextWidth_Font_UntilWidth_TrackColors_Size(const char *text, float w
        // maxwidth /= fnt->scale; // w and h are multiplied by it already
        // ftbase_x = snap_to_pixel_x(0);
 
-       for (i = 0;i < *maxlen && *text;)
+       for (i = 0;((bytes_left = *maxlen - (text - text_start)) > 0) && *text;)
        {
-               nextch = ch = u8_getchar(text, &text);
+               nextch = ch = u8_getnchar(text, &text, bytes_left);
                //i = text - text_start;
                if (!ch)
                        break;
@@ -1253,6 +1255,7 @@ float DrawQ_String_Font(float startx, float starty, const char *text, size_t max
        ft2_font_t *ft2 = fnt->ft2;
        qboolean snap = true;
        float pix_x, pix_y;
+       size_t bytes_left;
 
        int tw, th;
        tw = R_TextureWidth(fnt->tex);
@@ -1324,9 +1327,9 @@ float DrawQ_String_Font(float startx, float starty, const char *text, size_t max
                        y += r_textshadow.value * vid.height / vid_conheight.value;
                }
                */
-               for (i = 0;i < maxlen && *text;)
+               for (i = 0;((bytes_left = maxlen - (text - text_start)) > 0) && *text;)
                {
-                       nextch = ch = u8_getchar(text, &text);
+                       nextch = ch = u8_getnchar(text, &text, bytes_left);
                        //i = text - text_start;
                        if (!ch)
                                break;
index 8b50e753d4cf3a57e873416079b63f4866caf0b8..bc3ce39a615c3558f1470590c6b4be43d31e5063 100644 (file)
--- a/utf8lib.c
+++ b/utf8lib.c
@@ -25,9 +25,11 @@ UTF-8 encoding and decoding functions follow.
  * @param _start  Filled with the start byte-offset of the next valid character
  * @param _len    Fileed with the length of the next valid character
  * @param _ch     Filled with the unicode value of the next character
+ * @param _maxlen Maximum number of bytes to read from _s
  * @return        Whether or not another valid character is in the string
  */
-static qboolean u8_analyze(const char *_s, size_t *_start, size_t *_len, Uchar *_ch)
+#define U8_ANALYZE_INFINITY 7
+static qboolean u8_analyze(const char *_s, size_t *_start, size_t *_len, Uchar *_ch, size_t _maxlen)
 {
        const unsigned char *s = (const unsigned char*)_s;
        unsigned char bt, bc;
@@ -39,10 +41,12 @@ static qboolean u8_analyze(const char *_s, size_t *_start, size_t *_len, Uchar *
 findchar:
 
        // <0xC2 is always an overlong encoding, they're invalid, thus skipped
-       while (s[i] && s[i] >= 0x80 && s[i] <= 0xC2) {
+       while (i < _maxlen && s[i] && s[i] >= 0x80 && s[i] <= 0xC2) {
                //fprintf(stderr, "skipping\n");
                ++i;
        }
+       if(i >= _maxlen)
+               return false;
        //fprintf(stderr, "checking\n");
 
        // If we hit the end, well, we're out and invalid
@@ -72,6 +76,8 @@ findchar:
                ++i;
                goto findchar;
        }
+       if(i + bits > _maxlen)
+               return false;
        // turn bt into a mask and give ch a starting value
        --bt;
        ch = (s[i] & bt);
@@ -144,7 +150,7 @@ size_t u8_strlen(const char *_s)
                        continue;
                }
 
-               if (!u8_analyze((const char*)s, &st, &ln, NULL))
+               if (!u8_analyze((const char*)s, &st, &ln, NULL, U8_ANALYZE_INFINITY))
                        break;
                // valid character, skip after it
                s += st + ln;
@@ -189,7 +195,7 @@ size_t u8_strnlen(const char *_s, size_t n)
                        continue;
                }
 
-               if (!u8_analyze((const char*)s, &st, &ln, NULL))
+               if (!u8_analyze((const char*)s, &st, &ln, NULL, n))
                        break;
                // valid character, see if it's still inside the range specified by n:
                if (n < st + ln)
@@ -234,7 +240,7 @@ size_t u8_bytelen(const char *_s, size_t n)
                        continue;
                }
 
-               if (!u8_analyze((const char*)s, &st, &ln, NULL))
+               if (!u8_analyze((const char*)s, &st, &ln, NULL, U8_ANALYZE_INFINITY))
                        break;
                --n;
                s += st + ln;
@@ -265,7 +271,7 @@ int u8_byteofs(const char *_s, size_t i, size_t *len)
        do
        {
                ofs += ln;
-               if (!u8_analyze((const char*)s + ofs, &st, &ln, NULL))
+               if (!u8_analyze((const char*)s + ofs, &st, &ln, NULL, U8_ANALYZE_INFINITY))
                        return -1;
                ofs += st;
        } while(i-- > 0);
@@ -312,7 +318,7 @@ int u8_charidx(const char *_s, size_t i, size_t *len)
                        continue;
                }
 
-               if (!u8_analyze((const char*)s+ofs, &st, &ln, NULL))
+               if (!u8_analyze((const char*)s+ofs, &st, &ln, NULL, U8_ANALYZE_INFINITY))
                        return -1;
                // see if next char is after the bytemark
                if (ofs + st > i)
@@ -373,7 +379,7 @@ size_t u8_prevbyte(const char *_s, size_t i)
                        continue;
                }
 
-               if (!u8_analyze((const char*)s+ofs, &st, &ln, NULL))
+               if (!u8_analyze((const char*)s+ofs, &st, &ln, NULL, U8_ANALYZE_INFINITY))
                        return lastofs;
                if (ofs + st > i)
                        return lastofs;
@@ -429,7 +435,37 @@ Uchar u8_getchar(const char *_s, const char **_end)
                return (Uchar)*(const unsigned char*)_s;
        }
        
-       if (!u8_analyze(_s, &st, &ln, &ch))
+       if (!u8_analyze(_s, &st, &ln, &ch, U8_ANALYZE_INFINITY))
+               return 0;
+       if (_end)
+               *_end = _s + st + ln;
+       return ch;
+}
+
+/** Fetch a character from an utf-8 encoded string.
+ * @param _s      The start of an utf-8 encoded multi-byte character.
+ * @param _end    Will point to after the first multi-byte character.
+ * @return        The 32-bit integer representation of the first multi-byte character or 0 for invalid characters.
+ */
+Uchar u8_getnchar(const char *_s, const char **_end, size_t _maxlen)
+{
+       size_t st, ln;
+       Uchar ch;
+
+       if (!utf8_enable.integer)
+       {
+               if (_end)
+                       *_end = _s + 1;
+               /* Careful: if we disable utf8 but not freetype, we wish to see freetype chars
+                * for normal letters. So use E000+x for special chars, but leave the freetype stuff for the
+                * rest:
+                */
+               if (!char_usefont[(unsigned int)*(const unsigned char*)_s])
+                       return 0xE000 + (Uchar)*(const unsigned char*)_s;
+               return (Uchar)*(const unsigned char*)_s;
+       }
+       
+       if (!u8_analyze(_s, &st, &ln, &ch, _maxlen))
                return 0;
        if (_end)
                *_end = _s + st + ln;
index f435bbdf5169d1116b787a29a0c4b444663e238b..4133908a19498a23da9a5b35165079ab3c0c8c80 100644 (file)
--- a/utf8lib.h
+++ b/utf8lib.h
@@ -36,6 +36,7 @@ int    u8_charidx(const char*, size_t, size_t*);
 size_t u8_bytelen(const char*, size_t);
 size_t u8_prevbyte(const char*, size_t);
 Uchar  u8_getchar(const char*, const char**);
+Uchar  u8_getnchar(const char*, const char**, size_t);
 int    u8_fromchar(Uchar, char*, size_t);
 size_t u8_wcstombs(char*, const Uchar*, size_t);
 size_t u8_COM_StringLengthNoColors(const char *s, size_t size_s, qboolean *valid);