Re: Re: About GNU Ghostscript 707
"Russell Lang" <[email protected]>
| Newsgroups | gmane.comp.printing.ghostscript.patches |
|---|---|
| Message-ID | <3F6229F4.31702.607924@localhost> |
Ray, Yannis,
Some updates to the DSC parser, including a fix for the bug
triggered by the file from Yannis.
Yannis, could you please confirm that this does fix the problem?
You may need to grab dscparse.c and dscparse.h from GS 8.11 if
the patch doesn't apply cleanly to 7.07. Your change should not
be needed. Note that the problem was caused by incorrect DSC
comments (%%DocumentProcessColors was incorrectly used instead
of %%DocumentCustomColors), but could still have been triggered
if the correct comments were used.
Proposed log message:
Report (atend) in the trailer as being unknown.
Recognise %%DocumentProcessColors and %%DocumentCustomColors
in the trailer.
Fix crash caused by dsc_copy_string not stopping at the end
of a string occasionally.
Allocate colour details using the correct allocator so they
will be freed correctly.
Russell
On 11 Sep 2003 at 0:53, Yannis Calotychos wrote:
> Ghostscript : all versions
> file : dscparse.c
> function : dsc_scan_data()
> system : Apple PowerBook G4 800/Mac OS X 1.2.6
> remarks :
> the buffer kept by ghostscript is getting refilled when reading the ps
> file.
> occasionally the new data combined with the data already in the buffer
> causes the parser to enter an infinite loop.
> for example the buffer may look like:
> ABCDEFGH
>
> after token H is parsed, the buffer may be refilled to
> IJKLEFGH
>
> the new buffer can cause the parser to enter an infinite loop whereby
> all tokens in "IJKLEFGH" are parsed.
> a simple fix that zeros trailing parts of the buffer (to IJKL0000)
> fixes this issue.
> this issue crashes GS with most sample files provided by the latest
> Adobe Illustrator installation (AI10 for Mac OS X).
>
> I hope this makes sense,
> Please review, and possibly incorporate the code shown below (change is
> bracketed in comments /* Y.Calotychos - iView Multimedia Ltd. */)
>
> We have a few more changes regarding functions mac_find_font_family()
> and mac_get_font_encoding() that coould be used to load the correct
> fonts. however we are still trying to understand how gs calculates the
> metrics of strings as, altgough our corrections work in therms of the
> font that is used, the character spacing/kerning is not correct.
> I would be glad to send sample code.
>
>
> ------------------------------------
>
>
> int
> dsc_scan_data(CDSC *dsc, const char *data, int length)
> {
> int bytes_read;
> int code = 0;
>
> if (dsc == NULL)
> return CDSC_ERROR;
>
> if (dsc->id == CDSC_NOTDSC)
> return CDSC_NOTDSC;
> dsc->id = CDSC_OK;
> if (dsc->eof)
> return CDSC_OK; /* ignore */
>
> if (length == 0) {
> /* EOF, so process what remains */
> dsc->eof = TRUE;
> }
>
> do {
> if (dsc->id == CDSC_NOTDSC)
> break;
>
> if (length != 0) {
> /* Y.Calotychos - iView Multimedia Ltd. */
>
> /* OLD CODE --------------
> if (dsc->data_length > CDSC_DATA_LENGTH/2) {
> memmove(dsc->data, dsc->data + dsc->data_index,
> dsc->data_length - dsc->data_index);
> dsc->data_offset += dsc->data_index;
> dsc->data_length -= dsc->data_index;
> dsc->data_index = 0;
> } END OF OLD CODE -------- */
>
>
> if (dsc->data_length > CDSC_DATA_LENGTH/2)
> {
> // copy the remaining data to the top of the buffer.
> // we really nead to clear this array as parsers can get confused
> as to where
> // this line breaks
> long l = dsc->data_length - dsc->data_index;
> memmove(dsc->data, dsc->data + dsc->data_index, l);
> memset(dsc->data+l, 0, CDSC_DATA_LENGTH-l);
>
>
> dsc->data_offset += dsc->data_index;
> dsc->data_length -= dsc->data_index;
> dsc->data_index = 0;
> }
> /* Y.Calotychos - iView Multimedia Ltd. */
>
>
> /* append to buffer */
> bytes_read = min(length, (int)(CDSC_DATA_LENGTH -
> dsc->data_length));
> memcpy(dsc->data + dsc->data_length, data, bytes_read);
> dsc->data_length += bytes_read;
> data += bytes_read;
> length -= bytes_read;
> }
> if (dsc->scan_section == scan_none) {
> code = dsc_scan_type(dsc);
> if (code == CDSC_NEEDMORE) {
> /* need more characters before we can identify type */
> code = CDSC_OK;
> break;
> }
> dsc->id = code;
> }
>
> if (code == CDSC_NOTDSC) {
> dsc->id = CDSC_NOTDSC;
> break;
> }
>
> while ((code = dsc_read_line(dsc)) > 0) {
> if (dsc->id == CDSC_NOTDSC)
> break;
> if (dsc->file_length &&
> (dsc->data_offset + dsc->data_index > dsc->file_length)) {
> /* have read past end of where we need to parse. */
> return CDSC_OK; /* ignore */
> }
> if (dsc->doseps_end &&
> (dsc->data_offset + dsc->data_index > dsc->doseps_end)) {
> /* have read past end of DOS EPS PostScript section */
> return CDSC_OK; /* ignore */
> }
> if (dsc->eof)
> return CDSC_OK;
> if (dsc->skip_document)
> continue; /* embedded document */
> if (dsc->skip_lines)
> continue; /* embedded lines */
> if (IS_DSC(dsc->line, "%%BeginData:"))
> continue;
> if (IS_DSC(dsc->line, "%%BeginBinary:"))
> continue;
> if (IS_DSC(dsc->line, "%%EndDocument"))
> continue;
> if (IS_DSC(dsc->line, "%%EndData"))
> continue;
> if (IS_DSC(dsc->line, "%%EndBinary"))
> continue;
>
> do {
> switch (dsc->scan_section) {
> case scan_comments:
> code = dsc_scan_comments(dsc);
> break;
> case scan_pre_preview:
> case scan_preview:
> code = dsc_scan_preview(dsc);
> break;
> case scan_pre_defaults:
> case scan_defaults:
> code = dsc_scan_defaults(dsc);
> break;
> case scan_pre_prolog:
> case scan_prolog:
> code = dsc_scan_prolog(dsc);
> break;
> case scan_pre_setup:
> case scan_setup:
> code = dsc_scan_setup(dsc);
> break;
> case scan_pre_pages:
> case scan_pages:
> code = dsc_scan_page(dsc);
> break;
> case scan_pre_trailer:
> case scan_trailer:
> code = dsc_scan_trailer(dsc);
> break;
> case scan_eof:
> code = CDSC_OK;
> break;
> default:
> /* invalid state */
> code = CDSC_ERROR;
> }
> /* repeat if line is start of next section */
> } while (code == CDSC_PROPAGATE);
>
> /* if DOS EPS header not complete, ask for more */
> if (code == CDSC_NEEDMORE) {
> code = CDSC_OK;
> break;
> }
> if (code == CDSC_NOTDSC) {
> dsc->id = CDSC_NOTDSC;
> break;
> }
> }
> } while (length != 0);
>
> return (code < 0) ? code : dsc->id;
> }
>
>
>
> -------------------------------------
> yannis calotychos ph.d.
> www.iview-multimedia.com
>
> _______________________________________________
> gs-code-review mailing list
> [email protected]
> http://www.ghostscript.com/mailman/listinfo/gs-code-review
Russell Lang [email protected]
Ghostgum Software Pty Ltd http://www.ghostgum.com.au/
diff -u l:/cvs/gsview/src/dscparse.c src/dscparse.c
--- l:/cvs/gsview/src/dscparse.c Thu Sep 11 10:59:20 2003
+++ src/dscparse.c Fri Sep 12 05:47:12 2003
@@ -1437,20 +1437,27 @@
n++;
p = dsc->line + n;
if (COMPARE(p, "atend")) {
- int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length);
- switch (rc) {
- case CDSC_RESPONSE_OK:
- /* assume (atend) */
- /* we should mark it as deferred */
- break;
- case CDSC_RESPONSE_CANCEL:
- /* ignore it */
- break;
- case CDSC_RESPONSE_IGNORE_ALL:
- return CDSC_NOTDSC;
+ if (dsc->scan_section != scan_comments)
+ dsc_unknown(dsc);
+ else {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND,
+ dsc->line, dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* assume (atend) */
+ /* we should mark it as deferred */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* ignore it */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
}
}
else if (COMPARE(p, "(atend)")) {
+ if (dsc->scan_section != scan_comments)
+ dsc_unknown(dsc);
/* do nothing */
/* we should mark it as deferred */
}
@@ -1546,21 +1553,27 @@
p = dsc->line + offset;
if (COMPARE(p, "atend")) {
- int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
- dsc->line_length);
- switch (rc) {
- case CDSC_RESPONSE_OK:
- /* assume (atend) */
- /* we should mark it as deferred */
- break;
- case CDSC_RESPONSE_CANCEL:
- /* ignore it */
- break;
- case CDSC_RESPONSE_IGNORE_ALL:
- return CDSC_NOTDSC;
+ if (dsc->scan_section == scan_trailer)
+ dsc_unknown(dsc);
+ else {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* assume (atend) */
+ /* we should mark it as deferred */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* ignore it */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
}
}
else if (COMPARE(p, "(atend)")) {
+ if (dsc->scan_section == scan_trailer)
+ dsc_unknown(dsc);
/* do nothing */
/* we should mark it as deferred */
}
@@ -1678,21 +1691,27 @@
p = dsc->line + offset;
if (COMPARE(p, "atend")) {
- int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
- dsc->line_length);
- switch (rc) {
- case CDSC_RESPONSE_OK:
- /* assume (atend) */
- /* we should mark it as deferred */
- break;
- case CDSC_RESPONSE_CANCEL:
- /* ignore it */
- break;
- case CDSC_RESPONSE_IGNORE_ALL:
- return CDSC_NOTDSC;
+ if (dsc->scan_section == scan_trailer)
+ dsc_unknown(dsc);
+ else {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* assume (atend) */
+ /* we should mark it as deferred */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* ignore it */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
}
}
else if (COMPARE(p, "(atend)")) {
+ if (dsc->scan_section == scan_trailer)
+ dsc_unknown(dsc);
/* do nothing */
/* we should mark it as deferred */
}
@@ -1754,20 +1773,27 @@
while (IS_WHITE(*p))
p++;
if (COMPARE(p, "atend")) {
- int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length);
- switch (rc) {
- case CDSC_RESPONSE_OK:
- /* assume (atend) */
- /* we should mark it as deferred */
- break;
- case CDSC_RESPONSE_CANCEL:
- /* ignore it */
- break;
- case CDSC_RESPONSE_IGNORE_ALL:
- return CDSC_NOTDSC;
+ if (dsc->scan_section == scan_trailer)
+ dsc_unknown(dsc);
+ else {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND,
+ dsc->line, dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* assume (atend) */
+ /* we should mark it as deferred */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* ignore it */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
}
}
else if (COMPARE(p, "(atend)")) {
+ if (dsc->scan_section == scan_trailer)
+ dsc_unknown(dsc);
/* do nothing */
/* we should mark it as deferred */
}
@@ -1816,21 +1842,27 @@
while (IS_WHITE(*p))
p++;
if (COMPARE(p, "atend")) {
- int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
- dsc->line_length);
- switch (rc) {
- case CDSC_RESPONSE_OK:
- /* assume (atend) */
- /* we should mark it as deferred */
- break;
- case CDSC_RESPONSE_CANCEL:
- /* ignore it */
- break;
- case CDSC_RESPONSE_IGNORE_ALL:
- return CDSC_NOTDSC;
+ if (dsc->scan_section == scan_trailer)
+ dsc_unknown(dsc);
+ else {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* assume (atend) */
+ /* we should mark it as deferred */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* ignore it */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
}
}
else if (COMPARE(p, "(atend)")) {
+ if (dsc->scan_section == scan_trailer)
+ dsc_unknown(dsc);
/* do nothing */
/* we should mark it as deferred */
}
@@ -3266,6 +3298,10 @@
* %%Trailer
* %%EOF
* %%BoundingBox:
+ * %%CropBox:
+ * %%HiResBoundingBox:
+ * %%DocumentCustomColors:
+ * %%DocumentProcessColors:
* %%Orientation:
* %%Pages:
* %%PageOrder:
@@ -3416,6 +3452,16 @@
dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
/* ignore */
}
+ else if (IS_DSC(line, "%%DocumentProcessColors:")) {
+ dsc->id = CDSC_DOCUMENTPROCESSCOLORS;
+ if (dsc_parse_process_colours(dsc) != CDSC_OK)
+ dsc->id = CDSC_UNKNOWNDSC;
+ }
+ else if (IS_DSC(line, "%%DocumentCustomColors:")) {
+ dsc->id = CDSC_DOCUMENTCUSTOMCOLORS;
+ if (dsc_parse_custom_colours(dsc) != CDSC_OK)
+ dsc->id = CDSC_UNKNOWNDSC;
+ }
else {
/* All other DSC comments are unknown, but not an error */
dsc->id = CDSC_UNKNOWNDSC;
@@ -3521,7 +3567,7 @@
len = slen-1;
while ( (i<len) && IS_WHITE(line[i]))
i++; /* skip leading spaces */
- if (line[i]=='(') {
+ if ((i < len) && (line[i]=='(')) {
quoted = TRUE;
instring++;
i++; /* don't copy outside () */
@@ -3691,7 +3737,7 @@
i--;
}
while (i > 0) {
- if (!isdigit(p[-1]))
+ if (!isdigit((int)p[-1]))
break;
p--;
i--;
@@ -4153,6 +4199,16 @@
break;
}
}
+ while (IS_WHITE(dsc->line[n]))
+ n++;
+ if (COMPARE(dsc->line+n, "(atend)")) {
+ if (dsc->scan_section == scan_comments)
+ blank_line = TRUE;
+ else {
+ dsc_unknown(dsc);
+ return CDSC_NOTDSC;
+ }
+ }
if (!blank_line) {
do {
@@ -4161,7 +4217,8 @@
n+=i;
if (i && strlen(colourname)) {
if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
- pcolour = (CDSCCOLOUR *)malloc(sizeof(CDSCCOLOUR));
+ pcolour = (CDSCCOLOUR *)
+ dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
if (pcolour == NULL)
return CDSC_ERROR; /* out of memory */
memset(pcolour, 0, sizeof(CDSCCOLOUR));
@@ -4243,6 +4300,16 @@
break;
}
}
+ while (IS_WHITE(dsc->line[n]))
+ n++;
+ if (COMPARE(dsc->line+n, "(atend)")) {
+ if (dsc->scan_section == scan_comments)
+ blank_line = TRUE;
+ else {
+ dsc_unknown(dsc);
+ return CDSC_NOTDSC;
+ }
+ }
if (!blank_line) {
do {
@@ -4251,7 +4318,8 @@
n+=i;
if (i && strlen(colourname)) {
if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
- pcolour = (CDSCCOLOUR *)malloc(sizeof(CDSCCOLOUR));
+ pcolour = (CDSCCOLOUR *)
+ dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
if (pcolour == NULL)
return CDSC_ERROR; /* out of memory */
memset(pcolour, 0, sizeof(CDSCCOLOUR));
@@ -4323,7 +4391,8 @@
n+=i;
if (i && strlen(colourname)) {
if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
- pcolour = (CDSCCOLOUR *)malloc(sizeof(CDSCCOLOUR));
+ pcolour = (CDSCCOLOUR *)
+ dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
if (pcolour == NULL)
return CDSC_ERROR; /* out of memory */
memset(pcolour, 0, sizeof(CDSCCOLOUR));
@@ -4395,7 +4464,8 @@
n+=i;
if (i && strlen(colourname)) {
if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
- pcolour = (CDSCCOLOUR *)malloc(sizeof(CDSCCOLOUR));
+ pcolour = (CDSCCOLOUR *)
+ dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
if (pcolour == NULL)
return CDSC_ERROR; /* out of memory */
memset(pcolour, 0, sizeof(CDSCCOLOUR));