Package: libsdl-ttf2.0-0
Version: 2.0.9-1
Severity: normal

Also tested on source libsdl-ttf2.0 2.0.9-1 built with debug information.

Fixed in SDL_ttf (pre 2.0.10) changeset 144   0f803b00e43b
http://hg.libsdl.org/SDL_ttf/rev/0f803b00e43b

When the underline style is set the TTF_RenderUNICODE_xxx functions can write
past the end of the buffer of the returned SDL surface. The happens in the line
write for loop at the end of each function.

Attached are a program demonstrating the problem and a patch fixing it. The
patch is based on the fix applied to SDL_ttf 2.0.10. To apply the patch, from
the SDL-ttf root directory:

patch <sdl-ttf2.0-2.0.9-underline_bug.patch



-- System Information:
Debian Release: squeeze/sid
  APT prefers testing-proposed-updates
  APT policy: (500, 'testing-proposed-updates'), (500, 'testing')
Architecture: i386 (i686)

Kernel: Linux 2.6.32-5-686 (SMP w/1 CPU core)
Locale: LANG=en_CA.utf8, LC_CTYPE=en_CA.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages libsdl-ttf2.0-0 depends on:
ii  libc6                   2.11.2-2         Embedded GNU C Library: Shared lib
ii  libfreetype6            2.4.2-1          FreeType 2 font engine, shared lib
ii  libsdl1.2debian         1.2.14-6         Simple DirectMedia Layer
ii  zlib1g                  1:1.2.3.4.dfsg-3 compression library - runtime

libsdl-ttf2.0-0 recommends no packages.

libsdl-ttf2.0-0 suggests no packages.
/* Demonstrates libsdl-ttf2.0 2.0.9-1 memory corruption in TTF_RenderUNICODE_Solid
 *
 * underline [<font file> [<text message>]]
 *
 * Prints the last line and one line past, as hex byte values,
 * of a rendered underlined text message.
 *
 * This actual trigger the following error for me:
 * *** glibc detected *** ./underline: free(): invalid next size (normal): 0x084b0670 ***
 *
 * To build:
 * gcc -g underline.c -lSDL_ttf -lSDL -o underline
 *
 * There are no copyright claims on this program.
 */

#include <stdio.h>
#include <SDL/SDL_ttf.h>

static int init(void);
static void quit(void);
static void print_line(SDL_Surface *surf, int line);

int main(int argc, char *argv[])
{
    TTF_Font *font;
    const char *filename;
    const char *msg;
    FILE *test;
    int style;
    SDL_Surface *surf;
    SDL_Color foreg = {250, 240, 230, 0};
    
    if (argc > 1) {
        filename = argv[1];
    }
    else {
        filename = "freesansbold.ttf";
    }
    if (argc > 2) {
        msg = argv[2];
    }
    else {
        msg = "Fonty";
    }
        
    /*check if it is a valid file, else SDL_ttf segfaults*/
    test = fopen(filename, "rb");
    if(!test) {
        printf("Unable to open font file '%.1024s'\n", filename);
        return 1;
    }
    fclose(test);

    if (init() == -1) {
        printf("%s\n", SDL_GetError());
        return 1;
    }
        
    font = TTF_OpenFont(filename, 80);
    if (!font) {
        printf("%s\n", TTF_GetError());
        quit();
        return 1;
    }

    style = TTF_GetFontStyle(font);
    TTF_SetFontStyle(font, style | TTF_STYLE_UNDERLINE);
    
    surf = TTF_RenderText_Solid(font, msg, foreg);
    if (surf == NULL) {
        TTF_CloseFont(font);
        printf("%s\n", TTF_GetError());
        quit();
        return 1;
    }
    
    print_line(surf, surf->h - 1);
    print_line(surf, surf->h);
    
    SDL_FreeSurface(surf);
    TTF_CloseFont(font);

    quit();
    return 0;
}

int init(void)
{
    return TTF_Init();
}

void quit(void)
{
    TTF_Quit();
}

void print_line(SDL_Surface *surf, int line)
{
    unsigned char *lptr = (unsigned char *)surf->pixels + (surf->pitch * line);
    unsigned char *lendptr = lptr + surf->w;
    
    printf("[");
    while (lptr < lendptr) {
        printf(" %.2x ", (unsigned)*lptr);
        ++lptr;
    }
    printf("]\n");
}

--- /usr/local/src/sdl-ttf2.0-2.0.9/SDL_ttf.c	2007-07-14 23:18:29.000000000 -0700
+++ SDL_ttf.c	2010-08-29 12:01:40.000000000 -0700
@@ -1204,7 +1204,7 @@
 			row = (textbuf->h-1) - font->underline_height;
 		}
 		dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch;
-		for ( row=font->underline_height; row>0; --row ) {
+		for ( row=font->underline_height; row>0 && dst < dst_check; --row ) {
 			/* 1 because 0 is the bg color */
 			memset( dst, 1, textbuf->w );
 			dst += textbuf->pitch;
@@ -1465,7 +1465,7 @@
 			row = (textbuf->h-1) - font->underline_height;
 		}
 		dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch;
-		for ( row=font->underline_height; row>0; --row ) {
+		for ( row=font->underline_height; row>0 && dst < dst_check; --row ) {
 			memset( dst, NUM_GRAYS - 1, textbuf->w );
 			dst += textbuf->pitch;
 		}
@@ -1721,7 +1721,7 @@
 		}
 		dst = (Uint32 *)textbuf->pixels + row * textbuf->pitch/4;
 		pixel |= 0xFF000000; /* Amask */
-		for ( row=font->underline_height; row>0; --row ) {
+		for ( row=font->underline_height; row>0 && dst < dst_check; --row ) {
 			for ( col=0; col < textbuf->w; ++col ) {
 				dst[col] = pixel;
 			}

Reply via email to