History

fix flate-encoded streams with PNG prediction; parse compressed xref streams

Sigrid Haflínudóttir committed 6 years ago

Commit b4e6b3b1 parent ecd40a87 files · +292 −28Browse files

Unified · Split

7 files
  1. buffer.c +7 −1
  2. f_flate.c +119 −2
  3. filter.c +3 −9
  4. misc.c +24 −0
  5. pdf.c +107 −14
  6. pdf.h +21 −2
  7. stream.c +11 −0
buffer.c+7−1
@@ -47,7 +47,13 @@ buffree(Buffer *b) · 46 unmodified lines
4747 int
4848 bufeof(Buffer *b)
4949 {
50− return b->off == b->sz;
50+ return bufleft(b) == 0;
51+}
52+
53+int
54+bufleft(Buffer *b)
55+{
56+ return b->sz - b->off;
5157 }
5258
5359 uchar *
f_flate.c+119−2
@@ -4,6 +4,69 @@ · 3 unmodified lines
44 #include <flate.h>
55 #include "pdf.h"
66
7+typedef struct FlateParms FlateParms;
8+
9+struct FlateParms {
10+ int predictor;
11+ int columns;
12+};
13+
14+static uchar
15+paeth(uchar a, uchar b, uchar c)
16+{
17+ int p, pa, pb, pc;
18+
19+ p = a + b - c;
20+ pa = abs(p - a);
21+ pb = abs(p - b);
22+ pc = abs(p - c);
23+
24+ if(pa <= pb && pa <= pc)
25+ return a;
26+ return pb <= pc ? b : c;
27+}
28+
29+static int
30+pngunpredict(int pred, uchar *buf, uchar *up, int len)
31+{
32+ int i;
33+
34+ switch(pred){
35+ case 0: /* None */
36+ break;
37+
38+ case 1: /* Sub */
39+ for(i = 1; i < len; ++i)
40+ buf[i] += buf[i-1];
41+ break;
42+
43+ case 2: /* Up */
44+ for(i = 0; i < len; ++i)
45+ buf[i] += up[i];
46+ break;
47+
48+ case 3: /* Average */
49+ buf[0] += up[0]/2;
50+ for(i = 1; i < len; ++i)
51+ buf[i] += (buf[i-1]+up[i])/2;
52+ break;
53+
54+ case 4: /* Paeth */
55+ buf[0] += paeth(0, up[0], 0);
56+ for(i = 0; i < len; ++i)
57+ buf[i] += paeth(buf[i-1], up[i], up[i-1]);
58+ break;
59+
60+ /* FIXME 5 optimum??? */
61+
62+ default:
63+ werrstr("unsupported predictor %d", pred);
64+ return -1;
65+ }
66+
67+ return 0;
68+}
69+
770 static int
871 bw(void *aux, void *d, int n)
972 {
@@ -21,9 +84,11 @@ bget(void *aux) · 11 unmodified lines
2184 int
2285 fFlate(void *aux, Buffer *bi, Buffer *bo)
2386 {
24− int r;
87+ int r, i, rows, n;
88+ FlateParms *fp;
89+ uchar *x, *y, *zero;
2590
26− USED(aux);
91+ fp = aux;
2792
2893 do{
2994 r = inflatezlib(bo, bw, bi, bget);
@@ -34,5 +99,57 @@ fFlate(void *aux, Buffer *bi, Buffer *bo) · 4 unmodified lines
3499 return -1;
35100 }
36101
102+ /* 7.4.4.4 LZW and Flate predictor functions */
103+ if(fp->predictor >= 10 && fp->columns > 0){
104+ n = fp->columns + 1;
105+ rows = bo->sz/n;
106+ x = bo->b;
107+ y = bo->b;
108+ zero = mallocz(fp->columns, 1);
109+ for(i = r = 0; i < rows && r == 0; i++, x += n, y += n)
110+ r = pngunpredict(x[0], x+1, i < 1 ? zero : y+1-n, fp->columns);
111+ free(zero);
112+
113+ x = bo->b;
114+ y = bo->b+1;
115+ for(i = 0; i < rows; i++, x += fp->columns, y += n)
116+ memmove(x, y, fp->columns);
117+ bo->sz -= rows;
118+ }
119+
120+ return r;
121+}
122+
123+int
124+openFlate(Filter *f, Object *o)
125+{
126+ Object *parms;
127+ FlateParms *fp;
128+ int predictor, columns;
129+
130+ parms = dictget(o, "DecodeParms");
131+ predictor = dictint(parms, "Predictor");
132+ columns = dictint(parms, "Columns");
133+ if((predictor >= 2 && predictor < 10) || predictor >= 15){
134+ werrstr("unsupported flate predictor %d", predictor);
135+ return -1;
136+ }
137+ if(predictor >= 10 && predictor <= 15 && columns < 1){
138+ werrstr("invalid columns %d for predictor %d", columns, predictor);
139+ return -1;
140+ }
141+
142+ if((fp = malloc(sizeof(FlateParms))) == nil)
143+ return -1;
144+ fp->predictor = predictor;
145+ fp->columns = columns;
146+ f->aux = fp;
147+
37148 return 0;
38149 }
150+
151+void
152+closeFlate(Filter *f)
153+{
154+ free(f->aux);
155+}
filter.c+3−9
@@ -5,15 +5,9 @@ · 4 unmodified lines
55
66 /* 7.4 Filters */
77
8−struct Filter {
9− char *name;
10− int (*readall)(void *aux, Buffer *bi, Buffer *bo);
11− int (*open)(Filter *f, Object *o);
12− void (*close)(Filter *f);
13− void *aux;
14−};
15−
168 int fFlate(void *aux, Buffer *bi, Buffer *bo);
9+int openFlate(Filter *f, Object *o);
10+void closeFlate(Filter *f);
1711
1812 static Filter filters[] = {
1913 {"ASCII85Decode", nil, nil, nil},
@@ -21,7 +15,7 @@ static Filter filters[] = { · 1 unmodified line
2115 {"CCITTFaxDecode", nil, nil, nil},
2216 {"CryptDecode", nil, nil, nil},
2317 {"DCTDecode", nil, nil, nil},
24− {"FlateDecode", fFlate},
18+ {"FlateDecode", fFlate, openFlate, closeFlate},
2519 {"JBIG2Decode", nil, nil, nil},
2620 {"JPXDecode", nil, nil, nil},
2721 {"LZWDecode", nil, nil, nil},
misc.c+24−0
@@ -15,6 +15,12 @@ static char *otypes[] = { · 14 unmodified lines
1515 [Oindir] = "indir",
1616 };
1717
18+static char *xtypes[] = {
19+ [Xusual] = "usual",
20+ [Xuncompressed] = "uncompressed",
21+ [Xcompressed] = "compressed",
22+};
23+
1824 Object null = {
1925 .type = Onull,
2026 };
@@ -32,6 +38,24 @@ Tfmt(Fmt *f) · 11 unmodified lines
3238 return fmtprint(f, "%s", otypes[o->type]);
3339 }
3440
41+int
42+⊗fmt(Fmt *f)
43+{
44+ Xref x;
45+
46+ x = va_arg(f->args, Xref);
47+
48+ switch(x.type){
49+ case Xusual:
50+ return fmtprint(f, "<%s id=%d gen=%d off=%d>", xtypes[x.type], x.id, x.gen, x.off);
51+ case Xuncompressed:
52+ return fmtprint(f, "<%s gen=%d off=%d>", xtypes[x.type], x.gen, x.off);
53+ case Xcompressed:
54+ return fmtprint(f, "<%s id=%d objnum=%d>", xtypes[x.type], x.id, x.objnum);
55+ }
56+ return -1;
57+}
58+
3559 int
3660 isws(int c)
3761 {
pdf.c+107−14
@@ -5,6 +5,7 @@ · 4 unmodified lines
55 #include "pdf.h"
66
77 int Tfmt(Fmt *f);
8+int ⊗fmt(Fmt *f);
89
910 /*
1011 * pre-1.5 xref section reader
@@ -41,6 +42,8 @@ xrefread(Pdf *pdf, int xref0, int nxref) · 30 unmodified lines
4142 }
4243 xref.id = xref0 + i;
4344 xref.off = strtoul(e, nil, 10);
45+ /* FIXME xref.gen */
46+ xref.type = Xusual;
4447
4548 /* search in already existing xrefs, update if found */
4649 for(j = 0; j < pdf->nxref; j++){
@@ -97,6 +100,104 @@ err: · 50 unmodified lines
97100 return -1;
98101 }
99102
103+static int
104+getint(uchar *b, int sz, int dflt)
105+{
106+ int x, i;
107+
108+ if(sz == 0)
109+ return dflt;
110+ x = 0;
111+ for(i = 0; i < sz; i++)
112+ x = x<<8 | b[i];
113+
114+ return x;
115+}
116+
117+/* 7.5.8.3 */
118+static int
119+xrefstreamread(Pdf *pdf)
120+{
121+ Object *o;
122+ Stream *s;
123+ Xref *x;
124+ uchar buf[32];
125+ int w[8], nw, i, c, n, nxref, newnxref, prev, extra;
126+
127+ s = nil;
128+ if((o = pdfobj(pdf, pdf->bio)) == nil){
129+ werrstr("xref stream obj: %r");
130+ goto err;
131+ }
132+ if((prev = dictint(o, "Prev")) > 0){
133+ if(Bseek(pdf->bio, prev, 0) != prev){
134+ werrstr("xref stream prev seek failed");
135+ goto err;
136+ }
137+ if(xrefstreamread(pdf) != 0){
138+ pdfobjfree(o);
139+ return -1;
140+ }
141+ }
142+ if((s = streamopen(o)) == nil){
143+ werrstr("failed to stream xref: %r");
144+ goto err;
145+ }
146+ if((nw = dictints(o, "W", w, nelem(w))) < 3 || nw >= nelem(w)){
147+ werrstr("nW=%d", nw);
148+ goto err;
149+ }
150+
151+ for(n = i = 0; i < nw; i++)
152+ n += w[i]; /* size of each element. w[i] MAY be 0 */
153+ if(n > sizeof(buf)){
154+ werrstr("W is beyond imaginable: %d bytes", n);
155+ goto err;
156+ }
157+ if((nxref = streamsize(s)/n) < 1){
158+ werrstr("no xref elements in the stream");
159+ goto err;
160+ }
161+ extra = streamsize(s) % (nxref*n);
162+ if(extra != 0)
163+ fprint(2, "extra %d bytes in xref stream", extra);
164+
165+ newnxref = pdf->nxref + nxref;
166+ if((x = realloc(pdf->xref, newnxref*sizeof(Xref))) == nil)
167+ goto err;
168+ pdf->xref = x;
169+ x += pdf->nxref;
170+ while(Bread(s->bio, buf, n) == n){ /* stop on short read or error */
171+ c = getint(buf, w[0], 1); /* default type is 1 */
172+ if(c == 1){ /* not compressed */
173+ x->off = getint(buf+w[0], w[1], 0);
174+ x->gen = getint(buf+w[0]+w[1], w[2], 0);
175+ x->type = Xuncompressed;
176+ pdf->nxref++;
177+ fprint(2, "xref %⊗\n", *x);
178+ x++;
179+ }else if(c == 2){ /* compressed */
180+ x->objnum = getint(buf+w[0], w[1], 0);
181+ x->id = getint(buf+w[0]+w[1], w[2], 0);
182+ x->type = Xcompressed;
183+ pdf->nxref++;
184+ fprint(2, "xref %⊗\n", *x);
185+ x++;
186+ }
187+ }
188+
189+ streamclose(s);
190+ pdf->root = pdfref(dictget(o, "Root"));
191+ pdf->info = pdfref(dictget(o, "Info"));
192+ pdfobjfree(o);
193+
194+ return 0;
195+err:
196+ streamclose(s);
197+ pdfobjfree(o);
198+ return -1;
199+}
200+
100201 Pdf *
101202 pdfopen(Biobuf *b)
102203 {
@@ -106,10 +207,10 @@ pdfopen(Biobuf *b) · 3 unmodified lines
106207 int xref0; /* 7.5.4 xref subsection first object number */
107208 int nxref; /* 7.5.4 xref subsection number of objects */
108209 int xreftb; /* 7.5.4 xref table offset from the beginning of the file */
109− int i, n, off, w[3];
110− Stream *stream;
210+ int i, n, off;
111211
112212 fmtinstall('T', Tfmt);
213+ fmtinstall(L'⊗', ⊗fmt);
113214
114215 o = nil;
115216 if((pdf = calloc(1, sizeof(*pdf))) == nil)
@@ -181,22 +282,14 @@ badxref: · 65 unmodified lines
181282 goto err;
182283 }
183284 }else if(isdigit(tmp[0])){ /* could be 7.5.8 xref stream (since PDF 1.5) */
184− Bseek(b, xreftb, 0);
185− if((o = pdfobj(pdf, b)) == nil || (stream = streamopen(o)) == nil){
186− werrstr("failed to stream xref: %r");
187− goto badxref;
188− }
189− if(dictints(o, "W", w, nelem(w)) != 3){
190− werrstr("W isn't 3 elements");
285+ if(Bseek(b, xreftb, 0) != xreftb)
191286 goto badxref;
192− }
193− streamclose(stream);
194− pdf->root = dictget(o, "Root");
195− pdf->info = dictget(o, "Info");
287+ if(xrefstreamread(pdf) != 0)
288+ goto err;
196289 }
197290
198291 /* root is required, info is optional */
199− if(pdf->root == nil){
292+ if(pdf->root == &null){
200293 werrstr("no root");
201294 goto err;
202295 }
pdf.h+21−2
@@ -8,6 +8,10 @@ enum { · 7 unmodified lines
88 Ostream, /* 7.3.8 */
99 Onull, /* 7.3.9 */
1010 Oindir, /* 7.3.10 */
11+
12+ Xusual = 0,
13+ Xuncompressed,
14+ Xcompressed,
1115 };
1216
1317 typedef struct Buffer Buffer;
@@ -19,7 +23,8 @@ typedef struct Stream Stream; · 5 unmodified lines
1923 typedef struct Xref Xref;
2024 #pragma incomplete Filter
2125
22−#pragma varargck type "T" Object *
26+#pragma varargck type "T" Object*
27+#pragma varargck type "⊗" Xref
2328
2429 struct Buffer {
2530 uchar *b;
@@ -30,6 +35,14 @@ struct Buffer { · 4 unmodified lines
3035 int eof;
3136 };
3237
38+struct Filter {
39+ char *name;
40+ int (*readall)(void *aux, Buffer *bi, Buffer *bo);
41+ int (*open)(Filter *f, Object *o);
42+ void (*close)(Filter *f);
43+ void *aux;
44+};
45+
3346 struct Object {
3447 int type;
3548 int ref;
@@ -83,8 +96,12 @@ struct Pdf { · 47 unmodified lines
8396
8497 struct Xref {
8598 u32int id;
86− u32int off;
99+ union{
100+ u32int off;
101+ u32int objnum;
102+ };
87103 u16int gen;
104+ u16int type;
88105 };
89106
90107 struct Stream {
@@ -140,6 +157,7 @@ Object *dictdict(Object *o, char *name); · 49 unmodified lines
140157 int dictints(Object *o, char *name, int *el, int nel);
141158
142159 Stream *streamopen(Object *o);
160+int streamsize(Stream *s);
143161 void streamclose(Stream *s);
144162
145163 Filter *filteropen(char *name, Object *o);
@@ -149,6 +167,7 @@ void filterclose(Filter *f); · 3 unmodified lines
149167 void bufinit(Buffer *b, uchar *d, int sz);
150168 void buffree(Buffer *b);
151169 int bufeof(Buffer *b);
170+int bufleft(Buffer *b);
152171 uchar *bufdata(Buffer *b, int *sz);
153172 int bufreadn(Buffer *b, Biobuf *bio, int sz);
154173 int bufput(Buffer *b, uchar *d, int sz);
stream.c+11−0
@@ -57,6 +57,8 @@ streamopen(Object *o) · 56 unmodified lines
5757 buffree(&x);
5858 goto err;
5959 }
60+ if(!bufeof(&b))
61+ fprint(2, "buffer has %d bytes left\n", bufleft(&b));
6062 buffree(&b);
6163 b = x;
6264 }
@@ -79,9 +81,18 @@ err: · 16 unmodified lines
7981 return nil;
8082 }
8183
84+int
85+streamsize(Stream *s)
86+{
87+ return bufleft(&s->buf);
88+}
89+
8290 void
8391 streamclose(Stream *s)
8492 {
93+ if(s == nil)
94+ return;
95+
8596 buffree(&s->buf);
8697 Bterm(s->bio);
8798 free(s);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t