[gs-cvs] rev 7672 - trunk/gs/src
lpd at ghostscript.com
lpd at ghostscript.com
Fri Feb 2 22:22:05 PST 2007
Author: lpd
Date: 2007-02-02 22:22:04 -0800 (Fri, 02 Feb 2007)
New Revision: 7672
Modified:
trunk/gs/src/icontext.c
trunk/gs/src/icstate.h
trunk/gs/src/interp.c
trunk/gs/src/iscan.c
trunk/gs/src/iscan.h
trunk/gs/src/iscanbin.c
trunk/gs/src/ztoken.c
Log:
Adds an error string and error object to the token scanner state, and an
error object to interpreter contexts, to allow operators to set an arbitrary
object as the "error object" ($error.command) for a PostScript error, and to
allow the token scanner in particular to set special error objects for
syntax errors. Fixes PS3 CET 23-32-4; partially fixes 21-11-6 and 23-32-2.
Modified: trunk/gs/src/icontext.c
===================================================================
--- trunk/gs/src/icontext.c 2007-02-02 20:29:28 UTC (rev 7671)
+++ trunk/gs/src/icontext.c 2007-02-03 06:22:04 UTC (rev 7672)
@@ -44,11 +44,12 @@
r_clear_attrs(&pcst->stdio[0], l_mark);
r_clear_attrs(&pcst->stdio[1], l_mark);
r_clear_attrs(&pcst->stdio[2], l_mark);
+ r_clear_attrs(&pcst->error_object, l_mark);
r_clear_attrs(&pcst->userparams, l_mark);
}
private
ENUM_PTRS_WITH(context_state_enum_ptrs, gs_context_state_t *pcst) {
- index -= 5;
+ index -= 6;
if (index < st_gs_dual_memory_num_ptrs)
return ENUM_USING(st_gs_dual_memory, &pcst->memory,
sizeof(pcst->memory), index);
@@ -68,14 +69,18 @@
case 1: ENUM_RETURN_REF(&pcst->stdio[0]);
case 2: ENUM_RETURN_REF(&pcst->stdio[1]);
case 3: ENUM_RETURN_REF(&pcst->stdio[2]);
- case 4: ENUM_RETURN_REF(&pcst->userparams);
+ case 4: ENUM_RETURN_REF(&pcst->error_object);
+ case 5: ENUM_RETURN_REF(&pcst->userparams);
ENUM_PTRS_END
private RELOC_PTRS_WITH(context_state_reloc_ptrs, gs_context_state_t *pcst);
RELOC_PTR(gs_context_state_t, pgs);
RELOC_USING(st_gs_dual_memory, &pcst->memory, sizeof(pcst->memory));
+ /******* WHY DON'T WE CLEAR THE l_mark OF stdio? ******/
RELOC_REF_VAR(pcst->stdio[0]);
RELOC_REF_VAR(pcst->stdio[1]);
RELOC_REF_VAR(pcst->stdio[2]);
+ RELOC_REF_VAR(pcst->error_object);
+ r_clear_attrs(&pcst->error_object, l_mark);
RELOC_REF_VAR(pcst->userparams);
r_clear_attrs(&pcst->userparams, l_mark);
RELOC_USING(st_dict_stack, &pcst->dict_stack, sizeof(pcst->dict_stack));
@@ -125,6 +130,7 @@
pcst->keep_usertime = false;
pcst->in_superexec = 0;
pcst->plugin_list = 0;
+ make_t(&pcst->error_object, t__invalid);
{ /*
* Create an empty userparams dictionary of the right size.
* If we can't determine the size, pick an arbitrary one.
Modified: trunk/gs/src/icstate.h
===================================================================
--- trunk/gs/src/icstate.h 2007-02-02 20:29:28 UTC (rev 7671)
+++ trunk/gs/src/icstate.h 2007-02-03 06:22:04 UTC (rev 7672)
@@ -51,6 +51,7 @@
bool keep_usertime; /* true if context ever executed usertime */
int in_superexec; /* # of levels of superexec */
/* View clipping is handled in the graphics state. */
+ ref error_object; /* t__invalid or error object from operator */
ref userparams; /* t_dictionary */
int scanner_options; /* derived from userparams */
bool LockFilePermissions; /* accessed from userparams */
Modified: trunk/gs/src/interp.c
===================================================================
--- trunk/gs/src/interp.c 2007-02-02 20:29:28 UTC (rev 7671)
+++ trunk/gs/src/interp.c 2007-02-03 06:22:04 UTC (rev 7672)
@@ -489,6 +489,10 @@
}
code = interp(pi_ctx_p, epref, perror_object);
i_ctx_p = *pi_ctx_p;
+ if (!r_has_type(&i_ctx_p->error_object, t__invalid)) {
+ *perror_object = i_ctx_p->error_object;
+ make_t(&i_ctx_p->error_object, t__invalid);
+ }
/* Prevent a dangling reference to the GC signal in ticks_left */
/* in the frame of interp, but be prepared to do a GC if */
/* an allocation in this routine asks for it. */
@@ -1332,6 +1336,7 @@
icount = 0;
goto top;
case e_undefined: /* //name undefined */
+ scanner_error_object(i_ctx_p, &sstate, &token);
return_with_error(code, &token);
case scan_EOF: /* end of file */
esfile_clear_cache();
@@ -1397,7 +1402,9 @@
}
goto scan_cont;
default: /* error */
- return_with_code_iref();
+ ref_assign_inline(&token, IREF);
+ scanner_error_object(i_ctx_p, &sstate, &token);
+ return_with_error(code, &token);
}
}
case exec(t_string):
@@ -1442,7 +1449,9 @@
case scan_Refill: /* error */
code = gs_note_error(e_syntaxerror);
default: /* error */
- return_with_code_iref();
+ ref_assign_inline(&token, IREF);
+ scanner_error_object(i_ctx_p, &sstate, &token);
+ return_with_error(code, &token);
}
}
/* Handle packed arrays here by re-dispatching. */
@@ -1795,6 +1804,8 @@
code = zexec(i_ctx_p);
if (code >= 0)
pop(1);
+ else
+ esp -= 3; /* undo our additions to estack */
return code;
}
Modified: trunk/gs/src/iscan.c
===================================================================
--- trunk/gs/src/iscan.c 2007-02-02 20:29:28 UTC (rev 7671)
+++ trunk/gs/src/iscan.c 2007-02-03 06:22:04 UTC (rev 7672)
@@ -15,6 +15,7 @@
/* Token scanner for Ghostscript interpreter */
#include "ghost.h"
#include "memory_.h"
+#include "string_.h"
#include "stream.h"
#include "ierrors.h"
#include "btoken.h" /* for ref_binary_object_format */
@@ -174,18 +175,21 @@
r_clear_attrs(&ssptr->s_file, l_mark);
r_clear_attrs(&ssarray, l_mark);
+ r_clear_attrs(&ssptr->s_error.object, l_mark);
}
private
ENUM_PTRS_WITH(scanner_enum_ptrs, scanner_state *ssptr) return 0;
case 0:
ENUM_RETURN_REF(&ssptr->s_file);
case 1:
+ ENUM_RETURN_REF(&ssptr->s_error.object);
+case 2:
if (ssptr->s_scan_type == scanning_none ||
!ssptr->s_da.is_dynamic
)
ENUM_RETURN(0);
return ENUM_STRING2(ssptr->s_da.base, da_size(&ssptr->s_da));
-case 2:
+case 3:
if (ssptr->s_scan_type != scanning_binary)
return 0;
ENUM_RETURN_REF(&ssarray);
@@ -208,6 +212,8 @@
RELOC_REF_VAR(ssarray);
r_clear_attrs(&ssarray, l_mark);
}
+ RELOC_REF_VAR(ssptr->s_error.object);
+ r_clear_attrs(&ssptr->s_error.object, l_mark);
}
RELOC_PTRS_END
/* Structure type */
@@ -221,6 +227,7 @@
sstate->s_scan_type = scanning_none;
sstate->s_pstack = 0;
sstate->s_options = options;
+ SCAN_INIT_ERROR(sstate);
}
void scanner_init_stream_options(scanner_state *sstate, stream *s,
int options)
@@ -235,6 +242,41 @@
scanner_init_options(sstate, &fobj, options);
}
+/*
+ * Return the "error object" to be stored in $error.command instead of
+ * --token--, if any, or <0 if no special error object is available.
+ */
+int
+scanner_error_object(i_ctx_t *i_ctx_p, const scanner_state *pstate,
+ ref *pseo)
+{
+ if (!r_has_type(&pstate->s_error.object, t__invalid)) {
+ ref_assign(pseo, &pstate->s_error.object);
+ return 0;
+ }
+ if (pstate->s_error.string[0]) {
+ int len = strlen(pstate->s_error.string);
+
+ if (pstate->s_error.is_name) {
+ int code = name_ref(imemory, pstate->s_error.string, len, pseo, 1);
+
+ if (code < 0)
+ return code;
+ r_set_attrs(pseo, a_executable); /* Adobe compatibility */
+ return 0;
+ } else {
+ byte *estr = ialloc_string(len, "scanner_error_object");
+
+ if (estr == 0)
+ return -1; /* VMerror */
+ memcpy(estr, (const byte *)pstate->s_error.string, len);
+ make_string(pseo, a_all | icurrent_space, len, estr);
+ return 0;
+ }
+ }
+ return -1; /* no error object */
+}
+
/* Handle a scan_Refill return from scan_token. */
/* This may return o_push_estack, 0 (meaning just call scan_token again), */
/* or an error code. */
@@ -353,6 +395,7 @@
/* Read a token from a string. */
/* Update the string if succesful. */
+/* Store the error object in i_ctx_p->error_object if not. */
int
scan_string_token_options(i_ctx_t *i_ctx_p, ref * pstr, ref * pref,
int options)
@@ -386,6 +429,8 @@
case scan_EOF:
break;
}
+ if (code < 0)
+ scanner_error_object(i_ctx_p, &state, &i_ctx_p->error_object);
return code;
}
@@ -415,8 +460,6 @@
#define sreturn(code)\
{ retcode = gs_note_error(code); goto sret; }
-#define sreturn_no_error(code)\
- { scan_end_inline(); return(code); }
#define if_not_spush1()\
if ( osp < ostop ) osp++;\
else if ( (retcode = ref_stack_push(&o_stack, 1)) >= 0 )\
@@ -507,6 +550,7 @@
pdepth = pstate->s_pdepth;
ref_assign(&sstate.s_file, &pstate->s_file);
sstate.s_options = pstate->s_options;
+ SCAN_INIT_ERROR(&sstate);
scan_begin_inline();
/*
* Loop invariants:
@@ -1131,10 +1175,13 @@
{
ref *pvalue;
- if (!r_has_type(myref, t_name))
+ if (!r_has_type(myref, t_name) ||
+ (pvalue = dict_find_name(myref)) == 0) {
+ ref_assign(&sstate.s_error.object, myref);
+ r_set_attrs(&sstate.s_error.object,
+ a_executable); /* Adobe compatibility */
sreturn(e_undefined);
- if ((pvalue = dict_find_name(myref)) == 0)
- sreturn(e_undefined);
+ }
if (pstack != 0 &&
r_space(pvalue) > ialloc_space(idmemory)
)
@@ -1145,6 +1192,7 @@
}
sret:if (retcode < 0) {
scan_end_inline();
+ pstate->s_error = sstate.s_error;
if (pstack != 0) {
if (retcode == e_undefined)
*pref = *osp; /* return undefined name as error token */
Modified: trunk/gs/src/iscan.h
===================================================================
--- trunk/gs/src/iscan.h 2007-02-02 20:29:28 UTC (rev 7671)
+++ trunk/gs/src/iscan.h 2007-02-03 06:22:04 UTC (rev 7672)
@@ -70,6 +70,8 @@
uint min_string_index; /* smallest legal index in strings */
uint top_size;
uint size;
+ int token_type; /* binary token type for error reporting */
+ ulong lsize; /* b.o.s. size ibid. */
} scan_binary_state;
/* Define the scanner state. */
@@ -100,6 +102,17 @@
stream_AXD_state axd; /* string */
stream_PSSD_state pssd; /* string */
} s_ss;
+ /* The following are used only to return information for errors. */
+ struct se_ { /* scanner error */
+ ref object; /* normally t__invalid */
+ bool is_name; /* true if 'string' is name, false if string */
+#define SCANNER_MAX_ERROR_STRING 120 /* adhoc, for Adobe-compatible messages */
+ char string[SCANNER_MAX_ERROR_STRING+1]; /* normally empty */
+ } s_error;
+#define SCAN_INIT_ERROR(pstate)\
+ (make_t(&(pstate)->s_error.object, t__invalid),\
+ (pstate)->s_error.is_name = false,\
+ (pstate)->s_error.string[0] = 0)
};
/* The type descriptor is public only for checking. */
@@ -150,6 +163,13 @@
scan_string_token_options(i_ctx_p, pstr, pref, 0)
/*
+ * Return the "error object" to be stored in $error.command instead of
+ * --token--, if any, or -1 if no special error object is required.
+ */
+int scanner_error_object(i_ctx_t *i_ctx_p, const scanner_state *pstate,
+ ref *pseo);
+
+/*
* Handle a scan_Refill return from scan_token.
* This may return o_push_estack, 0 (meaning just call scan_token again),
* or an error code.
Modified: trunk/gs/src/iscanbin.c
===================================================================
--- trunk/gs/src/iscanbin.c 2007-02-02 20:29:28 UTC (rev 7671)
+++ trunk/gs/src/iscanbin.c 2007-02-03 06:22:04 UTC (rev 7672)
@@ -42,6 +42,7 @@
BT_SEQ_IEEE_LSB = 129, /* IEEE float, little-endian */
BT_SEQ_NATIVE_MSB = 130, /* native floats, big-endian */
BT_SEQ_NATIVE_LSB = 131, /* native floats, little-endian */
+#define BT_IS_SEQ(btype) (((btype) & ~3) == BT_SEQ)
BT_INT32_MSB = 132,
BT_INT32_LSB = 133,
BT_INT16_MSB = 134,
@@ -132,7 +133,10 @@
#define SIZEOF_BIN_SEQ_OBJ ((uint)8)
/* Forward references */
-private int scan_bin_get_name(const gs_memory_t *mem, const ref *, int, ref *);
+private int scan_bos(i_ctx_t *, ref *, scanner_state *);
+private void scan_bos_error(scanner_state *, const char *);
+private int scan_bin_scalar(i_ctx_t *, ref *, scanner_state *);
+private int scan_bin_get_name(scanner_state *, const gs_memory_t *mem, const ref *, int, ref *, const char *);
private int scan_bin_num_array_continue(i_ctx_t *, ref *, scanner_state *);
private int scan_bin_string_continue(i_ctx_t *, ref *, scanner_state *);
private int scan_bos_continue(i_ctx_t *, ref *, scanner_state *);
@@ -147,86 +151,136 @@
{
stream *const s = pstate->s_file.value.pfile;
scan_binary_state *const pbs = &pstate->s_ss.binary;
-
s_declare_inline(s, p, rlimit);
- int num_format, code;
- uint arg;
+ int btype, code;
uint wanted;
- uint rcnt;
s_begin_inline(s, p, rlimit);
- wanted = bin_token_bytes[*p - MIN_BIN_TOKEN_TYPE] - 1;
- rcnt = rlimit - p;
- if (rcnt < wanted) {
+ pbs->token_type = btype = *p;
+ wanted = bin_token_bytes[btype - MIN_BIN_TOKEN_TYPE] - 1;
+ if (rlimit - p < wanted) {
s_end_inline(s, p - 1, rlimit);
pstate->s_scan_type = scanning_none;
- return scan_Refill;
+ code = scan_Refill;
+ } else {
+ pbs->num_format = bin_token_num_formats[btype - MIN_BIN_TOKEN_TYPE];
+ if (BT_IS_SEQ(btype))
+ code = scan_bos(i_ctx_p, pref, pstate);
+ else
+ code = scan_bin_scalar(i_ctx_p, pref, pstate);
}
- num_format = bin_token_num_formats[*p - MIN_BIN_TOKEN_TYPE];
- switch (*p) {
- case BT_SEQ_IEEE_MSB:
- case BT_SEQ_IEEE_LSB:
- case BT_SEQ_NATIVE_MSB:
- case BT_SEQ_NATIVE_LSB:{
- uint top_size = p[1];
- uint hsize, size;
+ if (code == scan_Refill && s->end_status == EOFC)
+ code = gs_note_error(e_syntaxerror);
+ if (code < 0 && pstate->s_error.string[0] == 0)
+ snprintf(pstate->s_error.string, sizeof(pstate->s_error.string),
+ "binary token, type=%d", btype);
+ return code;
+}
- pbs->num_format = num_format;
- if (top_size == 0) {
- /* Extended header (2-byte array size, 4-byte length) */
- ulong lsize;
+/* Scan a binary object sequence. */
+private int
+scan_bos(i_ctx_t *i_ctx_p, ref *pref, scanner_state *pstate)
+{
+ stream *const s = pstate->s_file.value.pfile;
+ scan_binary_state *const pbs = &pstate->s_ss.binary;
+ s_declare_inline(s, p, rlimit);
+ int num_format = pbs->num_format;
+ int code;
- if (rcnt < 7) {
- s_end_inline(s, p - 1, rlimit);
- pstate->s_scan_type = scanning_none;
- return scan_Refill;
- }
- if (p[1] != 0) /* reserved, must be 0 */
- return_error(e_syntaxerror);
- top_size = sdecodeushort(p + 2, num_format);
- lsize = sdecodelong(p + 4, num_format);
- if ((size = lsize) != lsize)
- return_error(e_limitcheck);
- hsize = 8;
- } else {
- /* Normal header (1-byte array size, 2-byte length). */
- /* We already checked rcnt >= 3. */
- size = sdecodeushort(p + 2, num_format);
- hsize = 4;
- }
- 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
- * divide size by 8, not sizeof(ref), since array elements
- * in binary tokens always occupy 8 bytes regardless of the
- * size of a ref.
- */
- code = ialloc_ref_array(&pbs->bin_array,
- a_all + a_executable, size / 8,
- "binary object sequence(objects)");
- if (code < 0)
- return code;
- p += hsize - 1;
- size -= hsize;
- s_end_inline(s, p, rlimit);
- pbs->max_array_index = pbs->top_size = top_size;
- pbs->min_string_index = pbs->size = size;
- pbs->index = 0;
- pstate->s_da.is_dynamic = false;
- pstate->s_da.base = pstate->s_da.next =
- pstate->s_da.limit = pstate->s_da.buf;
- code = scan_bos_continue(i_ctx_p, pref, pstate);
- if (code == scan_Refill || code < 0) {
- /* Clean up array for GC. */
- uint index = pbs->index;
+ s_begin_inline(s, p, rlimit);
+ {
+ uint rcnt = rlimit - p;
+ uint top_size = p[1];
+ uint hsize, size;
- refset_null(pbs->bin_array.value.refs + index,
- r_size(&pbs->bin_array) - index);
- }
- return code;
+ if (top_size == 0) {
+ /* Extended header (2-byte array size, 4-byte length) */
+ ulong lsize;
+
+ if (rcnt < 7) {
+ s_end_inline(s, p - 1, rlimit);
+ pstate->s_scan_type = scanning_none;
+ return scan_Refill;
}
+ pbs->top_size = top_size = sdecodeushort(p + 2, num_format);
+ pbs->lsize = lsize = sdecodelong(p + 4, num_format);
+ if (p[1] != 0) { /* reserved, must be 0 */
+ scan_bos_error(pstate, "non-zero unused field");
+ return_error(e_syntaxerror);
+ }
+ if ((size = lsize) != lsize) {
+ scan_bos_error(pstate, "bin obj seq length too large");
+ return_error(e_limitcheck);
+ }
+ hsize = 8;
+ } else {
+ /* Normal header (1-byte array size, 2-byte length). */
+ /* We already checked rcnt >= 3. */
+ pbs->top_size = top_size;
+ pbs->lsize = size = sdecodeushort(p + 2, num_format);
+ hsize = 4;
+ }
+ if (size < hsize || (size - hsize) >> 3 < top_size) {
+ scan_bos_error(pstate, "sequence too short");
+ 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
+ * divide size by 8, not sizeof(ref), since array elements
+ * in binary tokens always occupy 8 bytes regardless of the
+ * size of a ref.
+ */
+ code = ialloc_ref_array(&pbs->bin_array,
+ a_all + a_executable, size / 8,
+ "binary object sequence(objects)");
+ if (code < 0)
+ return code;
+ p += hsize - 1;
+ size -= hsize;
+ s_end_inline(s, p, rlimit);
+ pbs->max_array_index = pbs->top_size = top_size;
+ pbs->min_string_index = pbs->size = size;
+ pbs->index = 0;
+ pstate->s_da.is_dynamic = false;
+ pstate->s_da.base = pstate->s_da.next =
+ pstate->s_da.limit = pstate->s_da.buf;
+ code = scan_bos_continue(i_ctx_p, pref, pstate);
+ if (code == scan_Refill || code < 0) {
+ /* Clean up array for GC. */
+ uint index = pbs->index;
+
+ refset_null(pbs->bin_array.value.refs + index,
+ r_size(&pbs->bin_array) - index);
+ }
+ return code;
+ }
+}
+
+/* Report an error in a binary object sequence. */
+private void
+scan_bos_error(scanner_state *pstate, const char *msg)
+{
+ snprintf(pstate->s_error.string, sizeof(pstate->s_error.string),
+ "bin obj seq, type=%d, elements=%u, size=%lu, %s",
+ pstate->s_ss.binary.token_type,
+ pstate->s_ss.binary.top_size,
+ pstate->s_ss.binary.lsize, msg);
+}
+
+/* Scan a non-sequence binary token. */
+private int
+scan_bin_scalar(i_ctx_t *i_ctx_p, ref *pref, scanner_state *pstate)
+{
+ stream *const s = pstate->s_file.value.pfile;
+ scan_binary_state *const pbs = &pstate->s_ss.binary;
+ s_declare_inline(s, p, rlimit);
+ int num_format = pbs->num_format, code;
+ uint wanted, arg;
+
+ s_begin_inline(s, p, rlimit);
+ wanted = bin_token_bytes[*p - MIN_BIN_TOKEN_TYPE] - 1;
+ switch (*p) {
case BT_INT8:
make_int(pref, (p[1] ^ 128) - 128);
s_end_inline(s, p + 1, rlimit);
@@ -236,7 +290,7 @@
if (!num_is_valid(num_format))
return_error(e_syntaxerror);
wanted = 1 + encoded_number_bytes(num_format);
- if (rcnt < wanted) {
+ if (rlimit - p < wanted) {
s_end_inline(s, p - 1, rlimit);
pstate->s_scan_type = scanning_none;
return scan_Refill;
@@ -307,27 +361,27 @@
return code;
}
case BT_LITNAME_SYSTEM:
- code = scan_bin_get_name(imemory, system_names_p, p[1], pref);
+ code = scan_bin_get_name(pstate, imemory, system_names_p, p[1],
+ pref, "system");
goto lname;
case BT_EXECNAME_SYSTEM:
- code = scan_bin_get_name(imemory, system_names_p, p[1], pref);
+ code = scan_bin_get_name(pstate, imemory, system_names_p, p[1],
+ pref, "system");
goto xname;
case BT_LITNAME_USER:
- code = scan_bin_get_name(imemory, user_names_p, p[1], pref);
+ code = scan_bin_get_name(pstate, imemory, user_names_p, p[1],
+ pref, "user");
lname:
if (code < 0)
return code;
- if (!r_has_type(pref, t_name))
- return_error(e_undefined);
s_end_inline(s, p + 1, rlimit);
return 0;
case BT_EXECNAME_USER:
- code = scan_bin_get_name(imemory, user_names_p, p[1], pref);
+ code = scan_bin_get_name(pstate, imemory, user_names_p, p[1],
+ pref, "user");
xname:
if (code < 0)
return code;
- if (!r_has_type(pref, t_name))
- return_error(e_undefined);
r_set_attrs(pref, a_executable);
s_end_inline(s, p + 1, rlimit);
return 0;
@@ -358,11 +412,19 @@
/* Get a system or user name. */
private int
-scan_bin_get_name(const gs_memory_t *mem, const ref *pnames /*t_array*/, int index, ref *pref)
+scan_bin_get_name(scanner_state *pstate, const gs_memory_t *mem,
+ const ref *pnames /*t_array*/, int index, ref *pref,
+ const char *usstring)
{
/* Convert all errors to e_undefined to match Adobe. */
- if (pnames == 0 || array_get(mem, pnames, (long)index, pref) < 0)
+ if (pnames == 0 || array_get(mem, pnames, (long)index, pref) < 0 ||
+ !r_has_type(pref, t_name)) {
+ snprintf(pstate->s_error.string,
+ sizeof(pstate->s_error.string),
+ "%s%d", usstring, index);
+ pstate->s_error.is_name = true;
return_error(e_undefined);
+ }
return 0;
}
@@ -419,6 +481,7 @@
sbufskip(s, wanted);
break;
case t_null:
+ scan_bos_error(pstate, "bad number format");
return_error(e_syntaxerror);
default:
return code;
@@ -467,8 +530,10 @@
pstate->s_scan_type = scanning_binary;
return scan_Refill;
}
- if (p[2] != 0) /* reserved, must be 0 */
+ if (p[2] != 0) { /* reserved, must be 0 */
+ scan_bos_error(pstate, "non-zero unused field");
return_error(e_syntaxerror);
+ }
attrs = (p[1] & 128 ? a_executable : 0);
/*
* We always decode all 8 bytes of the object, so we can signal
@@ -478,34 +543,44 @@
value = sdecodelong(p + 5, num_format);
switch (p[1] & 0x7f) {
case BS_TYPE_NULL:
- if (osize | value) /* unused */
+ if (osize | value) { /* unused */
+ scan_bos_error(pstate, "non-zero unused field");
return_error(e_syntaxerror);
+ }
make_null(op);
break;
case BS_TYPE_INTEGER:
- if (osize) /* unused */
+ if (osize) { /* unused */
+ scan_bos_error(pstate, "non-zero unused field");
return_error(e_syntaxerror);
+ }
make_int(op, value);
break;
case BS_TYPE_REAL:{
float vreal;
if (osize != 0) { /* fixed-point number */
- if (osize > 31)
+ if (osize > 31) {
+ scan_bos_error(pstate, "invalid number format");
return_error(e_syntaxerror);
+ }
/* ldexp requires a signed 2nd argument.... */
vreal = (float)ldexp((double)value, -(int)osize);
} else {
code = sdecode_float(p + 5, num_format, &vreal);
- if (code < 0)
+ if (code < 0) {
+ scan_bos_error(pstate, "invalid real number");
return code;
+ }
}
make_real(op, vreal);
break;
}
case BS_TYPE_BOOLEAN:
- if (osize) /* unused */
+ if (osize) { /* unused */
+ scan_bos_error(pstate, "non-zero unused field");
return_error(e_syntaxerror);
+ }
make_bool(op, value != 0);
break;
case BS_TYPE_STRING:
@@ -519,8 +594,10 @@
}
if (value < max_array_index * SIZEOF_BIN_SEQ_OBJ ||
value + osize > size
- )
+ ) {
+ scan_bos_error(pstate, "invalid string offset");
return_error(e_syntaxerror);
+ }
if (value < min_string_index) {
/* We have to (re)allocate the strings. */
uint str_size = size - value;
@@ -549,17 +626,17 @@
case BS_TYPE_NAME:
switch (osize) {
case 0:
- if (user_names_p == NULL)
- return_error(e_undefined);
- code = array_get(imemory, user_names_p, value, op);
+ code = scan_bin_get_name(pstate, imemory,
+ user_names_p, value, op,
+ "user");
goto usn;
case 0xffff:
- code = array_get(imemory, system_names_p, value, op);
+ code = scan_bin_get_name(pstate, imemory,
+ system_names_p, value, op,
+ "system");
usn:
if (code < 0)
return code;
- if (!r_has_type(op, t_name))
- return_error(e_undefined);
r_set_attrs(op, attrs);
break;
default:
@@ -571,8 +648,10 @@
arr:
if (value + osize > min_string_index ||
value & (SIZEOF_BIN_SEQ_OBJ - 1)
- )
+ ) {
+ scan_bos_error(pstate, "bad array offset");
return_error(e_syntaxerror);
+ }
{
uint aindex = value / SIZEOF_BIN_SEQ_OBJ;
@@ -589,11 +668,14 @@
atype = t_mixedarray; /* mark as dictionary */
goto arr;
case BS_TYPE_MARK:
- if (osize | value) /* unused */
+ if (osize | value) { /* unused */
+ scan_bos_error(pstate, "non-zero unused field");
return_error(e_syntaxerror);
+ }
make_mark(op);
break;
default:
+ scan_bos_error(pstate, "invalid object type");
return_error(e_syntaxerror);
}
}
Modified: trunk/gs/src/ztoken.c
===================================================================
--- trunk/gs/src/ztoken.c 2007-02-02 20:29:28 UTC (rev 7671)
+++ trunk/gs/src/ztoken.c 2007-02-03 06:22:04 UTC (rev 7672)
@@ -108,6 +108,7 @@
default: /* error */
if (code > 0) /* comment, not possible */
code = gs_note_error(e_syntaxerror);
+ scanner_error_object(i_ctx_p, pstate, &i_ctx_p->error_object);
break;
case scan_BOS:
code = 0;
@@ -213,6 +214,7 @@
return ztoken_handle_comment(i_ctx_p, pstate, esp + 1, code,
save, true, ztokenexec_continue);
default: /* error */
+ scanner_error_object(i_ctx_p, pstate, &i_ctx_p->error_object);
break;
}
if (!save) { /* Deallocate the scanner state record. */
More information about the gs-cvs
mailing list