-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tries to free previous results of SDL_SetVideoMode(), leading to use-after-free crash #305
Comments
libsdl-org/sdl12-compat#305 contains C code that is a simplification of what this binding is doing, leading to the same crash. Here's a similarly cut-down version of |
smcv
added a commit
to smcv/SDL1_perl
that referenced
this issue
Jul 18, 2023
In many SDL APIs that return a SDL_Surface *, the surface is considered to be owned by the caller, and must be freed by the caller. However, SDL_SetVideoMode and presumably SDL_GetVideoSurface return a pointer to SDL's internal video surface, which will be freed by SDL if necessary, and must not be freed by library users. Incorrectly freeing this surface can lead to a use-after-free crash, manifesting as a test failure in t/core_video.t. See also libsdl-org/sdl12-compat#305 Resolves: PerlGameDev#305 Signed-off-by: Simon McVittie <[email protected]>
This was referenced Jul 18, 2023
smcv
added a commit
to smcv/sdl12-compat
that referenced
this issue
Jul 20, 2023
The SDL Perl bindings incorrectly call SDL_FreeSurface() on the result of functions that return a "borrowed" pointer to the video surface, namely SDL_SetVideoMode() and SDL_GetVideoSurface(). (See PerlGameDev/SDL#305) When we would previously have allocated or freed the video surface wrapper object, instead allocate or free its contents in-place. When checking whether the video surface exists, because we never destroy it, we must now also check whether its underlying SDL2 video surface exists. Resolves: libsdl-org#305 Signed-off-by: Simon McVittie <[email protected]>
smcv
added a commit
to smcv/sdl12-compat
that referenced
this issue
Aug 26, 2023
The SDL Perl bindings incorrectly call SDL_FreeSurface() on the result of functions that return a "borrowed" pointer to the video surface, namely SDL_SetVideoMode() and SDL_GetVideoSurface(). (See PerlGameDev/SDL#305) When we would previously have allocated or freed the video surface wrapper object, instead allocate or free its contents in-place. When checking whether the video surface exists, because we never destroy it, we must now also check whether its underlying SDL2 video surface exists. Resolves: libsdl-org#305 Signed-off-by: Simon McVittie <[email protected]>
slouken
pushed a commit
to libsdl-org/sdl12-compat
that referenced
this issue
Aug 26, 2023
The SDL Perl bindings incorrectly call SDL_FreeSurface() on the result of functions that return a "borrowed" pointer to the video surface, namely SDL_SetVideoMode() and SDL_GetVideoSurface(). (See PerlGameDev/SDL#305) When we would previously have allocated or freed the video surface wrapper object, instead allocate or free its contents in-place. When checking whether the video surface exists, because we never destroy it, we must now also check whether its underlying SDL2 video surface exists. Resolves: #305 Signed-off-by: Simon McVittie <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This binding is packaged in Debian as libsdl-perl. Since trying to switch from classic SDL 1.2 to sdl12-compat in Debian, we've been seeing crashes in its test
perl t/core_video.t
. On 32-bit platforms it seems to segfault repeatably; on 64-bit platforms it usually succeeds, but using valgrind or AddressSanitizer reveals that there is still a use-after-free, it's just not fatal for whatever reason.I asked SDL/sdl12-compat upstream about this, and they say that calling
SDL_FreeSurface()
on the result ofSDL_SetVideoMode()
is considered to be a programming error (invalid/undefined behaviour), because the video surface is "borrowed" from SDL internals. This is mitigated by SDL silently ignoring attempts to free the current video surface; however, the test keeps a pointer to an older video surface around, and tries to free that later, after SDL has already freed it.I think the correct solution is likely to be for this binding to distinguish between SDL_Surface objects that are "owned" by the caller (which it should free), and SDL_Surface objects that are "borrowed" from SDL (which it must not free). At the moment, the binding assumes that it "owns" all SDL_Surface objects returned by any SDL API.
If I understand correctly,
SDL_GetVideoSurface()
has similar memory-management, and therefore its Perl interface has a similar bug.Here's an example of the use-after-free, using versions of SDL2 and sdl12-compat that have been compiled using AddressSanitizer:
AddressSanitizer output
t/core_palette.t
shows a similar user-after-free, although we haven't observed this causing real-world crashes in Debian (even on 32-bit) for whatever reason:AddressSanitizer output
The text was updated successfully, but these errors were encountered: