From 7a513e1434a0b5ed5f6cb81ef0a900f4822bc764 Mon Sep 17 00:00:00 2001 From: vrld Date: Sat, 12 Nov 2011 21:11:41 +0100 Subject: [PATCH] Make love::Exception safe(r). Now allows exceptions of arbitrary length. Now allows catching a non-reference, i.e. catch(love::Exception e). --- src/common/Exception.cpp | 41 +++++++++++++------ src/common/Exception.h | 16 +++----- src/modules/graphics/opengl/Font.cpp | 4 +- src/modules/graphics/opengl/wrap_Graphics.cpp | 2 +- 4 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/common/Exception.cpp b/src/common/Exception.cpp index ca804345a..fc5bd222f 100644 --- a/src/common/Exception.cpp +++ b/src/common/Exception.cpp @@ -20,26 +20,43 @@ #include "Exception.h" #include +#include +using namespace std; namespace love { Exception::Exception(const char * fmt, ...) { va_list args; - va_start(args, fmt); - vsnprintf(buffer, BUFFER_SIZE, fmt, args); - va_end(args); - } + int size_buffer = 256, size_out; + char * buffer; + while (true) { + buffer = new char[size_buffer]; + memset(buffer, 0, size_buffer); - Exception::Exception(int unparsed, const char * str) - { - LOVE_UNUSED(unparsed); - strncpy(buffer, str, BUFFER_SIZE); - } + va_start(args, fmt); + size_out = vsnprintf(buffer, size_buffer, fmt, args); + va_end(args); - const char * Exception::what() const throw() - { - return (const char *)buffer; + // see http://perfec.to/vsnprintf/pasprintf.c + // if size_out ... + // == -1 --> output was truncated + // == size_buffer --> output was truncated + // == size_buffer-1 --> ambiguous, /may/ have been truncated + // > size_buffer --> output was truncated, and size_out + // bytes would have been written + if (size_out == size_buffer || size_out == -1 || size_out == size_buffer-1) + size_buffer *= 2; + else if (size_out > size_buffer) + size_buffer = size_out + 2; // to avoid the ambiguous case + else + break; + + delete[] buffer; + } + message = std::string(buffer); + cerr << message << endl; + delete[] buffer; } } diff --git a/src/common/Exception.h b/src/common/Exception.h index 337ec9d36..c02a00eae 100644 --- a/src/common/Exception.h +++ b/src/common/Exception.h @@ -25,6 +25,7 @@ #include // vararg #include // vsnprintf #include // strncpy +#include namespace love { @@ -35,15 +36,7 @@ namespace love { private: - /** - * The vsnprintf operates on a buffer this large. - **/ - static const int BUFFER_SIZE = 256; - - /** - * The buffer for vsnprintf. - **/ - char buffer[BUFFER_SIZE]; + std::string message; public: @@ -55,13 +48,14 @@ namespace love * @param fmt The format string (see printf). **/ Exception(const char * fmt, ...); - Exception(int unparsed, const char * str); + virtual ~Exception() throw() {} /** * Returns a string containing reason for the exception. * @return A description of the exception. **/ - virtual const char * what() const throw(); + inline virtual const char * what() const throw() + { return message.c_str(); } }; // class diff --git a/src/modules/graphics/opengl/Font.cpp b/src/modules/graphics/opengl/Font.cpp index 10046413e..139124cac 100644 --- a/src/modules/graphics/opengl/Font.cpp +++ b/src/modules/graphics/opengl/Font.cpp @@ -177,7 +177,7 @@ namespace opengl catch (utf8::exception & e) { glPopMatrix(); - throw love::Exception(1, e.what()); + throw love::Exception("%s", e.what()); } glPopMatrix(); } @@ -212,7 +212,7 @@ namespace opengl } catch (utf8::exception & e) { - throw love::Exception(1, e.what()); + throw love::Exception("%s", e.what()); } return temp; diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index 883379878..436b492ec 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -388,7 +388,7 @@ namespace opengl const char* code = lua_tostring(L, -1); PixelEffect * effect = instance->newPixelEffect(code); luax_newtype(L, "PixelEffect", GRAPHICS_PIXELEFFECT_T, (void*)effect); - } catch (love::Exception& e) { + } catch (const love::Exception& e) { // memory is freed in Graphics::newPixelEffect luax_getfunction(L, "graphics", "_transformGLSLErrorMessages"); lua_pushstring(L, e.what());