assert: Remove use of alloca() For short messages, use a stack buffer that is significantly smaller than SDL_MAX_LOG_MESSAGE. For larger messages, fall back to allocation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
diff --git a/src/SDL_assert.c b/src/SDL_assert.c
index 9c7acac..8f2e950 100644
--- a/src/SDL_assert.c
+++ b/src/SDL_assert.c
@@ -45,6 +45,8 @@
#include <emscripten.h>
#endif
+/* The size of the stack buffer to use for rendering assert messages. */
+#define SDL_MAX_ASSERT_MESSAGE_STACK 256
static SDL_assert_state SDLCALL
SDL_PromptAssertion(const SDL_assert_data *data, void *userdata);
@@ -160,30 +162,43 @@ SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
SDL_ASSERTION_ALWAYS_IGNORE, "Always Ignore" }
};
- char *message;
int selected;
+ char stack_buf[SDL_MAX_ASSERT_MESSAGE_STACK];
+ char *message = stack_buf;
+ size_t buf_len = sizeof(stack_buf);
+ size_t len;
+
(void) userdata; /* unused in default handler. */
- /* !!! FIXME: why is this using SDL_stack_alloc and not just "char message[SDL_MAX_LOG_MESSAGE];" ? */
- message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
- if (!message) {
- /* Uh oh, we're in real trouble now... */
- return SDL_ASSERTION_ABORT;
- }
- SDL_snprintf(message, SDL_MAX_LOG_MESSAGE,
- "Assertion failure at %s (%s:%d), triggered %u %s:" ENDLINE
- " '%s'",
- data->function, data->filename, data->linenum,
- data->trigger_count, (data->trigger_count == 1) ? "time" : "times",
- data->condition);
+ do {
+ /* Assume the output will fit... */
+ len = SDL_snprintf(message, buf_len,
+ "Assertion failure at %s (%s:%d), triggered %u %s:" ENDLINE " '%s'",
+ data->function, data->filename, data->linenum,
+ data->trigger_count, (data->trigger_count == 1) ? "time" : "times",
+ data->condition);
+
+ /* .. and if it didn't, allocate a bigger buffer and try again */
+ if (len >= buf_len && message == stack_buf) {
+ buf_len = SDL_MAX_LOG_MESSAGE;
+ message = (char *)SDL_malloc(buf_len);
+ if (!message) {
+ /* Uh oh, we're in real trouble now... */
+ return SDL_ASSERTION_ABORT;
+ }
+ len = 0;
+ }
+ } while (len == 0);
debug_print("\n\n%s\n\n", message);
/* let env. variable override, so unit tests won't block in a GUI. */
envr = SDL_getenv("SDL_ASSERT");
if (envr != NULL) {
- SDL_stack_free(message);
+ if (message != stack_buf) {
+ SDL_free(message);
+ }
if (SDL_strcmp(envr, "abort") == 0) {
return SDL_ASSERTION_ABORT;
@@ -301,7 +316,9 @@ SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
SDL_RestoreWindow(window);
}
- SDL_stack_free(message);
+ if (message != stack_buf) {
+ SDL_free(message);
+ }
return state;
}