Commits

Alex Szpakowski committed bc2200c

Fixed undefined behaviour when love exceptions are converted into Lua errors (resolves issue #729)

  • Participants
  • Parent commits 85ee2a2

Comments (0)

Files changed (45)

File src/common/runtime.h

 
 Type luax_type(lua_State *L, int idx);
 
+/**
+ * Macro for converting a LOVE exception into a Lua error.
+ * lua_error (and luaL_error) cannot be called from inside the exception handler
+ * because they use longjmp, which causes undefined behaviour when the
+ * destructor of the exception would have been called.
+ **/
+#define EXCEPT_GUARD(A) \
+{ \
+	bool should_error = false; \
+	try { A } \
+	catch (love::Exception &e) \
+	{ \
+		should_error = true; \
+		lua_pushstring(L, e.what()); \
+	} \
+	if (should_error) \
+		return lua_error(L); \
+}
+
 } // love
 
 #endif // LOVE_RUNTIME_H

File src/modules/event/sdl/wrap_Event.cpp

 {
 	if (instance == 0)
 	{
-		try
-		{
-			instance = new Event();
-		}
-		catch (love::Exception &e)
-		{
-			return luaL_error(L, "%s", e.what());
-		}
+		EXCEPT_GUARD(instance = new Event();)
 	}
 	else
 		instance->retain();

File src/modules/filesystem/physfs/Filesystem.cpp

 		}
 		else
 		{
-			char *str;
+			char *str = 0;
 			try
 			{
 				str = new char[linesize + 1];
 			}
 			catch(std::bad_alloc &)
 			{
-				return luaL_error(L, "Out of memory");
+				// Can't lua_error (longjmp) in exception handlers.
 			}
+
+			if (!str)
+				return luaL_error(L, "Out of memory.");
+
 			file->seek(pos);
 
 			// Read the \n anyway and save us a call to seek.

File src/modules/filesystem/physfs/wrap_File.cpp

 #include "common/Exception.h"
 #include "common/int.h"
 
-static int ioError(lua_State *L, const char *fmt, ...)
+namespace love
+{
+namespace filesystem
+{
+namespace physfs
+{
+
+int luax_ioError(lua_State *L, const char *fmt, ...)
 {
 	va_list args;
 	va_start(args, fmt);
 	return 2;
 }
 
-namespace love
-{
-namespace filesystem
-{
-namespace physfs
-{
-
 File *luax_checkfile(lua_State *L, int idx)
 {
 	return luax_checktype<File>(L, idx, "File", FILESYSTEM_FILE_T);
 	int64 size = t->getSize();
 
 	// Push nil on failure or if size does not fit into a double precision floating-point number.
-	if (size == -1 || size >= 0x20000000000000LL)
-		lua_pushnil(L);
-	else
-		lua_pushnumber(L, (lua_Number)size);
+	if (size == -1)
+		return luax_ioError(L, "Could not determine file size.");
+	else if (size >= 0x20000000000000LL)
+		return luax_ioError(L, "Size is too large.");
 
+	lua_pushnumber(L, (lua_Number) size);
 	return 1;
 }
 
 	}
 	catch (love::Exception &e)
 	{
-		return ioError(L, "%s", e.what());
+		return luax_ioError(L, "%s", e.what());
 	}
 
 	return 1;
 	}
 	catch (love::Exception &e)
 	{
-		return ioError(L, "%s", e.what());
+		return luax_ioError(L, "%s", e.what());
 	}
 
 	lua_pushlstring(L, (const char *) d->getData(), d->getSize());
 	{
 		try
 		{
-			result = file->write(lua_tostring(L, 2), luaL_optint(L, 3, lua_objlen(L, 2)));
+			size_t datasize = 0;
+			const char *data = lua_tolstring(L, 2, &datasize);
+
+			if (!lua_isnoneornil(L, 3))
+				datasize = luaL_checkinteger(L, 3);
+
+			result = file->write(data, datasize);
 		}
 		catch (love::Exception &e)
 		{
-			return ioError(L, "%s", e.what());
+			return luax_ioError(L, "%s", e.what());
 		}
 	}
 	else if (luax_istype(L, 2, DATA_T))
 		try
 		{
 			love::Data *data = luax_totype<love::Data>(L, 2, "Data", DATA_T);
-			result = file->write(data, luaL_optint(L, 3, data->getSize()));
+			result = file->write(data, luaL_optinteger(L, 3, data->getSize()));
 		}
 		catch (love::Exception &e)
 		{
-			return ioError(L, "%s", e.what());
+			return luax_ioError(L, "%s", e.what());
 		}
 	}
 	else
 		return luaL_argerror(L, 2, "string or data expected");
 	}
 
-	lua_pushboolean(L, result);
+	luax_pushboolean(L, result);
 	return 1;
 }
 
 	}
 	catch (love::Exception &e)
 	{
-		return ioError(L, "%s", e.what());
+		return luax_ioError(L, "%s", e.what());
 	}
 	luax_pushboolean(L, success);
 	return 1;
 	File *file = luax_checkfile(L, 1);
 	int64 pos = file->tell();
 	// Push nil on failure or if pos does not fit into a double precision floating-point number.
-	if (pos == -1 || pos >= 0x20000000000000LL)
-		lua_pushnil(L);
+	if (pos == -1)
+		return luax_ioError(L, "Invalid position.");
+	else if (pos >= 0x20000000000000LL)
+		return luax_ioError(L, "Number is too large.");
 	else
 		lua_pushnumber(L, (lua_Number)pos);
 	return 1;
 		if (file->getMode() != File::CLOSED)
 			file->close();
 
-		try
-		{
-			if (!file->open(File::READ))
-				return luaL_error(L, "Could not open file.");
-		}
-		catch (love::Exception &e)
-		{
-			return luaL_error(L, "%s", e.what());
-		}
+		bool success = false;
+		EXCEPT_GUARD(success = file->open(File::READ);)
+
+		if (!success)
+			return luaL_error(L, "Could not open file.");
 	}
 
 	lua_pushcclosure(L, Filesystem::lines_i, 3);
 	}
 	catch (love::Exception &e)
 	{
-		return ioError(L, "%s", e.what());
+		return luax_ioError(L, "%s", e.what());
 	}
 
 	luax_pushboolean(L, success);
 	const char *str = 0;
 
 	if (!File::getConstant(bufmode, str))
-		return ioError(L, "Unknown file buffer mode.");
+		return luax_ioError(L, "Unknown file buffer mode.");
 
 	lua_pushstring(L, str);
 	lua_pushnumber(L, (lua_Number) size);
 	const char *str = 0;
 
 	if (!File::getConstant(mode, str))
-		return ioError(L, "Unknown file mode.");
+		return luax_ioError(L, "Unknown file mode.");
 
 	lua_pushstring(L, str);
 	return 1;

File src/modules/filesystem/physfs/wrap_File.h

 namespace physfs
 {
 
+// Does not use lua_error, so it's safe to call in exception handling code.
+int luax_ioError(lua_State *L, const char *fmt, ...);
+
 File *luax_checkfile(lua_State *L, int idx);
 int w_File_getSize(lua_State *L);
 int w_File_open(lua_State *L);

File src/modules/filesystem/physfs/wrap_Filesystem.cpp

 // LOVE
 #include "wrap_Filesystem.h"
 
-static int ioError(lua_State *L, const char *fmt, ...)
-{
-	va_list args;
-	va_start(args, fmt);
-
-	lua_pushnil(L);
-	lua_pushvfstring(L, fmt, args);
-
-	va_end(args);
-	return 2;
-}
+// SDL
+#include <SDL_loadso.h>
 
 namespace love
 {
 int w_init(lua_State *L)
 {
 	const char *arg0 = luaL_checkstring(L, 1);
-
-	try
-	{
-		instance->init(arg0);
-	}
-	catch(Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
-
+	EXCEPT_GUARD(instance->init(arg0);)
 	return 0;
 }
 
 		catch (love::Exception &e)
 		{
 			t->release();
-			return ioError(L, "%s", e.what());
+			return luax_ioError(L, "%s", e.what());
 		}
 	}
 
 			}
 			catch (love::Exception &e)
 			{
-				return ioError(L, "%s", e.what());
+				return luax_ioError(L, "%s", e.what());
 			}
 			luax_pushtype(L, "FileData", FILESYSTEM_FILE_DATA_T, data);
 			return 1;
 	}
 	catch (love::Exception &e)
 	{
-		return ioError(L, "%s", e.what());
+		return luax_ioError(L, "%s", e.what());
 	}
 
 	if (data == 0)
-		return ioError(L, "File could not be read.");
+		return luax_ioError(L, "File could not be read.");
 
 	// Push the string.
 	lua_pushlstring(L, (const char *) data->getData(), data->getSize());
 	}
 	catch (love::Exception &e)
 	{
-		return ioError(L, "%s", e.what());
+		return luax_ioError(L, "%s", e.what());
 	}
 
 	luax_pushboolean(L, true);
-
 	return 1;
 }
 
 	if (lua_isstring(L, 1))
 	{
 		file = instance->newFile(lua_tostring(L, 1));
-		try
-		{
-			if (!file->open(File::READ))
-				return luaL_error(L, "Could not open file.");
-		}
-		catch(love::Exception &e)
-		{
-			return luaL_error(L, "%s", e.what());
-		}
+		bool success = false;
+
+		EXCEPT_GUARD(success = file->open(File::READ);)
+
+		if (!success)
+			return luaL_error(L, "Could not open file.");
+		
 		luax_pushtype(L, "File", FILESYSTEM_FILE_T, file);
 	}
 	else
-		return luaL_error(L, "Expected filename.");
+		return luaL_argerror(L, 1, "expected filename.");
 
 	lua_pushcclosure(L, Filesystem::lines_i, 1);
 	return 1;
 	}
 	catch (love::Exception &e)
 	{
-		return ioError(L, "%s", e.what());
+		return luax_ioError(L, "%s", e.what());
 	}
 
 	int status = luaL_loadbuffer(L, (const char *)data->getData(), data->getSize(), ("@" + filename).c_str());
 	}
 	catch (love::Exception &e)
 	{
-		lua_pushnil(L);
-		lua_pushstring(L, e.what());
-		return 2;
+		return luax_ioError(L, "%s", e.what());
 	}
 
 	lua_pushnumber(L, static_cast<lua_Number>(time));
-
 	return 1;
 }
 
 	}
 	catch (love::Exception &e)
 	{
-		return ioError(L, "%s", e.what());
+		return luax_ioError(L, "%s", e.what());
 	}
 
 	// Error on failure or if size does not fit into a double precision floating-point number.
 	if (size == -1)
-		return ioError(L, "Could not determine file size.");
+		return luax_ioError(L, "Could not determine file size.");
 	else if (size >= 0x20000000000000LL)
-		return luaL_error(L, "Size too large to fit into a Lua number!");
-
+		return luax_ioError(L, "Size too large to fit into a Lua number!");
 
 	lua_pushnumber(L, (lua_Number) size);
 	return 1;
 {
 	if (instance == 0)
 	{
-		try
-		{
-			instance = new Filesystem();
-			love::luax_register_searcher(L, loader, 1);
-			love::luax_register_searcher(L, extloader, 2);
-		}
-		catch(Exception &e)
-		{
-			return luaL_error(L, e.what());
-		}
+		EXCEPT_GUARD(instance = new Filesystem();)
 	}
 	else
-	{
 		instance->retain();
-		love::luax_register_searcher(L, loader, 1);
-		love::luax_register_searcher(L, extloader, 2);
-	}
+
+	love::luax_register_searcher(L, loader, 1);
+	love::luax_register_searcher(L, extloader, 2);
 
 	WrappedModule w;
 	w.module = instance;

File src/modules/filesystem/physfs/wrap_Filesystem.h

 #include "wrap_File.h"
 #include "wrap_FileData.h"
 
-// SDL
-#include <SDL_loadso.h>
-
 namespace love
 {
 namespace filesystem

File src/modules/font/freetype/wrap_Font.cpp

 	if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T))
 		luax_convobj(L, 1, "filesystem", "newFileData");
 
-	Rasterizer *t = NULL;
-	try
-	{
+	Rasterizer *t = 0;
+
+	EXCEPT_GUARD(
 		if (luax_istype(L, 1, IMAGE_IMAGE_DATA_T))
 		{
 			love::image::ImageData *d = luax_checktype<love::image::ImageData>(L, 1, "ImageData", IMAGE_IMAGE_DATA_T);
 			int size = luaL_checkint(L, 2);
 			t = instance->newRasterizer(d, size);
 		}
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	)
 
 	luax_pushtype(L, "Rasterizer", FONT_RASTERIZER_T, t);
 	return 1;
 	if (lua_type(L, 2) == LUA_TSTRING)
 	{
 		std::string glyph = luax_checkstring(L, 2);
-		try
-		{
-			t = instance->newGlyphData(r, glyph);
-		}
-		catch (love::Exception &e)
-		{
-			return luaL_error(L, "%s", e.what());
-		}
+
+		EXCEPT_GUARD(t = instance->newGlyphData(r, glyph);)
 	}
 	else
 	{
 {
 	if (instance == 0)
 	{
-		try
-		{
-			instance = new Font();
-		}
-		catch(Exception &e)
-		{
-			return luaL_error(L, e.what());
-		}
+		EXCEPT_GUARD(instance = new Font();)
 	}
 	else
 		instance->retain();

File src/modules/font/wrap_GlyphData.cpp

 int w_GlyphData_getGlyphString(lua_State *L)
 {
 	GlyphData *t = luax_checkglyphdata(L, 1);
-	try
-	{
-		luax_pushstring(L, t->getGlyphString());
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+
+	EXCEPT_GUARD(luax_pushstring(L, t->getGlyphString());)
 	return 1;
 }
 

File src/modules/font/wrap_Rasterizer.cpp

 	Rasterizer *t = luax_checkrasterizer(L, 1);
 	GlyphData *g = 0;
 
-	try
-	{
+	EXCEPT_GUARD(
 		// getGlyphData accepts a unicode character or a codepoint number.
 		if (lua_type(L, 2) == LUA_TSTRING)
 		{
 			uint32 glyph = (uint32) luaL_checknumber(L, 2);
 			g = t->getGlyphData(glyph);
 		}
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	)
 
 	luax_pushtype(L, "GlyphData", FONT_GLYPH_DATA_T, g);
 	return 1;
 
 	bool hasglyph = false;
 
-	try
-	{
+	EXCEPT_GUARD(
 		if (lua_type(L, 2) == LUA_TSTRING)
 			hasglyph = t->hasGlyph(luax_checkstring(L, 2));
 		else
 			hasglyph = t->hasGlyph((uint32) luaL_checknumber(L, 2));
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	)
 
 	luax_pushboolean(L, hasglyph);
 	return 1;

File src/modules/graphics/opengl/wrap_Canvas.cpp

 	Canvas *canvas = luax_checkcanvas(L, 1);
 	luaL_checktype(L, 2, LUA_TFUNCTION);
 
-	try
-	{
-		canvas->startGrab();
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(canvas->startGrab();)
+
 	lua_settop(L, 2); // make sure the function is on top of the stack
 	lua_call(L, 0, 0);
 	canvas->stopGrab();
 	int x = luaL_checkint(L, 2);
 	int y = luaL_checkint(L, 3);
 	unsigned char c[4];
-	try
-	{
-		canvas->getPixel(c, x, y);
-	}
-	catch (love::Exception & e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+
+	EXCEPT_GUARD(canvas->getPixel(c, x, y);)
+
 	lua_pushnumber(L, c[0]);
 	lua_pushnumber(L, c[1]);
 	lua_pushnumber(L, c[2]);

File src/modules/graphics/opengl/wrap_Font.cpp

 {
 	Font *t = luax_checkfont(L, 1);
 	const char *str = luaL_checkstring(L, 2);
-	try
-	{
-		lua_pushinteger(L, t->getWidth(str));
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+
+	EXCEPT_GUARD(lua_pushinteger(L, t->getWidth(str));)
 	return 1;
 }
 
 	const char *str = luaL_checkstring(L, 2);
 	float wrap = (float) luaL_checknumber(L, 3);
 	int max_width = 0, numlines = 0;
-	try
-	{
+
+	EXCEPT_GUARD(
 		std::vector<std::string> lines = t->getWrap(str, wrap, &max_width);
 		numlines = lines.size();
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+	)
+
 	lua_pushinteger(L, max_width);
 	lua_pushinteger(L, numlines);
 	return 2;
 
 	f.anisotropy = (float) luaL_optnumber(L, 4, 1.0);
 
-	try
-	{
-		t->setFilter(f);
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
-
+	EXCEPT_GUARD(t->setFilter(f);)
 	return 0;
 }
 
 	Font *t = luax_checkfont(L, 1);
 	bool hasglyph = false;
 
-	try
-	{
+	EXCEPT_GUARD(
 		if (lua_type(L, 2) == LUA_TSTRING)
 			hasglyph = t->hasGlyph(luax_checkstring(L, 2));
 		else
 			hasglyph = t->hasGlyph((uint32) luaL_checknumber(L, 2));
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	)
 
 	luax_pushboolean(L, hasglyph);
 	return 1;

File src/modules/graphics/opengl/wrap_Geometry.cpp

 int w_Geometry_getVertex(lua_State *L)
 {
 	Geometry *geom = luax_checkgeometry(L, 1);
-	size_t i = size_t(luaL_checkint(L, 2));
-	try
-	{
+	size_t i = size_t(luaL_checkinteger(L, 2));
+
+	EXCEPT_GUARD(
 		const vertex &v = geom->getVertex(i-1);
 		lua_pushnumber(L, v.x);
 		lua_pushnumber(L, v.y);
 		lua_pushnumber(L, v.g);
 		lua_pushnumber(L, v.b);
 		lua_pushnumber(L, v.a);
-	}
-	catch (Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+	)
 
 	return 8;
 }
 		v.a = luaL_optinteger(L, 10, 255);
 	}
 
-	try
-	{
-		geom->setVertex(i-1, v);
-	}
-	catch (Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+	EXCEPT_GUARD(geom->setVertex(i-1, v);)
 
 	if (v.r != 255 || v.g != 255 || v.b != 255 || v.a != 255)
 		geom->setVertexColors(true);
 			vertexmap.push_back(luaL_checkinteger(L, i + 2) - 1);
 	}
 
-	try
-	{
-		g->setElementArray(&vertexmap[0], vertexmap.size());
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(g->setElementArray(&vertexmap[0], vertexmap.size());)
 	return 0;
 }
 

File src/modules/graphics/opengl/wrap_Graphics.cpp

 	else
 		data = luax_checktype<love::image::ImageData>(L, 1, "ImageData", IMAGE_IMAGE_DATA_T);
 
+	if (!data && !data)
+		return luaL_error(L, "Error creating image.");
+
 	// Create the image.
 	Image *image = 0;
-	try
-	{
+	EXCEPT_GUARD(
 		if (cdata)
 			image = instance->newImage(cdata);
 		else if (data)
 			image = instance->newImage(data);
-		else
-			throw love::Exception("Error creating image.");
-	}
-	catch(love::Exception &e)
-	{
-		luaL_error(L, e.what());
-	}
+	)
 
 	if (image == 0)
 		return luaL_error(L, "Could not load image.");
 
-
 	// Push the type.
 	luax_pushtype(L, "Image", GRAPHICS_IMAGE_T, image);
-
 	return 1;
 }
 
 	}
 
 	Geometry *geom = 0;
-	try
-	{
-		geom = instance->newGeometry(vertices, vertexmap, mode);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(geom = instance->newGeometry(vertices, vertexmap, mode);)
 
 	if (geom == 0)
 		return luaL_error(L, "Could not create geometry.");
 
 	// Note: This should be changed to luax_pushtype if the new Geometry is ever
 	// expected to be pushed to Lua from another C++ function!
+	// We're only using rawnewtype instead of pushtype for performance.
 	luax_rawnewtype(L, "Geometry", GRAPHICS_GEOMETRY_T, geom);
 	return 1;
 }
 
 	// Note: This should be changed to luax_pushtype if the new Geometry is ever
 	// expected to be pushed to Lua from another C++ function!
+	// We're only using rawnewtype instead of pushtype for performance.
 	luax_rawnewtype(L, "Geometry", GRAPHICS_GEOMETRY_T, quad);
 	return 1;
 }
 
 	love::font::Rasterizer *rasterizer = luax_checktype<love::font::Rasterizer>(L, 1, "Rasterizer", FONT_RASTERIZER_T);
 
-	Font *font = NULL;
-	try
-	{
-		// Create the font.
-		font = instance->newFont(rasterizer, instance->getDefaultFilter());
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+	Font *font = 0;
+	EXCEPT_GUARD(font = instance->newFont(rasterizer, instance->getDefaultFilter());)
 
 	if (font == 0)
 		return luaL_error(L, "Could not load font.");
 
 	// Push the type.
 	luax_pushtype(L, "Font", GRAPHICS_FONT_T, font);
-
 	return 1;
 }
 
 		if (!SpriteBatch::getConstant(usagestr, usage))
 			return luaL_error(L, "Invalid SpriteBatch usage hint: %s", usagestr);
 	}
-	SpriteBatch *t = NULL;
-	try
-	{
-		t = instance->newSpriteBatch(image, size, usage);
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+
+	SpriteBatch *t = 0;
+	EXCEPT_GUARD(t = instance->newSpriteBatch(image, size, usage);)
+
 	luax_pushtype(L, "SpriteBatch", GRAPHICS_SPRITE_BATCH_T, t);
 	return 1;
 }
 	ParticleSystem *t = 0;
 	if (size < 1.0 || size > LOVE_UINT32_MAX)
 		return luaL_error(L, "Invalid ParticleSystem size");	
-	try
-	{
-		t = instance->newParticleSystem(image, size);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+
+	EXCEPT_GUARD(t = instance->newParticleSystem(image, size);)
+
 	luax_pushtype(L, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T, t);
 	return 1;
 }
 	if (!Canvas::getConstant(str, texture_type))
 		return luaL_error(L, "Invalid canvas type: %s", str);
 
-	Canvas *canvas = NULL;
-	try
-	{
-		canvas = instance->newCanvas(width, height, texture_type);
-	}
-	catch(Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+	Canvas *canvas = 0;
+	EXCEPT_GUARD(canvas = instance->newCanvas(width, height, texture_type);)
 
-	if (NULL == canvas)
+	if (canvas == 0)
 		return luaL_error(L, "Canvas not created, but no error thrown. I don't even...");
 
 	luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, canvas);
 		}
 	}
 
+	bool should_error = false;
 	try
 	{
 		Shader *shader = instance->newShader(sources);
 		luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
 	}
-	catch (const love::Exception &e)
+	catch (love::Exception &e)
 	{
-		// memory is freed in Graphics::newShader
 		luax_getfunction(L, "graphics", "_transformGLSLErrorMessages");
 		lua_pushstring(L, e.what());
+
+		// Function pushes the new error string onto the stack.
 		lua_pcall(L, 1, 1, 0);
-		const char *err = lua_tostring(L, -1);
-		return luaL_error(L, "%s", err);
+		should_error = true;
 	}
 
+	if (should_error)
+		return lua_error(L);
+
 	return 1;
 }
 
 	if (!Graphics::getConstant(str, mode))
 		return luaL_error(L, "Invalid blend mode: %s", str);
 
-	try
-	{
-		instance->setBlendMode(mode);
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+	EXCEPT_GUARD(instance->setBlendMode(mode);)
 	return 0;
 }
 
 int w_getBlendMode(lua_State *L)
 {
-	try
-	{
-		Graphics::BlendMode mode = instance->getBlendMode();
-		const char *str;
-		if (!Graphics::getConstant(mode, str))
-			return luaL_error(L, "Unknown blend mode");
-		lua_pushstring(L, str);
-		return 1;
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	const char *str;
+	Graphics::BlendMode mode;
+
+	EXCEPT_GUARD(mode = instance->getBlendMode();)
+
+	if (!Graphics::getConstant(mode, str))
+		return luaL_error(L, "Unknown blend mode");
+
+	lua_pushstring(L, str);
+	return 1;
 }
 
 int w_setDefaultFilter(lua_State *L)
 	love::image::Image *image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
 	bool copyAlpha = luax_optboolean(L, 1, false);
 	love::image::ImageData *i = 0;
-	try
-	{
-		i = instance->newScreenshot(image, copyAlpha);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+
+	EXCEPT_GUARD(i = instance->newScreenshot(image, copyAlpha);)
+
 	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, i);
 	return 1;
 }
 			attachments.push_back(luax_checkcanvas(L, i));
 	}
 
-	try
-	{
+	EXCEPT_GUARD(
 		if (attachments.size() > 0)
 			canvas->startGrab(attachments);
 		else
 			canvas->startGrab();
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	)
 
 	return 0;
 }
 	if (!Graphics::getConstant(str, infotype))
 		return luaL_error(L, "Invalid renderer info type: %s", str);
 
-	try
-	{
-		luax_pushstring(L, instance->getRendererInfo(infotype));
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
-	
+	EXCEPT_GUARD(luax_pushstring(L, instance->getRendererInfo(infotype));)
 	return 1;
 }
 
 	float oy = (float)luaL_optnumber(L, 8, 0.0f);
 	float kx = (float)luaL_optnumber(L, 9, 0.0f);
 	float ky = (float)luaL_optnumber(L, 10, 0.0f);
-	try
-	{
-		instance->print(str, x, y, angle, sx, sy, ox, oy, kx,ky);
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+
+	EXCEPT_GUARD(instance->print(str, x, y, angle, sx, sy, ox, oy, kx,ky);)
 	return 0;
 }
 
 		ky = (float) luaL_optnumber(L, 12, 0.0f);
 	}
 
-	try
-	{
-		instance->printf(str, x, y, wrap, align, angle, sx, sy, ox, oy, kx, ky);
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(instance->printf(str, x, y, wrap, align, angle, sx, sy, ox, oy, kx, ky);)
 	return 0;
 }
 
 
 int w_push(lua_State *L)
 {
-	try
-	{
-		instance->push();
-	}
-	catch(love::Exception e)
-	{
-		return luaL_error(L, e.what());
-	}
+	EXCEPT_GUARD(instance->push();)
 	return 0;
 }
 
 int w_pop(lua_State *L)
 {
-	try
-	{
-		instance->pop();
-	}
-	catch(love::Exception e)
-	{
-		return luaL_error(L, e.what());
-	}
+	EXCEPT_GUARD(instance->pop();)
 	return 0;
 }
 
 {
 	if (instance == 0)
 	{
-		try
-		{
-			instance = new Graphics();
-		}
-		catch (love::Exception &e)
-		{
-			return luaL_error(L, e.what());
-		}
+		EXCEPT_GUARD(instance = new Graphics();)
 	}
 	else
 		instance->retain();

File src/modules/graphics/opengl/wrap_Image.cpp

 
 	f.anisotropy = (float) luaL_optnumber(L, 4, 1.0);
 
-	try
-	{
-		t->setFilter(f);
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
-
+	EXCEPT_GUARD(t->setFilter(f);)
 	return 0;
 }
 
 			return luaL_error(L, "Invalid filter mode: %s", mipmapstr);
 	}
 
-	try
-	{
-		t->setFilter(f);
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(t->setFilter(f);)
 
 	float sharpness = luaL_optnumber(L, 3, 0);
+	t->setMipmapSharpness(sharpness);
 
-	t->setMipmapSharpness(sharpness);
-	
 	return 0;
 }
 
 		lua_pushnil(L); // only return a mipmap filter if mipmapping is enabled
 
 	lua_pushnumber(L, t->getMipmapSharpness());
-
 	return 2;
 }
 
 int w_Image_refresh(lua_State *L)
 {
 	Image *i = luax_checkimage(L, 1);
-	try
-	{
-		i->refresh();
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(i->refresh();)
 	return 0;
 }
 

File src/modules/graphics/opengl/wrap_ParticleSystem.cpp

 	lua_Number arg1 = luaL_checknumber(L, 2);
 	if (arg1 < 1.0 || arg1 > ParticleSystem::MAX_PARTICLES)
 		return luaL_error(L, "Invalid buffer size");
-	try
-	{
-		t->setBufferSize((uint32) arg1);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+
+	EXCEPT_GUARD(t->setBufferSize((uint32) arg1);)
 	return 0;
 }
 
 {
 	ParticleSystem *t = luax_checkparticlesystem(L, 1);
 	int arg1 = luaL_checkint(L, 2);
-	try
-	{
-		t->setEmissionRate(arg1);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(t->setEmissionRate(arg1);)
 	return 0;
 }
 

File src/modules/graphics/opengl/wrap_Shader.cpp

 	if (!values)
 		return luaL_error(L, "Error in arguments.");
 
+	bool should_error = false;
 	try
 	{
 		shader->sendInt(name, dimension, values, count);
 	}
 	catch (love::Exception &e)
 	{
-		delete[] values;
-		return luaL_error(L, "%s", e.what());
+		should_error = true;
+		lua_pushstring(L, e.what());
 	}
 
 	delete[] values;
 
+	if (should_error)
+		return lua_error(L);
+
 	return 0;
 }
 
 	if (!values)
 		return luaL_error(L, "Error in arguments.");
 
+	bool should_error = false;
 	try
 	{
 		shader->sendFloat(name, dimension, values, count);
 	}
 	catch (love::Exception &e)
 	{
-		delete[] values;
-		return luaL_error(L, "%s", e.what());
+		should_error = true;
+		lua_pushstring(L, e.what());
 	}
 
 	delete[] values;
 
+	if (should_error)
+		return lua_error(L);
+
 	return 0;
 }
 
 		lua_pop(L, 1 + dimension);
 	}
 
+	bool should_error = false;
+
 	try
 	{
 		shader->sendMatrix(name, dimension, values, count);
 	}
 	catch(love::Exception &e)
 	{
-		delete[] values;
-		return luaL_error(L, "%s", e.what());
+		should_error = true;
+		lua_pushstring(L, e.what());
 	}
 
 	delete[] values;
+
+	if (should_error)
+		return lua_error(L);
+
 	return 0;
 }
 
 	const char *name = luaL_checkstring(L, 2);
 	Image *img = luax_checkimage(L, 3);
 
-	try
-	{
-		shader->sendImage(name, *img);
-	}
-	catch(love::Exception &e)
-	{
-		luaL_error(L, "%s", e.what());
-	}
-
+	EXCEPT_GUARD(shader->sendImage(name, *img);)
 	return 0;
 }
 
 	const char *name = luaL_checkstring(L, 2);
 	Canvas *canvas = luax_checkcanvas(L, 3);
 
-	try
-	{
-		shader->sendCanvas(name, *canvas);
-	}
-	catch(love::Exception &e)
-	{
-		luaL_error(L, "%s", e.what());
-	}
-
+	EXCEPT_GUARD(shader->sendCanvas(name, *canvas);)
 	return 0;
 }
 

File src/modules/graphics/opengl/wrap_SpriteBatch.cpp

 	float ky = (float) luaL_optnumber(L, startidx + 8, 0.0);
 
 	int id = 0;
-	try
-	{
+	EXCEPT_GUARD(
 		if (geom)
 			id = t->addg(geom, x, y, a, sx, sy, ox, oy, kx, ky);
 		else
 			id = t->add(x, y, a, sx, sy, ox, oy, kx, ky);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	)
 
 	lua_pushinteger(L, id);
 	return 1;
 	float kx = (float) luaL_optnumber(L, startidx + 7, 0.0);
 	float ky = (float) luaL_optnumber(L, startidx + 8, 0.0);
 
-	try
-	{
+	EXCEPT_GUARD(
 		if (geom)
 			t->addg(geom, x, y, a, sx, sy, ox, oy, kx, ky, id);
 		else
 			t->add(x, y, a, sx, sy, ox, oy, kx, ky, id);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	)
 
 	return 0;
 }
 int w_SpriteBatch_bind(lua_State *L)
 {
 	SpriteBatch *t = luax_checkspritebatch(L, 1);
-	try
-	{
-		t->lock();
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(t->lock();)
 	return 0;
 }
 
 {
 	SpriteBatch *t = luax_checkspritebatch(L, 1);
 	int size = luaL_checkint(L, 2);
-	try
-	{
-		t->setBufferSize(size);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(t->setBufferSize(size);)
 	return 0;
 }
 

File src/modules/image/wrap_CompressedData.cpp

 	CompressedData *t = luax_checkcompresseddata(L, 1);
 	int miplevel = luaL_optinteger(L, 2, 1);
 	int width = 0;
-	try
-	{
-		width = t->getWidth(miplevel >= 1 ? miplevel - 1 : 0);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+
+	EXCEPT_GUARD(width = t->getWidth(miplevel >= 1 ? miplevel - 1 : 0);)
+
 	lua_pushinteger(L, width);
 	return 1;
 }
 	CompressedData *t = luax_checkcompresseddata(L, 1);
 	int miplevel = luaL_optinteger(L, 2, 1);
 	int height = 0;
-	try
-	{
-		height = t->getHeight(miplevel >= 1 ? miplevel - 1 : 0);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+
+	EXCEPT_GUARD(height = t->getHeight(miplevel >= 1 ? miplevel - 1 : 0);)
+
 	lua_pushinteger(L, height);
 	return 1;
 }
 	CompressedData *t = luax_checkcompresseddata(L, 1);
 	int miplevel = luaL_optinteger(L, 2, 1);
 	int width = 0, height = 0;
-	try
-	{
+
+	EXCEPT_GUARD(
 		width = t->getWidth(miplevel >= 1 ? miplevel - 1 : 0);
 		height = t->getHeight(miplevel >= 1 ? miplevel - 1 : 0);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	)
+
 	lua_pushinteger(L, width);
 	lua_pushinteger(L, height);
 	return 2;

File src/modules/image/wrap_Image.cpp

 			return luaL_error(L, "Invalid image size.");
 
 		ImageData *t = 0;
-		try
-		{
-			t = instance->newImageData(w, h);
-		}
-		catch(love::Exception &e)
-		{
-			return luaL_error(L, "%s", e.what());
-		}
+		EXCEPT_GUARD(t = instance->newImageData(w, h);)
+
 		luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t);
 		return 1;
 	}
 	love::filesystem::FileData *data = luax_checktype<love::filesystem::FileData>(L, 1, "FileData", FILESYSTEM_FILE_DATA_T);
 
 	ImageData *t = 0;
-	try
-	{
-		t = instance->newImageData(data);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(t = instance->newImageData(data);)
 
 	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t);
-
 	return 1;
 }
 
 	love::filesystem::FileData *data = luax_checktype<love::filesystem::FileData>(L, 1, "FileData", FILESYSTEM_FILE_DATA_T);
 
 	CompressedData *t = 0;
-	try
-	{
-		t = instance->newCompressedData(data);
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(t = instance->newCompressedData(data);)
 
 	luax_pushtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, t);
-
 	return 1;
 }
 
 	love::filesystem::FileData *data = luax_checktype<love::filesystem::FileData>(L, 1, "FileData", FILESYSTEM_FILE_DATA_T);
 
 	bool compressed = false;
-	try
-	{
-		compressed = instance->isCompressed(data);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(compressed = instance->isCompressed(data);)
+
 	luax_pushboolean(L, compressed);
 	return 1;
 }
 {
 	if (instance == 0)
 	{
-		try
-		{
-			instance = new love::image::magpie::Image();
-		}
-		catch(Exception &e)
-		{
-			return luaL_error(L, "%s", e.what());
-		}
+		EXCEPT_GUARD(instance = new love::image::magpie::Image();)
 	}
 	else
 		instance->retain();

File src/modules/image/wrap_ImageData.cpp

 	int x = luaL_checkint(L, 2);
 	int y = luaL_checkint(L, 3);
 	pixel c;
-	try
-	{
-		c = t->getPixel(x, y);
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+
+	EXCEPT_GUARD(c = t->getPixel(x, y);)
+
 	lua_pushnumber(L, c.r);
 	lua_pushnumber(L, c.g);
 	lua_pushnumber(L, c.b);
 		c.a = (unsigned char)luaL_optinteger(L, 7, 255);
 	}
 
-	try
-	{
-		t->setPixel(x, y, c);
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(t->setPixel(x, y, c);)
 	return 0;
 }
 
 			return luaL_error(L, "Invalid image format '%s'.", fmt);
 	}
 
-	try
-	{
-		t->encode(file, format);
-	}
-	catch(love::Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+	EXCEPT_GUARD(t->encode(file, format);)
 	return 0;
 }
 

File src/modules/joystick/sdl/wrap_JoystickModule.cpp

 	// Only accept a GUID string. We don't accept a Joystick object because
 	// the gamepad mapping applies to all joysticks with the same GUID (e.g. all
 	// Xbox 360 controllers on the system), rather than individual objects.
-	std::string guid = luax_checkstring(L, 1);
+	const char *guid = luaL_checkstring(L, 1);
 
 	const char *gpbindstr = luaL_checkstring(L, 2);
 	Joystick::GamepadInput gpinput;
 	}
 
 	bool success = false;
-	try
-	{
-		success = instance->setGamepadMapping(guid, gpinput, jinput);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(success = instance->setGamepadMapping(guid, gpinput, jinput);)
+
 	luax_pushboolean(L, success);
 	return 1;
 }
 	Joystick::JoystickInput jinput;
 	jinput.type = Joystick::INPUT_TYPE_MAX_ENUM;
 
-	try
-	{
-		jinput = instance->getGamepadMapping(guid, gpinput);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(jinput = instance->getGamepadMapping(guid, gpinput);)
 
 	if (jinput.type == Joystick::INPUT_TYPE_MAX_ENUM)
 		return 0;
 {
 	if (instance == 0)
 	{
-		try
-		{
-			instance = new JoystickModule();
-		}
-		catch (Exception &e)
-		{
-			return luaL_error(L, e.what());
-		}
+		EXCEPT_GUARD(instance = new JoystickModule();)
 	}
 	else
 		instance->retain();
 
-
 	WrappedModule w;
 	w.module = instance;
 	w.name = "joystick";

File src/modules/keyboard/wrap_Keyboard.cpp

 {
 	if (instance == 0)
 	{
-		try
-		{
-			instance = new love::keyboard::sdl::Keyboard();
-		}
-		catch(Exception &e)
-		{
-			return luaL_error(L, e.what());
-		}
+		EXCEPT_GUARD(instance = new love::keyboard::sdl::Keyboard();)
 	}
 	else
 		instance->retain();

File src/modules/math/wrap_BezierCurve.cpp

 	if (idx > 0) // 1-indexing
 		idx--;
 
-	try
-	{
+	EXCEPT_GUARD(
 		Vector v = curve->getControlPoint(idx);
 		lua_pushnumber(L, v.x);
 		lua_pushnumber(L, v.y);
-	}
-	catch (Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+	)
 
 	return 2;
 }
 	if (idx > 0) // 1-indexing
 		idx--;
 
-	try
-	{
-		curve->setControlPoint(idx, Vector(vx,vy));
-	}
-	catch (Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
-
+	EXCEPT_GUARD(curve->setControlPoint(idx, Vector(vx,vy));)
 	return 0;
 }
 
 	if (idx > 0) // 1-indexing
 		idx--;
 
-	try
-	{
-		curve->insertControlPoint(Vector(vx,vy), idx);
-	}
-	catch (Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
-
+	EXCEPT_GUARD(curve->insertControlPoint(Vector(vx,vy), idx);)
 	return 0;
 }
 
 	BezierCurve *curve = luax_checkbeziercurve(L, 1);
 	double t = luaL_checknumber(L, 2);
 
-	try
-	{
+	EXCEPT_GUARD(
 		Vector v = curve->eval(t);
 		lua_pushnumber(L, v.x);
 		lua_pushnumber(L, v.y);
-	}
-	catch (Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+	)
 
 	return 2;
 
 	int accuracy = luaL_optinteger(L, 2, 5);
 
 	std::vector<Vector> points;
-	try
-	{
-		points = curve->render(accuracy);
-	}
-	catch (Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+	EXCEPT_GUARD(points = curve->render(accuracy);)
 
 	lua_createtable(L, points.size()*2, 0);
 	for (size_t i = 0; i < points.size(); ++i)

File src/modules/math/wrap_Math.cpp

 
 int w_setRandomState(lua_State *L)
 {
-	try
-	{
-		Math::instance.setRandomState(luax_checkrandomstate(L, 1));
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(Math::instance.setRandomState(luax_checkrandomstate(L, 1));)
 	return 0;
 }
 
 
 	if (lua_gettop(L) > 0)
 	{
+		bool should_error = false;
+
 		try
 		{
 			t->setState(s);
 		catch (love::Exception &e)
 		{
 			t->release();
-			return luaL_error(L, "%s", e.what());
+			should_error = true;
+			lua_pushstring(L, e.what());
 		}
+
+		if (should_error)
+			return lua_error(L);
 	}
 
 	luax_pushtype(L, "RandomGenerator", MATH_RANDOM_GENERATOR_T, t);
 		return luaL_error(L, "Need at least 3 vertices to triangulate");
 
 	std::vector<Triangle> triangles;
-	try
-	{
+
+	EXCEPT_GUARD(
 		if (vertices.size() == 3)
 			triangles.push_back(Triangle(vertices[0], vertices[1], vertices[2]));
 		else
 			triangles = Math::instance.triangulate(vertices);
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, e.what());
-	}
+	)
 
 	lua_createtable(L, triangles.size(), 0);
 	for (size_t i = 0; i < triangles.size(); ++i)

File src/modules/math/wrap_RandomGenerator.cpp

 int w_RandomGenerator_setState(lua_State *L)
 {
 	RandomGenerator *rng = luax_checkrandomgenerator(L, 1);
-	try
-	{
-		rng->setState(luax_checkrandomstate(L, 2));
-	}
-	catch (love::Exception &e)
-	{
-		return luaL_error(L, "%s", e.what());
-	}
+	EXCEPT_GUARD(rng->setState(luax_checkrandomstate(L, 2));)
 	return 0;
 }
 

File src/modules/mouse/wrap_Mouse.cpp

 		if (!Cursor::getConstant(str, systemCursor))
 			return luaL_error(L, "Invalid cursor type %s", str);
 
-		try
-		{
-			cursor = instance->newCursor(systemCursor);
-		}
-		catch (love::Exception &e)
-		{
-			return luaL_error(L, "%s", e.what());
-		}
+		EXCEPT_GUARD(cursor = instance->newCursor(systemCursor);)
 	}
 	else
 	{
 		int hotx = luaL_optint(L, 2, 0);
 		int hoty = luaL_optint(L, 3, 0);
 
-		try
-		{
-			cursor = instance->newCursor(data, hotx, hoty);
-		}
-		catch (love::Exception &e)
-		{
-			return luaL_error(L, "%s", e.what());
-		}
+		EXCEPT_GUARD(cursor = instance->newCursor(data, hotx, hoty);)
 	}
 
 	luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor);
 {
 	if (instance == 0)
 	{
-		try
-		{
-			instance = new love::mouse::sdl::Mouse();
-		}
-		catch(Exception &e)
-		{
-			return luaL_error(L, e.what());
-		}
+		EXCEPT_GUARD(instance = new love::mouse::sdl::Mouse();)
 	}
 	else
 		instance->retain();

File src/modules/physics/box2d/Physics.cpp

 	b2DistanceOutput o;
 	b2SimplexCache c;
 	c.count = 0;
-	try
-	{
+
+	EXCEPT_GUARD(
 		pA.Set(fixtureA->fixture->GetShape(), 0);
 		pB.Set(fixtureB->fixture->GetShape(), 0);
 		i.proxyA = pA;
 		i.transformB = fixtureB->fixture->GetBody()->GetTransform();
 		i.useRadii = true;
 		b2Distance(&o, &c, &i);