diff options
author | Sebastian Rasmussen <sebras@gmail.com> | 2012-02-16 01:08:05 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2012-03-12 13:27:36 +0000 |
commit | a7a180366686298fa7f7aae686152e5a759d3a89 (patch) | |
tree | baec074baa4e89f18314c226bf3c528bbb1ef6a2 /pdf/pdf_function.c | |
parent | 5e31bc05a0299033dad386ea346c6c8503125113 (diff) | |
download | mupdf-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/pdf_function.c')
-rw-r--r-- | pdf/pdf_function.c | 27 |
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: |