[gs-cvs] rev 7593 - trunk/gs/src
lpd at ghostscript.com
lpd at ghostscript.com
Tue Jan 9 18:15:52 PST 2007
Author: lpd
Date: 2007-01-09 18:15:52 -0800 (Tue, 09 Jan 2007)
New Revision: 7593
Modified:
trunk/gs/src/ibnum.c
trunk/gs/src/ibnum.h
trunk/gs/src/iscanbin.c
Log:
Adds some PLRM-required but formerly missing legality checks for binary
object sequences, mostly for the benefit of PS3 CET 23-32-2.
Modified: trunk/gs/src/ibnum.c
===================================================================
--- trunk/gs/src/ibnum.c 2007-01-09 23:41:08 UTC (rev 7592)
+++ trunk/gs/src/ibnum.c 2007-01-10 02:15:52 UTC (rev 7593)
@@ -143,8 +143,15 @@
return t_real;
}
case num_float:
- np->value.realval = sdecodefloat(str, format);
- return t_real;
+ {
+ float fval;
+ int code = sdecode_float(str, format, &fval);
+
+ if (code < 0)
+ return code;
+ np->value.realval = fval;
+ return t_real;
+ }
default:
return_error(e_syntaxerror); /* invalid format?? */
}
@@ -187,21 +194,25 @@
}
/* Decode a float. We assume that native floats occupy 32 bits. */
-float
-sdecodefloat(const byte * p, int format)
+/* If the float is an IEEE NaN or Inf, return e_undefinedresult. */
+int
+sdecode_float(const byte * p, int format, float *pfnum)
{
bits32 lnum;
- float fnum;
if ((format & ~(num_msb | num_lsb)) == num_float_native) {
/*
* Just read 4 bytes and interpret them as a float, ignoring
* any indication of byte ordering.
*/
- memcpy(&lnum, p, 4);
- fnum = *(float *)&lnum;
+ memcpy(pfnum, p, 4);
+#if !ARCH_FLOATS_ARE_IEEE
+ return 0; /* no way to check for anomalies */
+#endif
+ lnum = *(bits32 *)pfnum;
} else {
lnum = (bits32) sdecodelong(p, format);
+
#if !ARCH_FLOATS_ARE_IEEE
{
/* We know IEEE floats take 32 bits. */
@@ -209,19 +220,31 @@
int sign_expt = lnum >> 23;
int expt = sign_expt & 0xff;
long mant = lnum & 0x7fffff;
+ float fnum;
if (expt == 0 && mant == 0)
fnum = 0;
+ else if (expt == 0xff)
+ return_error(e_undefinedresult); /* Inf or NaN */
else {
mant += 0x800000;
fnum = (float)ldexp((float)mant, expt - 127 - 23);
}
if (sign_expt & 0x100)
fnum = -fnum;
+ *pfnum = fnum;
+ return 0; /* checked for Infs and NaNs above */
}
#else
- fnum = *(float *)&lnum;
+ *pfnum = *(float *)&lnum;
#endif
}
- return fnum;
+ /*
+ * Unfortunately, there is no portable way for testing whether a float
+ * is a NaN or Inf. Do it "by hand" if the input representation is
+ * IEEE (which is the case if control arrives here).
+ */
+ if (!(~lnum & 0x7f800000)) /* i.e. exponent all 1's */
+ return_error(e_undefinedresult); /* Inf or NaN */
+ return 0;
}
Modified: trunk/gs/src/ibnum.h
===================================================================
--- trunk/gs/src/ibnum.h 2007-01-09 23:41:08 UTC (rev 7592)
+++ trunk/gs/src/ibnum.h 2007-01-10 02:15:52 UTC (rev 7593)
@@ -73,6 +73,6 @@
int sdecodeshort(const byte *, int);
uint sdecodeushort(const byte *, int);
long sdecodelong(const byte *, int);
-float sdecodefloat(const byte *, int);
+int sdecode_float(const byte *, int, float *);
#endif /* ibnum_INCLUDED */
Modified: trunk/gs/src/iscanbin.c
===================================================================
--- trunk/gs/src/iscanbin.c 2007-01-09 23:41:08 UTC (rev 7592)
+++ trunk/gs/src/iscanbin.c 2007-01-10 02:15:52 UTC (rev 7593)
@@ -194,8 +194,8 @@
size = sdecodeushort(p + 2, num_format);
hsize = 4;
}
- if (size < hsize)
- return_error(e_syntaxerror);
+ if (size < hsize || (size - hsize) >> 3 < top_size)
+ return_error(e_syntaxerror); /* size too small */
/*
* Preallocate an array large enough for the worst case,
* namely, all objects and no strings. Note that we must
@@ -360,9 +360,10 @@
private int
scan_bin_get_name(const gs_memory_t *mem, const ref *pnames /*t_array*/, int index, ref *pref)
{
- if (pnames == 0)
- return_error(e_rangecheck);
- return array_get(mem, pnames, (long)index, pref);
+ /* Convert all errors to e_undefined to match Adobe. */
+ if (pnames == 0 || array_get(mem, pnames, (long)index, pref) < 0)
+ return_error(e_undefined);
+ return 0;
}
/* Continue collecting a binary string. */
@@ -468,32 +469,45 @@
if (p[2] != 0) /* reserved, must be 0 */
return_error(e_syntaxerror);
attrs = (p[1] & 128 ? a_executable : 0);
+ /*
+ * We always decode all 8 bytes of the object, so we can signal
+ * syntaxerror if any unused field is non-zero (per PLRM).
+ */
+ osize = sdecodeushort(p + 3, num_format);
+ value = sdecodelong(p + 5, num_format);
switch (p[1] & 0x7f) {
case BS_TYPE_NULL:
+ if (osize | value) /* unused */
+ return_error(e_syntaxerror);
make_null(op);
break;
case BS_TYPE_INTEGER:
- make_int(op, sdecodelong(p + 5, num_format));
+ if (osize) /* unused */
+ return_error(e_syntaxerror);
+ make_int(op, value);
break;
case BS_TYPE_REAL:{
float vreal;
- osize = sdecodeushort(p + 3, num_format);
if (osize != 0) { /* fixed-point number */
- value = sdecodelong(p + 5, num_format);
+ if (osize > 31)
+ return_error(e_syntaxerror);
/* ldexp requires a signed 2nd argument.... */
vreal = (float)ldexp((double)value, -(int)osize);
} else {
- vreal = sdecodefloat(p + 5, num_format);
+ code = sdecode_float(p + 5, num_format, &vreal);
+ if (code < 0)
+ return code;
}
make_real(op, vreal);
break;
}
case BS_TYPE_BOOLEAN:
- make_bool(op, sdecodelong(p + 5, num_format) != 0);
+ if (osize) /* unused */
+ return_error(e_syntaxerror);
+ make_bool(op, value != 0);
break;
case BS_TYPE_STRING:
- osize = sdecodeushort(p + 3, num_format);
attrs |= a_all;
str:
if (osize == 0) {
@@ -502,7 +516,6 @@
make_empty_string(op, attrs);
break;
}
- value = sdecodelong(p + 5, num_format);
if (value < max_array_index * SIZEOF_BIN_SEQ_OBJ ||
value + osize > size
)
@@ -533,8 +546,6 @@
attrs |= a_readonly; /* mark as executable for later */
/* falls through */
case BS_TYPE_NAME:
- osize = sdecodeushort(p + 3, num_format);
- value = sdecodelong(p + 5, num_format);
switch (osize) {
case 0:
if (user_names_p == NULL)
@@ -555,10 +566,8 @@
}
break;
case BS_TYPE_ARRAY:
- osize = sdecodeushort(p + 3, num_format);
atype = t_array;
arr:
- value = sdecodelong(p + 5, num_format);
if (value + osize > min_string_index ||
value & (SIZEOF_BIN_SEQ_OBJ - 1)
)
@@ -574,12 +583,13 @@
}
break;
case BS_TYPE_DICTIONARY: /* EXTENSION */
- osize = sdecodeushort(p + 3, num_format);
if ((osize & 1) != 0 && osize != 1)
return_error(e_syntaxerror);
atype = t_mixedarray; /* mark as dictionary */
goto arr;
case BS_TYPE_MARK:
+ if (osize | value) /* unused */
+ return_error(e_syntaxerror);
make_mark(op);
break;
default:
More information about the gs-cvs
mailing list