summaryrefslogtreecommitdiff
path: root/source/fitz/error.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2015-09-28 15:24:00 +0100
committerRobin Watts <robin.watts@artifex.com>2015-09-30 17:35:42 +0100
commit1f15bade3112bfdc8ddbae9c4b06047427c2367f (patch)
tree3a7b21fd984e2b16040939fbab6022e0fe7f12cd /source/fitz/error.c
parent399a04b4af991c71826ce0e6962a23b4f8fa127d (diff)
downloadmupdf-1f15bade3112bfdc8ddbae9c4b06047427c2367f.tar.xz
Bug 696115: Further fix for setjmp/longjmp.
Tor turned up an interesting section in the C spec about this. See page 275 of http://open-std.org/jtc1/sc22/wg14/www/docs/n1494.pdf regarding acceptable places for setjmp to occur. It seems that: if (setjmp(buf)) if (!setjmp(buf)) if (setjmp(buf) {==,!=,<,>} <integer constant>) etc are all valid things to do, but assignments (and subsequent testing of values) like: if ((code = setjmp(buf)) == 0) are not allowed. Further, it's not even clear that: if (a() && setjmp(buf)) is permissible. We therefore recast the macros into the form: a(); if (setjmp((buf)) == 0) which should be acceptable under the C spec. To keep try atomic, we introduce a block '{{{' around this, along with a matching close block '}}}' in the catch clause. This has the nifty extra effect of giving us a compile time error if we mismatch our try/catches.
Diffstat (limited to 'source/fitz/error.c')
-rw-r--r--source/fitz/error.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/source/fitz/error.c b/source/fitz/error.c
index 414b993f..6d0b831d 100644
--- a/source/fitz/error.c
+++ b/source/fitz/error.c
@@ -86,7 +86,8 @@ static void throw(fz_error_context *ex)
{
if (ex->top >= 0)
{
- fz_longjmp(ex->stack[ex->top].buffer, ex->stack[ex->top].code + 2);
+ ex->stack[ex->top].code += 2;
+ fz_longjmp(ex->stack[ex->top].buffer, ex->stack[ex->top].code);
}
else
{
@@ -101,23 +102,25 @@ static void throw(fz_error_context *ex)
}
}
-int fz_push_try(fz_error_context *ex)
+void fz_push_try(fz_error_context *ex)
{
- assert(ex);
ex->top++;
/* Normal case, get out of here quick */
if (ex->top < nelem(ex->stack)-1)
- return 1; /* We exit here, and the setjmp sets the code to 0 */
+ {
+ ex->stack[ex->top].code = 0;
+ return;
+ }
/* We reserve the top slot on the exception stack purely to cope with
* the case when we overflow. If we DO hit this, then we 'throw'
- * immediately - returning 0 stops the setjmp happening and takes us
- * direct to the always/catch clauses. */
- assert(ex->top == nelem(ex->stack)-1);
+ * immediately. */
+ assert(ex->top == nelem(ex->stack));
+ ex->top--;
+ ex->errcode = FZ_ERROR_GENERIC;
strcpy(ex->message, "exception stack overflow!");
- ex->stack[ex->top].code = 2;
fprintf(stderr, "error: %s\n", ex->message);
LOGE("error: %s\n", ex->message);
- return 0;
+ throw(ex);
}
int fz_caught(fz_context *ctx)