summaryrefslogtreecommitdiff
path: root/source/fitz/error.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-03-15 18:51:15 +0000
committerRobin Watts <robin.watts@artifex.com>2016-03-15 19:28:12 +0000
commite31c26d7a0fad2cd935d597d1dabd38f7d8941bc (patch)
treeac0ffcedd9a664e411a2af8d00a166f094ac6eaa /source/fitz/error.c
parent66c2ddc228960b1c1d365bff3255c9c992acf757 (diff)
downloadmupdf-e31c26d7a0fad2cd935d597d1dabd38f7d8941bc.tar.xz
Tweak fz_try/catch to fix overflow case.
In the current code, when we hit the fz_try(), we check to see if we are about to overflow the exception stack. If we are, we throw. This does NOT throw to the fz_catch following the try, but rather to the enclosing fz_always/fz_catch blocks. This can cause leaks, as it's very hard to code correctly. It would be a far nicer behaviour to have a failure in fz_try() cause us to throw to the immediately following fz_always/fz_catch. This commit achieves that.
Diffstat (limited to 'source/fitz/error.c')
-rw-r--r--source/fitz/error.c41
1 files changed, 36 insertions, 5 deletions
diff --git a/source/fitz/error.c b/source/fitz/error.c
index a99a3f83..f3c5973d 100644
--- a/source/fitz/error.c
+++ b/source/fitz/error.c
@@ -100,16 +100,47 @@ FZ_NORETURN static void throw(fz_context *ctx)
}
}
-fz_error_stack_slot *fz_push_try(fz_context *ctx)
+/* Only called when we hit the bottom of the exception stack.
+ * Do the same as fz_throw, but don't actually throw. */
+static int fz_fake_throw(fz_context *ctx, int code, const char *fmt, ...)
+{
+ va_list args;
+ ctx->error->errcode = code;
+ va_start(args, fmt);
+ vsnprintf(ctx->error->message, sizeof ctx->error->message, fmt, args);
+ va_end(args);
+
+ if (code != FZ_ERROR_ABORT)
+ {
+ fz_flush_warnings(ctx);
+ fprintf(stderr, "error: %s\n", ctx->error->message);
+ LOGE("error: %s\n", ctx->error->message);
+#ifdef USE_OUTPUT_DEBUG_STRING
+ OutputDebugStringA("error: ");
+ OutputDebugStringA(ctx->error->message);
+ OutputDebugStringA("\n");
+#endif
+ }
+
+ /* We need to arrive in the always/catch block as if throw
+ * had taken place. */
+ ctx->error->top++;
+ ctx->error->top->code = 2;
+ return 0;
+}
+
+int fz_push_try(fz_context *ctx)
{
/* If we would overflow the exception stack, throw an exception instead
- * of entering the try block. */
- if (ctx->error->top + 1 >= ctx->error->stack + nelem(ctx->error->stack))
- fz_throw(ctx, FZ_ERROR_GENERIC, "exception stack overflow!");
+ * of entering the try block. We assume that we always have room for
+ * 1 extra level on the stack here - i.e. we throw the error on us
+ * starting to use the last level. */
+ if (ctx->error->top + 2 >= ctx->error->stack + nelem(ctx->error->stack))
+ return fz_fake_throw(ctx, FZ_ERROR_GENERIC, "exception stack overflow!");
ctx->error->top++;
ctx->error->top->code = 0;
- return ctx->error->top;
+ return 1;
}
int fz_caught(fz_context *ctx)