summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2020-03-08 00:26:16 +0000
committerKen Sharp <ken.sharp@artifex.com>2020-03-08 00:26:16 +0000
commit56840269a9df474a029f12ce8e4e41bb2abea313 (patch)
tree27ea01e9d83c6b5b425a6c8dcedd9250ba20dc80
parent933a09069dea35d570694e157013f272995ca5c4 (diff)
downloadghostpdl-56840269a9df474a029f12ce8e4e41bb2abea313.tar.gz
PS interpreter some 64-bit integer fixes
Bug #702194 "cvi produces incorrect results" This was simply caused by a cast through long. However its not enough merely to change the cast, we must also check for running in CPSI mode and throw an error if the returned integer cannot be represented in a 32-bit word, for compatibility with test suites. In addition (see bug #702134) when exp throws an undefinedresult error delay setting the stack variable until after we have tested the result, so that we do not end up returning a INF on the stack, as is done in other code paths which check for NaN and INF. Thirdly; in div cater for the case of an integer divided by a real and check the result for NaN and INF (as the other cases do). This now properly throws an error and does not return NaN or INF on the stack.
-rw-r--r--psi/zarith.c8
-rw-r--r--psi/zmath.c2
-rw-r--r--psi/ztype.c13
3 files changed, 21 insertions, 2 deletions
diff --git a/psi/zarith.c b/psi/zarith.c
index fce9686e8..cb624a438 100644
--- a/psi/zarith.c
+++ b/psi/zarith.c
@@ -148,6 +148,14 @@ zdiv(i_ctx_t *i_ctx_p)
break;
case t_integer:
result = (double)op1->value.intval / op->value.realval;
+#ifdef HAVE_ISINF
+ if (isinf(result))
+ return_error(gs_error_undefinedresult);
+#endif
+#ifdef HAVE_ISNAN
+ if (isnan(result))
+ return_error(gs_error_undefinedresult);
+#endif
make_real(op1, result);
}
break;
diff --git a/psi/zmath.c b/psi/zmath.c
index d6ecae233..f6bf3a787 100644
--- a/psi/zmath.c
+++ b/psi/zmath.c
@@ -157,11 +157,11 @@ zexp(i_ctx_t *i_ctx_p)
result = 1.0; /* match Adobe; can't rely on C library */
else
result = pow(args[0], args[1]);
- make_real(op - 1, result);
#ifdef HAVE_ISINF
if (isinf((op - 1)->value.realval))
return_error(gs_error_undefinedresult);
#endif
+ make_real(op - 1, result);
pop(1);
return 0;
}
diff --git a/psi/ztype.c b/psi/ztype.c
index 94e5e032a..df334abd7 100644
--- a/psi/ztype.c
+++ b/psi/ztype.c
@@ -281,7 +281,18 @@ zcvi(i_ctx_t *i_ctx_p)
}
if (!REAL_CAN_BE_INT(fval))
return_error(gs_error_rangecheck);
- make_int(op, (long)fval); /* truncates towards 0 */
+ if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory)) {
+ if ((double)fval > (double)MAX_PS_INT32) /* (double)0x7fffffff */
+ return_error(gs_error_rangecheck);
+ else if ((double)fval < (double)MIN_PS_INT32) /* (double)(int)0x80000000 */
+ return_error(gs_error_rangecheck);
+ else {
+ make_int(op, (ps_int) fval);
+ }
+ }
+ else
+ make_int(op, (ps_int) fval);
+
return 0;
}