diff options
-rw-r--r-- | fitz/fitz.h | 4 | ||||
-rw-r--r-- | pdf/pdf_function.c | 27 |
2 files changed, 24 insertions, 7 deletions
diff --git a/fitz/fitz.h b/fitz/fitz.h index 594bc4e9..d80204f0 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -15,7 +15,7 @@ #include <assert.h> #include <errno.h> #include <limits.h> /* INT_MAX & co */ -#include <float.h> /* FLT_EPSILON */ +#include <float.h> /* FLT_EPSILON, FLT_MAX & co */ #include <fcntl.h> /* O_RDONLY & co */ #include <setjmp.h> @@ -46,6 +46,7 @@ #define MIN(a,b) ( (a) < (b) ? (a) : (b) ) #define MAX(a,b) ( (a) > (b) ? (a) : (b) ) #define CLAMP(x,a,b) ( (x) > (b) ? (b) : ( (x) < (a) ? (a) : (x) ) ) +#define DIV_BY_ZERO(a, b, min, max) (((a) < 0) ^ ((b) < 0) ? (min) : (max)) /* * Some differences in libc can be smoothed over @@ -62,6 +63,7 @@ int gettimeofday(struct timeval *tv, struct timezone *tz); #define snprintf _snprintf +#define isnan _isnan #else /* Unix or close enough */ diff --git a/pdf/pdf_function.c b/pdf/pdf_function.c index 932d4c77..a6941ca1 100644 --- a/pdf/pdf_function.c +++ b/pdf/pdf_function.c @@ -203,7 +203,13 @@ ps_push_real(ps_stack *st, float n) if (!ps_overflow(st, 1)) { st->stack[st->sp].type = PS_REAL; - st->stack[st->sp].u.f = n; + if (isnan(n)) + { + /* Push 1.0, as it's a small known value that won't + cause a divide by 0. Same reason as in fz_atof. */ + n = 1.0; + } + st->stack[st->sp].u.f = CLAMP(n, -FLT_MAX, FLT_MAX); st->sp++; } } @@ -360,9 +366,9 @@ ps_run(fz_context *ctx, psobj *code, ps_stack *st, int pc) case PS_OP_BITSHIFT: i2 = ps_pop_int(st); i1 = ps_pop_int(st); - if (i2 > 0) + if (i2 > 0 && i2 < 8 * sizeof (i2)) ps_push_int(st, i1 << i2); - else if (i2 < 0) + else if (i2 < 0 && i2 > -8 * sizeof (i2)) ps_push_int(st, (int)((unsigned int)i1 >> i2)); else ps_push_int(st, i1); @@ -393,7 +399,10 @@ ps_run(fz_context *ctx, psobj *code, ps_stack *st, int pc) case PS_OP_DIV: r2 = ps_pop_real(st); r1 = ps_pop_real(st); - ps_push_real(st, r1 / r2); + if (fabsf(r2) < FLT_EPSILON) + ps_push_real(st, r1 / r2); + else + ps_push_real(st, DIV_BY_ZERO(r1, r2, -FLT_MAX, FLT_MAX)); break; case PS_OP_DUP: @@ -466,7 +475,10 @@ ps_run(fz_context *ctx, psobj *code, ps_stack *st, int pc) case PS_OP_IDIV: i2 = ps_pop_int(st); i1 = ps_pop_int(st); - ps_push_int(st, i1 / i2); + if (i2 != 0) + ps_push_int(st, i1 / i2); + else + ps_push_int(st, DIV_BY_ZERO(i1, i2, INT_MIN, INT_MAX)); break; case PS_OP_INDEX: @@ -512,7 +524,10 @@ ps_run(fz_context *ctx, psobj *code, ps_stack *st, int pc) case PS_OP_MOD: i2 = ps_pop_int(st); i1 = ps_pop_int(st); - ps_push_int(st, i1 % i2); + if (i2 != 0) + ps_push_int(st, i1 % i2); + else + ps_push_int(st, DIV_BY_ZERO(i1, i2, INT_MIN, INT_MAX)); break; case PS_OP_MUL: |