From 1f15bade3112bfdc8ddbae9c4b06047427c2367f Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 28 Sep 2015 15:24:00 +0100 Subject: 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) {==,!=,<,>} ) 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. --- source/fitz/error.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'source/fitz/error.c') 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) -- cgit v1.2.3