[gs-cvs] rev 8313 - trunk/gs/src
ken at ghostscript.com
ken at ghostscript.com
Wed Oct 24 00:31:10 PDT 2007
Author: ken
Date: 2007-10-24 00:31:09 -0700 (Wed, 24 Oct 2007)
New Revision: 8313
Modified:
trunk/gs/src/gdevpsfx.c
trunk/gs/src/gstype1.c
trunk/gs/src/gxtype1.h
Log:
Fix (pdfwrite) : An integer arithmetic overflow while converting Type 1 CharStrings into Type 2.
DETAILS :
Bug #689106 "Wrong charpath direction in PDF"
Patch from Rolf Becker with minor improvements.
A processing of big integers was implemented in gstype1.c
while rendering a glyph, but it was not implemented
in pdfwrite while converting a Type 1 font into Type 2.
It caused an incorrect glyph outlines embedded into PDF.
This patch factors out the old processing as a new
function gs_type1_check_float and applies it in gdevpsfx.c .
The function prototype is added to gxtype1.h as it needs to be public.
The patch also improves comments in code
because now we understand better what happens in there.
For more details see comments in code.
The change to gstype1.c is algorithmically equivalent
except inserting a new check for overflow in float2fixed.
The new check may fail when the old code
renders an incorrect outline.
We have no practical cases that demonstrate it.
EXPECTED DIFFERENCES :
None.
Modified: trunk/gs/src/gdevpsfx.c
===================================================================
--- trunk/gs/src/gdevpsfx.c 2007-10-23 03:48:59 UTC (rev 8312)
+++ trunk/gs/src/gdevpsfx.c 2007-10-24 07:31:09 UTC (rev 8313)
@@ -185,6 +185,15 @@
decode_num4(lw, cip, state, encrypted);
CS_CHECK_PUSH(csp, pcis->ostack);
*++csp = int2fixed(lw);
+ if (lw != fixed2long(*csp)) {
+ /*
+ * The integer was too large to handle in fixed point.
+ * Handle this case specially.
+ */
+ code = gs_type1_check_float(&state, encrypted, &cip, csp, lw);
+ if (code < 0)
+ return code;
+ }
} else /* not possible */
return_error(gs_error_invalidfont);
continue;
Modified: trunk/gs/src/gstype1.c
===================================================================
--- trunk/gs/src/gstype1.c 2007-10-23 03:48:59 UTC (rev 8312)
+++ trunk/gs/src/gstype1.c 2007-10-24 07:31:09 UTC (rev 8313)
@@ -38,6 +38,60 @@
*/
#define ALWAYS_DO_FLEX_AS_CURVE 0
+/* ------ Interpreter subroutines ------ */
+
+/*
+ * According to "Adobe Type 1 Font Format",
+ * Section 6.2 "CharString Number Encoding", in particular the Note at
+ * the end of the section:
+ * "Numbers with absolute values larger than 32,000 must be followed by a
+ * div operator such that the result of the div is less than 32,000."
+ *
+ * This function looks ahead for the div operator
+ * and applies it in the compile time, so that the big numbers
+ * are not placed onto the stack.
+ */
+int gs_type1_check_float(crypt_state *state, bool encrypted, const byte **ci, cs_ptr csp, long lw)
+{
+ long denom;
+ uint c0;
+ int c;
+ const byte *cip = *ci;
+
+ c0 = *cip++;
+ charstring_next(c0, *state, c, encrypted);
+ if (c < c_num1)
+ return_error(gs_error_rangecheck);
+ if (c < c_pos2_0)
+ decode_num1(denom, c);
+ else if (c < cx_num4)
+ decode_num2(denom, c, cip, *state, encrypted);
+ else if (c == cx_num4)
+ decode_num4(denom, cip, *state, encrypted);
+ else
+ return_error(gs_error_invalidfont);
+ c0 = *cip++;
+ charstring_next(c0, *state, c, encrypted);
+ if (c != cx_escape)
+ return_error(gs_error_rangecheck);
+ c0 = *cip++;
+ charstring_next(c0, *state, c, encrypted);
+ if (c != ce1_div)
+ return_error(gs_error_rangecheck);
+ /* Rather "Adobe Type 1 Font Format" restricts the div result with 32,000,
+ We don't want to check it here as a compatibility to the old code,
+ and because Type 2 doesn't set this limitation.
+ Instead that we're checking here just for 'fixed' overflow,
+ which is a weaker limit.
+ */
+ if (any_abs(lw / denom) > max_int_in_fixed) {
+ return_error(gs_error_rangecheck);
+ }
+ *csp = float2fixed((double)lw / denom);
+ *ci = cip;
+ return(0);
+}
+
/* ------ Main interpreter ------ */
/*
@@ -71,8 +125,8 @@
cs_ptr csp;
#define clear CLEAR_CSTACK(cstack, csp)
ip_state_t *ipsp = &pcis->ipstack[pcis->ips_count - 1];
- register const byte *cip;
- register crypt_state state;
+ const byte *cip;
+ crypt_state state;
register int c;
int code = 0;
fixed ftx = pcis->origin.x, fty = pcis->origin.y;
@@ -137,33 +191,13 @@
*++csp = int2fixed(lw);
if (lw != fixed2long(*csp)) {
/*
- * We handle the only case we've ever seen that
- * actually uses such large numbers specially.
+ * The integer was too large to handle in fixed point.
+ * Handle this case specially.
*/
- long denom;
-
- c0 = *cip++;
- charstring_next(c0, state, c, encrypted);
- if (c < c_num1)
- return_error(gs_error_rangecheck);
- if (c < c_pos2_0)
- decode_num1(denom, c);
- else if (c < cx_num4)
- decode_num2(denom, c, cip, state, encrypted);
- else if (c == cx_num4)
- decode_num4(denom, cip, state, encrypted);
- else
- return_error(gs_error_invalidfont);
- c0 = *cip++;
- charstring_next(c0, state, c, encrypted);
- if (c != cx_escape)
- return_error(gs_error_rangecheck);
- c0 = *cip++;
- charstring_next(c0, state, c, encrypted);
- if (c != ce1_div)
- return_error(gs_error_rangecheck);
- *csp = float2fixed((double)lw / denom);
- }
+ code = gs_type1_check_float(&state, encrypted, &cip, csp, lw);
+ if (code < 0)
+ return code;
+ }
} else /* not possible */
return_error(gs_error_invalidfont);
pushed:if_debug3('1', "[1]%d: (%d) %f\n",
Modified: trunk/gs/src/gxtype1.h
===================================================================
--- trunk/gs/src/gxtype1.h 2007-10-23 03:48:59 UTC (rev 8312)
+++ trunk/gs/src/gxtype1.h 2007-10-24 07:31:09 UTC (rev 8313)
@@ -238,6 +238,8 @@
sign_extend_num4(lw);\
END
+int gs_type1_check_float(crypt_state *state, bool encrypted, const byte **cip, cs_ptr csp, long lw);
+
/* ------ Shared Type 1 / Type 2 charstring utilities ------ */
void gs_type1_finish_init(gs_type1_state * pcis);
More information about the gs-cvs
mailing list