summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebras@gmail.com>2012-02-16 01:08:05 +0100
committerRobin Watts <robin.watts@artifex.com>2012-03-12 13:27:36 +0000
commita7a180366686298fa7f7aae686152e5a759d3a89 (patch)
treebaec074baa4e89f18314c226bf3c528bbb1ef6a2 /pdf
parent5e31bc05a0299033dad386ea346c6c8503125113 (diff)
downloadmupdf-a7a180366686298fa7f7aae686152e5a759d3a89.tar.xz
Take care of boundary conditions in ps function evaluation.
Floating point numbers are now clamped, division by zero is approximated by minimum or maximum value and NaN results in 1.0.
Diffstat (limited to 'pdf')
-rw-r--r--pdf/pdf_function.c27
1 files changed, 21 insertions, 6 deletions
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: