shithub: cstory

Download patch

ref: 145864cf2dc4dafdf9d7f345a635376bb6f42605
parent: 679c6d0391d2ad520f5c672fa5b25a63518af017
author: Clownacy <Clownacy@users.noreply.github.com>
date: Wed Jul 24 19:34:16 EDT 2019

Added sanity checks to the backends

This fixes the Texture backend bug that made the program take forever
to shut down:

The problem was that the font system would try to load a glyph that's
0 pixels wide/tall (likely the space character), which SDL2 didn't
like, so it would fail to allocate the texture, causing
Backend_CreateSurface, and by extension Backend_CreateGlyph, to
return a NULL. Later, upon shutdown, the font system would pass this
NULL to Backend_FreeGlyph, causing NULL pointer dereferences that
make the program take forever to shut down.

Personally, I think passing NULLs to the backend is valid behaviour,
so I've added a bunch of sanity checks to make sure they're never
dereferenced.

--- a/src/Backends/Rendering/OpenGL2.cpp
+++ b/src/Backends/Rendering/OpenGL2.cpp
@@ -213,6 +213,9 @@
 
 void Backend_FreeSurface(Backend_Surface *surface)
 {
+	if (surface == NULL)
+		return;
+
 	glDeleteTextures(1, &surface->texture_id);
 	free(surface);
 }
@@ -219,6 +222,9 @@
 
 unsigned char* Backend_Lock(Backend_Surface *surface, unsigned int *pitch)
 {
+	if (surface == NULL)
+		return NULL;
+
 	surface->pixels = (unsigned char*)malloc(surface->width * surface->height * 3);
 	*pitch = surface->width * 3;
 	return surface->pixels;
@@ -226,6 +232,9 @@
 
 void Backend_Unlock(Backend_Surface *surface)
 {
+	if (surface == NULL)
+		return;
+
 	glBindTexture(GL_TEXTURE_2D, surface->texture_id);
 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surface->width, surface->height, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels);
 	free(surface->pixels);
@@ -256,6 +265,9 @@
 
 void Backend_Blit(Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key)
 {
+	if (source_surface == NULL || destination_surface == NULL)
+		return;
+
 	// Point our framebuffer to the destination texture
 	SetRenderTarget(destination_surface);
 
@@ -264,6 +276,9 @@
 
 void Backend_BlitToScreen(Backend_Surface *source_surface, const RECT *rect, long x, long y, BOOL colour_key)
 {
+	if (source_surface == NULL)
+		return;
+
 	// Point our framebuffer to the screen texture
 	SetRenderTarget(&framebuffer_surface);
 
@@ -292,6 +307,9 @@
 
 void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
 {
+	if (surface == NULL)
+		return;
+
 	// Point our framebuffer to the destination texture
 	SetRenderTarget(surface);
 
@@ -308,6 +326,9 @@
 
 void Backend_ScreenToSurface(Backend_Surface *surface, const RECT *rect)
 {
+	if (surface == NULL)
+		return;
+
 	// Point our framebuffer to the destination texture
 	SetRenderTarget(surface);
 
@@ -385,6 +406,9 @@
 
 void Backend_UnloadGlyph(Backend_Glyph *glyph)
 {
+	if (glyph == NULL)
+		return;
+
 	glDeleteTextures(1, &glyph->texture_id);
 	free(glyph);
 }
@@ -411,6 +435,9 @@
 
 void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
 {
+	if (glyph == NULL || surface == NULL)
+		return;
+
 	// Point our framebuffer to the destination texture
 	SetRenderTarget(surface);
 
@@ -419,6 +446,9 @@
 
 void Backend_DrawGlyphToScreen(Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
 {
+	if (glyph == NULL)
+		return;
+
 	// Point our framebuffer to the screen texture
 	SetRenderTarget(&framebuffer_surface);
 
--- a/src/Backends/Rendering/SDLSurface.cpp
+++ b/src/Backends/Rendering/SDLSurface.cpp
@@ -88,6 +88,9 @@
 
 void Backend_FreeSurface(Backend_Surface *surface)
 {
+	if (surface == NULL)
+		return;
+
 	SDL_FreeSurface(surface->sdl_surface);
 	free(surface);
 }
@@ -94,6 +97,9 @@
 
 unsigned char* Backend_Lock(Backend_Surface *surface, unsigned int *pitch)
 {
+	if (surface == NULL)
+		return NULL;
+
 	*pitch = surface->sdl_surface->pitch;
 	return (unsigned char*)surface->sdl_surface->pixels;
 }
@@ -105,6 +111,9 @@
 
 void Backend_Blit(Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key)
 {
+	if (source_surface == NULL || destination_surface == NULL)
+		return;
+
 	SDL_Rect source_rect;
 	RectToSDLRect(rect, &source_rect);
 
@@ -126,6 +135,9 @@
 
 void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
 {
+	if (surface == NULL)
+		return;
+
 	SDL_Rect destination_rect;
 	RectToSDLRect(rect, &destination_rect);
 
@@ -206,6 +218,9 @@
 
 void Backend_UnloadGlyph(Backend_Glyph *glyph)
 {
+	if (glyph == NULL)
+		return;
+
 	SDL_FreeSurface(glyph->sdl_surface);
 	free(glyph);
 }
@@ -212,6 +227,9 @@
 
 void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
 {
+	if (glyph == NULL || surface == NULL)
+		return;
+
 	SDL_Rect rect;
 	rect.x = x;
 	rect.y = y;
--- a/src/Backends/Rendering/SDLTexture.cpp
+++ b/src/Backends/Rendering/SDLTexture.cpp
@@ -163,11 +163,15 @@
 
 void Backend_FreeSurface(Backend_Surface *surface)
 {
+	if (surface == NULL)
+		return;
+
 	if (surface->next)
 		surface->next->prev = surface->prev;
 	if (surface->prev)
 		surface->prev->next = surface->next;
 
+	SDL_DestroyTexture(surface->texture);
 	SDL_FreeSurface(surface->sdl_surface);
 	free(surface);
 }
@@ -174,6 +178,9 @@
 
 unsigned char* Backend_Lock(Backend_Surface *surface, unsigned int *pitch)
 {
+	if (surface == NULL)
+		return NULL;
+
 	*pitch = surface->sdl_surface->pitch;
 	return (unsigned char*)surface->sdl_surface->pixels;
 }
@@ -180,11 +187,17 @@
 
 void Backend_Unlock(Backend_Surface *surface)
 {
+	if (surface == NULL)
+		return;
+
 	surface->needs_syncing = TRUE;
 }
 
 void Backend_Blit(Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key)
 {
+	if (source_surface == NULL || destination_surface == NULL)
+		return;
+
 	if (source_surface->needs_syncing)
 	{
 		FlushSurface(source_surface);
@@ -209,6 +222,9 @@
 
 void Backend_BlitToScreen(Backend_Surface *source_surface, const RECT *rect, long x, long y, BOOL colour_key)
 {
+	if (source_surface == NULL)
+		return;
+
 	if (source_surface->needs_syncing)
 	{
 		FlushSurface(source_surface);
@@ -227,6 +243,9 @@
 
 void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
 {
+	if (surface == NULL)
+		return;
+
 	SDL_Rect sdl_rect;
 	RectToSDLRect(rect, &sdl_rect);
 
@@ -261,6 +280,9 @@
 
 void Backend_ScreenToSurface(Backend_Surface *surface, const RECT *rect)
 {
+	if (surface == NULL)
+		return;
+
 	SDL_Rect sdl_rect;
 	RectToSDLRect(rect, &sdl_rect);
 
@@ -362,6 +384,9 @@
 
 void Backend_UnloadGlyph(Backend_Glyph *glyph)
 {
+	if (glyph == NULL)
+		return;
+
 	Backend_FreeSurface(glyph->surface);
 	free(glyph);
 }
@@ -373,6 +398,9 @@
 	// colour-keys, so the next best thing is relying on the software fallback, but I don't like the idea
 	// of uploading textures to the GPU every time a glyph is drawn.
 
+	if (glyph == NULL || surface == NULL)
+		return;
+
 	RECT rect;
 	rect.left = 0;
 	rect.top = 0;
@@ -387,6 +415,9 @@
 
 void Backend_DrawGlyphToScreen(Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
 {
+	if (glyph == NULL)
+		return;
+
 	RECT rect;
 	rect.left = 0;
 	rect.top = 0;
--- a/src/Backends/Rendering/Software.cpp
+++ b/src/Backends/Rendering/Software.cpp
@@ -93,6 +93,9 @@
 
 void Backend_FreeSurface(Backend_Surface *surface)
 {
+	if (surface == NULL)
+		return;
+
 	free(surface->pixels);
 	free(surface);
 }
@@ -99,6 +102,9 @@
 
 unsigned char* Backend_Lock(Backend_Surface *surface, unsigned int *pitch)
 {
+	if (surface == NULL)
+		return NULL;
+
 	*pitch = surface->pitch;
 	return surface->pixels;
 }
@@ -110,6 +116,9 @@
 
 void Backend_Blit(Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key)
 {
+	if (source_surface == NULL || destination_surface == NULL)
+		return;
+
 	RECT rect_clamped;
 
 	rect_clamped.left = rect->left;
@@ -195,6 +204,9 @@
 
 void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
 {
+	if (surface == NULL)
+		return;
+
 	RECT rect_clamped;
 
 	rect_clamped.left = rect->left;
@@ -356,6 +368,9 @@
 
 void Backend_UnloadGlyph(Backend_Glyph *glyph)
 {
+	if (glyph == NULL)
+		return;
+
 	free(glyph->pixels);
 	free(glyph);
 }
@@ -362,6 +377,9 @@
 
 void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
 {
+	if (glyph == NULL || surface == NULL)
+		return;
+
 	switch (glyph->pixel_mode)
 	{
 		case FONT_PIXEL_MODE_LCD: