summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fitz/fitz.h4
-rw-r--r--pdf/pdf_function.c27
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: