libsdl-org / SDL_ttf

Support for TrueType (.ttf) font files with Simple Directmedia Layer.
zlib License
363 stars 122 forks source link

Segfault on Windows 2.0.18 release for certain fonts/sizes #201

Closed Starbuck5 closed 2 years ago

Starbuck5 commented 2 years ago

Over at pygame we got an issue report after updating to SDL_ttf 2.0.18 that rendering a font that previously worked segfaulted their program. It only seems to segfault at certain sizes.

I wanted to be sure this was a problem at the C level, and not an unrelated regression by pygame, so I put together a small test script.

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

int main(int argc, char *argv[])
{
    SDL_SetMainReady();
    SDL_Init(SDL_INIT_VIDEO);

    SDL_Window *window = NULL;
    SDL_Surface *screen = NULL;

    window = SDL_CreateWindow("Example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 500, 150, SDL_WINDOW_SHOWN);

    screen = SDL_GetWindowSurface(window);
    SDL_FillRect(screen, NULL, SDL_MapRGBA(screen->format, 0, 0, 120, 255));

    printf("running on patch level %i\n", SDL_TTF_PATCHLEVEL);

    TTF_Init();

    // font size 70 = segfault, 20 = fine
    TTF_Font* f = TTF_OpenFont("PlayfairDisplay-Regular.ttf", 20);
    printf("error=%s\n", SDL_GetError());

    SDL_Color white;
    white.r = 255;
    white.g = 255;
    white.b = 255;
    white.a = 255;

    //SDL_Surface *text = TTF_RenderText_Blended(f, "Hello world", white);
    SDL_Surface *text = TTF_RenderUTF8_Blended(f, "Hello world", white);
    printf("text=%p\n", text);
    printf("error=%s\n", SDL_GetError());

    SDL_BlitSurface(text, NULL, screen, NULL);
    printf("error=%s\n", SDL_GetError());

    SDL_UpdateWindowSurface(window);
    printf("error=%s\n", SDL_GetError());

    // Keep the main loop until the window is closed (SDL_QUIT event)
    int exit = 0;
    SDL_Event eventData;
    while (!exit)
    {
        while (SDL_PollEvent(&eventData))
        {
            switch (eventData.type)
            {
            case SDL_QUIT:
                exit = 1;
                break;
            }
        }
    }

    SDL_Quit();

    return 0;
}

Both pygame and my test script are compiled with Visual Studio, and use the 64 bit dev VS SDL_ttf 2.0.18 release. I tried to replicate this bug on my Mac, but I was unable to.

Running this in the VS debugger yields: Unhandled exception at 0x00007FFDE6C723F6 (ntdll.dll) in SDL_c_test.exe: 0xC0000028: An invalid or unaligned stack was encountered during an unwind operation. ^ This pops up over the call to TTF_RenderUTF8_Blended

Call stack: Capture

This hits the playfair family, at least regular and semibold (those are the ones I tested). PlayfairDisplay-Regular.zip

I also tested this through pygame with all the system fonts pygame could detect, and got failures on the fonts

algerian, castellar, gigi, imprintshadow, blackadderitc, edwardianscriptitc, kunstlerscript
maturascriptcapitals, oldenglishtext, msoutlook, parchment, vivaldi, vladimirscript
1bsyl commented 2 years ago

I can't reproduce it on linux. also using some fuzzy test doesn't fail.

Starbuck5 commented 2 years ago

Sorry for the late response @1bsyl

Can you add some debug flag to have more info ?

I'm not sure how. I'm building the c code in debug mode, and running it in a debugger. I probably need an SDL_ttf with debug symbols, I'm just using the stock development DLL prebuilt. I've had difficulties before when I've attempted to build SDL_ttf from source in Visual Studio.

Printf the Surface width, height, pitch ?

The surface doesn't get created, it crashes somewhere in the render. Or perhaps something goes wrong in the TTF_OpenFont only at certain sizes, that is encountered when the program goes to render text.

Eventually replace "SDL_Surface *text = TTF_RenderUTF8_Blended(f, "Hello world", white);" by a dummy blank surface to make sure that SDL_ttf is really involved.

I did that, and the code worked.

Some messing around got me more debug info from the bottom of the callstack: Capture

Here's a thread I found on this issue: https://stackoverflow.com/questions/26605063/an-invalid-or-unaligned-stack-was-encountered-during-an-unwind-operation

I guess I need to try and build SDL_ttf myself, with debug symbols? In Visual Studio. I'm confident other Windows users could replicate this bug though, although it might be specific to the MSVC DLL prebuilt.

1bsyl commented 2 years ago

I tried on window with my VisualC project and it runs fine. (this is visual studio 2017) Build for x86 and also x64 for UWP I use the latest dev source of SDL_ttf. and latest SDL dev source

Maybe put SDL_Log() instead of printf() because traces didn't appear

Starbuck5 commented 2 years ago

I use the latest dev source of SDL_ttf. and latest SDL dev source

Try using the SDL_ttf 2.0.18 VC development DLL. It's also specific to the font and size.

1bsyl commented 2 years ago

I tried you test case. eg font + size. So this should get reproduce.

Maybe your SDL dll (not dll) isn't recent enough. I am not much familiar wit window. I suggest to try to rebuild SDL_ttf

Starbuck5 commented 2 years ago

I'll try.

I checked, my test case uses SDL 2.0.22.

Is there a way to build SDL_ttf easily on VS? It seems like such a pain to have to pick out the linker folders and the include folders.

Capture Ok, I put in the include paths (to external/freetype, external/harfbuzz, and I put my SDL in there too, external/SDL). I put in the SDL include path as well. I'm not sure how to deal with these harfbuzz guys, since it's not a prebuilt I don't have an include path to put.

Solved with this: https://stackoverflow.com/questions/42801276/error-lnk-2019-unresolved-external-symbol-imp-crtdbgreportw-in-visual-studio

1bsyl commented 2 years ago

Ok. Really double check the dll sdl2 beacause this could silently fails if it doesnt handle aligned memory

Le jeu. 19 mai 2022, 07:42, Charlie Hayden @.***> a écrit :

I'll try.

I checked, my test case uses SDL 2.0.22.

— Reply to this email directly, view it on GitHub https://github.com/libsdl-org/SDL_ttf/issues/201#issuecomment-1131232349, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGH4KEKPCVVXPBOJ5VFWA3VKXIDVANCNFSM5VHP2LIQ . You are receiving this because you were mentioned.Message ID: @.***>

Starbuck5 commented 2 years ago

@1bsyl Yes!

With the SDL_ttf 2.0.19 DLL I built, the segfault goes away!

It is slightly different, because I built the DLL for x86 by mistake, and my previous tests were in x64, but that shouldn't matter (hopefully). This is also a debug build vs a release build.

Do you SDL peeps want to do another SDL_ttf release soon? :smile:

RageRocker commented 2 years ago

I get the same "unaligned stack" exception described above when calling TTF_RenderUTF8_Blended. x64 debug and release builds crash. x86 builds seem to work as expected.

Using Visual Studio 2022, SDL2_ttf-devel-2.0.18-VC.zip, C++17. OpenSans-Regular.ttf from Google's free fonts.

Starbuck5 commented 2 years ago

@RageRocker I just tried it on my homemade SDL_ttf 2.0.19 DLL, x64, and it seems to be working on this.

Try slotting this guy in: (It's an x64 release build) SDL2_ttf.zip

slouken commented 2 years ago

Okay, I found the ft_longjmp call that's problematic at font size 70. It's in ftgrays.c, line 616.

slouken commented 2 years ago

The official SDL_ttf DLL is built with mingw64, and it looks like there's an issue with setjmp/longjmp on 64-bit architecture: https://stackoverflow.com/questions/53709069/setjmp-longjmp-in-x86-64-w64-mingw32

slouken commented 2 years ago

And a workaround: https://web.archive.org/web/20170110124635/http://www.agardner.me/golang/windows/cgo/64-bit/setjmp/longjmp/2016/02/29/go-windows-setjmp-x86.html

Starbuck5 commented 2 years ago

The official SDL_ttf DLL is built with mingw64

Even the MSVC release? (That's the one I was using, specifically SDL2_ttf-devel-2.0.18-VC

slouken commented 2 years ago

Yep, it's just the official SDL_ttf DLL with Visual Studio import libraries.

slouken commented 2 years ago

The good news is, I can reproduce this, so I can see if the workaround is viable.

Starbuck5 commented 2 years ago

Should this be a patch to freetype when compiled in Mingw?

slouken commented 2 years ago

I built with a newer mingw64 compiler, and it looks like this may have been fixed. Can you try this DLL? https://www.libsdl.org/tmp/SDL2_ttf.zip

Starbuck5 commented 2 years ago

Yes, that works!

To get it building I used the .lib file I had around from my build of SDL_ttf. (If that matters, which it probably doesn't)

slouken commented 2 years ago

Great, thanks!

slouken commented 2 years ago

I'll leave this issue open for verification with the final 2.20.0 release candidate build.

Thanks!

Starbuck5 commented 2 years ago

I've verified this against the SDL_ttf 2.19.2 MSVC development prebuilt. No segfault!

slouken commented 2 years ago

Great, thanks!