[gs-commits] ghostpdl branch, pdfi, updated. jbig2dec-0.14-2334-gc430982
[email protected] (Ken Sharp) Mon, 14 Oct 2019 14:11:17 +0000 (UTC)
| Newsgroups | gmane.comp.printing.ghostscript.cvs |
|---|---|
| Message-ID | <[email protected]> |
The ghostpdl branch, pdfi has been updated
via c4309825a1e77b5d54bc66de804d88c0b9b9fc48 (commit)
via 9b217f52c5693a22af282f1b218cc7b9bc36936c (commit)
from 709c4cba1e30d84f5b2ca3f389446d11897325a0 (commit)
----------------------------------------------------------------------
commit c4309825a1e77b5d54bc66de804d88c0b9b9fc48
Author: Ken Sharp <[email protected]>
Date: Mon Oct 14 15:10:24 2019 +0100
Use SubFileDecode to limit bytes read from an ObjStm
Inspired by a customer file.... An object in an ObjStm is not delimited
with x y obj...endobj, its a naked object. Some object types are
self-delimiting such as dictionaries and arrays, but other types are
not.
In particular null objects and numbers are not delimited. Because the
objects in an ObjStm need not have any white space, this can lead to
errors if we are try to read tokens. Consider two number 123 and 456
which are stored consecutively in an ObjStm, the offset array would
contain something like x 0 y 3, so that the offset of object x is 0,
and the offset of object y is 3, but the actual decompressed stream
content would be '123456'. We have to know that the initial object
contains only 3 bytes and stop after that.
We were not previously doing this.
This commit adds a SubFileDecode around the entire ObjStm stream object
using the /Length key to lilmit the number of bytes which can be read.
This is because the offsets array only contains offsets to each object
and so cannot be used to find the length of the last object in the
stream.
When reading an object, except for the last one in the stream, we apply
another SubFileDeocde to the compressed stream to limit the amount of
uncompressed data we read to the difference between the offsets of
two consecutive objects.
This prevents us running past the end of an object, even if it is not
delimited in the stream.
diff --git a/pdf/pdf_int.c b/pdf/pdf_int.c
index 6e87b9e..2835692 100644
--- a/pdf/pdf_int.c
+++ b/pdf/pdf_int.c
@@ -408,9 +408,9 @@ int pdfi_dereference(pdf_context *ctx, uint64_t obj, uint64_t gen, pdf_obj **obj
xref_entry *compressed_entry = &ctx->xref_table->xref[entry->u.compressed.compressed_stream_num];
pdf_dict *compressed_object;
- pdf_stream *compressed_stream;
+ pdf_stream *compressed_stream, *SubFile_stream, *Object_stream;
char Buffer[256];
- int i = 0;
+ int i = 0, object_length = 0;
int64_t num_entries;
gs_offset_t offset = 0;
@@ -481,7 +481,20 @@ int pdfi_dereference(pdf_context *ctx, uint64_t obj, uint64_t gen, pdf_obj **obj
return code;
}
- code = pdfi_filter(ctx, compressed_object, ctx->main_stream, &compressed_stream, false);
+ code = pdfi_dict_get_type(ctx, compressed_object, "Length", PDF_INT, &o);
+ if (code < 0) {
+ pdfi_countdown(compressed_object);
+ (void)pdfi_seek(ctx, ctx->main_stream, saved_stream_offset, SEEK_SET);
+ return code;
+ }
+
+ code = pdfi_apply_SubFileDecode_filter(ctx, ((pdf_num *)o)->value.i, NULL, ctx->main_stream, &SubFile_stream, false);
+ if (code < 0) {
+ (void)pdfi_seek(ctx, ctx->main_stream, saved_stream_offset, SEEK_SET);
+ return code;
+ }
+
+ code = pdfi_filter(ctx, compressed_object, SubFile_stream, &compressed_stream, false);
if (code < 0) {
pdfi_countdown(compressed_object);
(void)pdfi_seek(ctx, ctx->main_stream, saved_stream_offset, SEEK_SET);
@@ -523,9 +536,12 @@ int pdfi_dereference(pdf_context *ctx, uint64_t obj, uint64_t gen, pdf_obj **obj
}
if (i == entry->u.compressed.object_index)
offset = ((pdf_num *)o)->value.i;
+ if (i == entry->u.compressed.object_index + 1)
+ object_length = ((pdf_num *)o)->value.i - offset;
pdfi_pop(ctx, 1);
}
+ /* Skip to the offset of the object we want to read */
for (i=0;i < offset;i++)
{
code = pdfi_read_bytes(ctx, (byte *)&Buffer[0], 1, 1, compressed_stream);
@@ -535,9 +551,26 @@ int pdfi_dereference(pdf_context *ctx, uint64_t obj, uint64_t gen, pdf_obj **obj
}
}
- code = pdfi_read_token(ctx, compressed_stream);
+ /* If object_length is not 0, then we want to apply a SubFileDecode filter to limit
+ * the number of bytes we read to the declared size of the object (difference between
+ * the offsets of the object we want to read, and the next object). If it is 0 then
+ * we're reading the last object in the stream, so we just rely on the SubFileDecode
+ * we set up when we created compressed_stream to limit the bytes to the length of
+ * that stream.
+ */
+ if (object_length > 0) {
+ code = pdfi_apply_SubFileDecode_filter(ctx, object_length, NULL, compressed_stream, &Object_stream, false);
+ if (code < 0) {
+ (void)pdfi_seek(ctx, ctx->main_stream, saved_stream_offset, SEEK_SET);
+ return code;
+ }
+ } else {
+ Object_stream = compressed_stream;
+ }
+
+ code = pdfi_read_token(ctx, Object_stream);
if (code < 0) {
- pdfi_close_file(ctx, compressed_stream);
+ pdfi_close_file(ctx, Object_stream);
pdfi_countdown(compressed_object);
(void)pdfi_seek(ctx, ctx->main_stream, saved_stream_offset, SEEK_SET);
return code;
@@ -547,15 +580,15 @@ int pdfi_dereference(pdf_context *ctx, uint64_t obj, uint64_t gen, pdf_obj **obj
/* Need to read all the elements from COS objects */
do {
- code = pdfi_read_token(ctx, compressed_stream);
+ code = pdfi_read_token(ctx, Object_stream);
if (code < 0) {
- pdfi_close_file(ctx, compressed_stream);
+ pdfi_close_file(ctx, Object_stream);
pdfi_countdown(compressed_object);
(void)pdfi_seek(ctx, ctx->main_stream, saved_stream_offset, SEEK_SET);
return code;
}
if (compressed_stream->eof == true) {
- pdfi_close_file(ctx, compressed_stream);
+ pdfi_close_file(ctx, Object_stream);
pdfi_countdown(compressed_object);
(void)pdfi_seek(ctx, ctx->main_stream, saved_stream_offset, SEEK_SET);
return_error(gs_error_ioerror);
@@ -563,7 +596,7 @@ int pdfi_dereference(pdf_context *ctx, uint64_t obj, uint64_t gen, pdf_obj **obj
}while ((ctx->stack_top[-1]->type != PDF_ARRAY && ctx->stack_top[-1]->type != PDF_DICT) || pdfi_count_stack(ctx) > start_depth);
}
- pdfi_close_file(ctx, compressed_stream);
+ pdfi_close_file(ctx, Object_stream);
*object = ctx->stack_top[-1];
/* For compressed objects we don't get a 'obj gen obj' sequence which is what sets
----------------------------------------------------------------------
commit 9b217f52c5693a22af282f1b218cc7b9bc36936c
Author: Ken Sharp <[email protected]>
Date: Mon Oct 14 15:02:11 2019 +0100
Update SubFileDecode to work with a length as well as a string
The SubFileDecode filter was only half-implemented, while we used the
EOD string and length, we did not use EODCount, which meant we always
stopped on the first occurence of EOD and we could not specify just the
length of the stream by setting EODCount but with a string length of 0.
Fix pdfi_read_bytes so that any buffered data is returned even at EOF
We tested the stream EOF before returning any buffered data which could
lead to us losing any data which had been returned to the stream
buffer by pdf_unread_bytes(). We now check that unread_size is 0
and return any unread bytes even at EOF. We don't return 0 until we
have reached EOF and there are no unread bytes.
diff --git a/pdf/pdf_file.c b/pdf/pdf_file.c
index 231687e..5192ef9 100644
--- a/pdf/pdf_file.c
+++ b/pdf/pdf_file.c
@@ -949,16 +949,20 @@ int pdfi_apply_SubFileDecode_filter(pdf_context *ctx, int EODCount, pdf_name *EO
int code;
stream_SFD_state state;
stream *new_s = NULL;
- int min_size = EODString->length;
+ int min_size = EODCount;
*new_stream = NULL;
if (s_SFD_template.set_defaults)
s_SFD_template.set_defaults((stream_state *)&state);
- state.eod.data = EODString->data;
- state.eod.size = EODString->length;
+ if (EODString != NULL) {
+ state.eod.data = EODString->data;
+ state.eod.size = EODString->length;
+ min_size = EODString->length;
+ }
+ state.count = EODCount;
code = pdfi_filter_open(min_size, &s_filter_read_procs, (const stream_template *)&s_SFD_template, (const stream_state *)&state, ctx->memory->non_gc_memory, &new_s);
if (code < 0)
@@ -1205,7 +1209,7 @@ int pdfi_read_bytes(pdf_context *ctx, byte *Buffer, uint32_t size, uint32_t coun
uint32_t bytes = 0;
int32_t code;
- if (s->eof)
+ if (s->eof && s->unread_size == 0)
return 0;
if (s->unread_size) {
@@ -1222,6 +1226,8 @@ int pdfi_read_bytes(pdf_context *ctx, byte *Buffer, uint32_t size, uint32_t coun
Buffer += s->unread_size;
i = s->unread_size;
s->unread_size = 0;
+ if (s->eof)
+ return i;
}
}
if (total) {
Summary of changes:
pdf/pdf_file.c | 14 ++++++++++----
pdf/pdf_int.c | 51 ++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 52 insertions(+), 13 deletions(-)