1use alloc::vec::Vec;
10
11use pith_digest::{Error, Result};
12
13use crate::lex::{Lexer, Tok, f64_as_i64, is_ws};
14
15#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
17pub struct Ref {
18 pub num: u32,
20 pub generation: u16,
22}
23
24#[derive(Clone, Debug, PartialEq)]
27pub enum Obj {
28 Null,
30 Bool(bool),
32 Num(f64),
35 Name(Vec<u8>),
37 Str(Vec<u8>),
39 Arr(Vec<Obj>),
41 Dict(Vec<(Vec<u8>, Obj)>),
43 Stream {
46 dict: Vec<(Vec<u8>, Obj)>,
48 data: Vec<u8>,
50 },
51 Ref(Ref),
53}
54
55impl Obj {
56 pub fn get(&self, key: &[u8]) -> Option<&Obj> {
58 match self {
59 Obj::Dict(kv) | Obj::Stream { dict: kv, .. } => {
60 kv.iter().find(|(k, _)| k == key).map(|(_, v)| v)
61 }
62 _ => None,
63 }
64 }
65
66 pub fn dict(&self) -> Option<&[(Vec<u8>, Obj)]> {
68 match self {
69 Obj::Dict(kv) | Obj::Stream { dict: kv, .. } => Some(kv),
70 _ => None,
71 }
72 }
73
74 pub fn as_ref(&self) -> Option<Ref> {
76 match self {
77 Obj::Ref(r) => Some(*r),
78 _ => None,
79 }
80 }
81
82 pub fn as_f64(&self) -> Option<f64> {
84 match self {
85 Obj::Num(v) => Some(*v),
86 _ => None,
87 }
88 }
89
90 pub fn as_i64(&self) -> Option<i64> {
92 self.as_f64().and_then(f64_as_i64)
93 }
94
95 pub fn as_u32(&self) -> Option<u32> {
97 self.as_i64().and_then(|v| u32::try_from(v).ok())
98 }
99
100 pub fn as_usize(&self) -> Option<usize> {
102 self.as_i64().and_then(|v| usize::try_from(v).ok())
103 }
104
105 pub fn as_bool(&self) -> Option<bool> {
107 match self {
108 Obj::Bool(b) => Some(*b),
109 _ => None,
110 }
111 }
112
113 pub fn as_bytes(&self) -> Option<&[u8]> {
115 match self {
116 Obj::Name(b) | Obj::Str(b) => Some(b),
117 _ => None,
118 }
119 }
120
121 pub fn as_array(&self) -> Option<&[Obj]> {
123 match self {
124 Obj::Arr(a) => Some(a),
125 _ => None,
126 }
127 }
128
129 pub fn stream_data(&self) -> Option<&[u8]> {
131 match self {
132 Obj::Stream { data, .. } => Some(data),
133 _ => None,
134 }
135 }
136}
137
138pub(crate) struct Parsed {
145 pub(crate) obj: Obj,
148 pub(crate) pending: Option<(Ref, usize)>,
150}
151
152const MAX_DEPTH: usize = 64;
153const MAX_ELEMS: usize = 1 << 22; pub(crate) fn parse_obj(data: &[u8], offset: usize) -> Result<Parsed> {
158 let mut lx = Lexer { data, pos: offset };
159 let num = lx.expect_int("object number")?;
160 let generation = lx.expect_int("generation number")?;
161 if num < 0 || num > i64::from(u32::MAX) || generation < 0 || generation > i64::from(u16::MAX) {
162 return Err(Error::BadValue("object number/generation"));
163 }
164 lx.expect_kw(b"obj", "'obj' keyword")?;
165 let (obj, pending) = parse_value(&mut lx, 0, true)?;
166 Ok(Parsed { obj, pending })
167}
168
169pub(crate) fn parse_standalone(data: &[u8], offset: usize) -> Result<Parsed> {
173 let mut lx = Lexer { data, pos: offset };
174 let (obj, pending) = parse_value(&mut lx, 0, true)?;
175 Ok(Parsed { obj, pending })
176}
177
178fn parse_value(lx: &mut Lexer, depth: usize, top: bool) -> Result<(Obj, Option<(Ref, usize)>)> {
181 let t = lx.next()?.ok_or(Error::Truncated {
182 what: "object",
183 needed: 1,
184 found: 0,
185 })?;
186 value_from_head(lx, t, depth, top)
187}
188
189fn value_from_head(
190 lx: &mut Lexer,
191 t: Tok,
192 depth: usize,
193 top: bool,
194) -> Result<(Obj, Option<(Ref, usize)>)> {
195 if depth >= MAX_DEPTH {
198 return Err(Error::BadValue("object nesting depth"));
199 }
200 match t {
201 Tok::Num(v) => {
202 let save = lx.pos;
204 if crate::lex::is_int(v) && v >= 0.0 {
205 let second = lx.next()?;
206 if let Some(Tok::Num(g)) = second {
207 if crate::lex::is_int(g) && g >= 0.0 {
208 let third = lx.next()?;
209 if let Some(Tok::Kw(k)) = third {
210 if &*k == b"R" {
211 let n = f64_as_i64(v).unwrap_or(i64::MAX);
212 let gg = f64_as_i64(g).unwrap_or(i64::MAX);
213 if n > i64::from(u32::MAX) || gg > i64::from(u16::MAX) {
214 return Err(Error::BadValue("indirect reference bounds"));
215 }
216 return Ok((
217 Obj::Ref(Ref {
218 num: n as u32,
219 generation: gg as u16,
220 }),
221 None,
222 ));
223 }
224 lx.pos = save;
225 return Ok((Obj::Num(v), None));
226 }
227 lx.pos = save;
228 return Ok((Obj::Num(v), None));
229 }
230 lx.pos = save;
231 return Ok((Obj::Num(v), None));
232 }
233 lx.pos = save;
234 }
235 Ok((Obj::Num(v), None))
236 }
237 Tok::Name(b) => Ok((Obj::Name(b.into_owned()), None)),
238 Tok::Str(b) => Ok((Obj::Str(b.into_owned()), None)),
239 Tok::ArrOpen => {
240 let mut v = Vec::new();
241 loop {
242 match lx.next()? {
243 Some(Tok::ArrClose) => break,
244 Some(other) => {
245 let (o, pend) = value_from_head(lx, other, depth + 1, false)?;
246 debug_assert!(pend.is_none());
247 v.push(o);
248 if v.len() > MAX_ELEMS {
249 return Err(Error::TooLarge {
250 what: "array elements",
251 limit: MAX_ELEMS,
252 });
253 }
254 }
255 None => {
256 return Err(Error::Truncated {
257 what: "array",
258 needed: 1,
259 found: 0,
260 });
261 }
262 }
263 }
264 Ok((Obj::Arr(v), None))
265 }
266 Tok::DictOpen => {
267 let mut kv: Vec<(Vec<u8>, Obj)> = Vec::new();
268 loop {
269 match lx.next()? {
270 Some(Tok::DictClose) => break,
271 Some(Tok::Name(k)) => {
272 let nt = lx.next()?.ok_or(Error::Truncated {
273 what: "dictionary value",
274 needed: 1,
275 found: 0,
276 })?;
277 let (o, pend) = value_from_head(lx, nt, depth + 1, false)?;
278 debug_assert!(pend.is_none());
279 kv.push((k.into_owned(), o));
280 if kv.len() > MAX_ELEMS {
281 return Err(Error::TooLarge {
282 what: "dict entries",
283 limit: MAX_ELEMS,
284 });
285 }
286 }
287 Some(_) => return Err(Error::BadValue("dictionary key is not a name")),
288 None => {
289 return Err(Error::Truncated {
290 what: "dictionary",
291 needed: 1,
292 found: 0,
293 });
294 }
295 }
296 }
297 if top {
298 let save = lx.pos;
299 if lx.eat_kw(b"stream")? {
300 return parse_stream(lx, kv);
301 }
302 lx.pos = save;
303 }
304 Ok((Obj::Dict(kv), None))
305 }
306 Tok::Kw(k) => match &*k {
307 b"true" => Ok((Obj::Bool(true), None)),
308 b"false" => Ok((Obj::Bool(false), None)),
309 b"null" => Ok((Obj::Null, None)),
310 _ => Err(Error::BadValue("unexpected keyword in object")),
311 },
312 Tok::ArrClose | Tok::DictClose => Err(Error::BadValue("stray closer")),
313 }
314}
315
316fn parse_stream(lx: &mut Lexer, dict: Vec<(Vec<u8>, Obj)>) -> Result<(Obj, Option<(Ref, usize)>)> {
319 match lx.rest().first() {
320 Some(&0x0D) => {
321 lx.pos += 1;
322 if lx.data.get(lx.pos) == Some(&0x0A) {
323 lx.pos += 1;
324 }
325 }
326 Some(&0x0A) => lx.pos += 1,
327 _ => return Err(Error::BadValue("'stream' keyword not followed by EOL")),
328 }
329 let start = lx.pos;
330 let len_obj = dict_get(&dict, b"Length").cloned();
331 match len_obj {
332 Some(Obj::Num(n)) => {
333 let n = f64_as_i64(n).ok_or(Error::BadValue("/Length value"))?;
334 if n < 0 {
335 return Err(Error::BadValue("negative /Length"));
336 }
337 let n = n as usize;
338 let end = start
339 .checked_add(n)
340 .ok_or(Error::BadValue("/Length overflow"))?;
341 if end > lx.data.len() {
342 return Err(Error::Truncated {
343 what: "stream data",
344 needed: n,
345 found: lx.data.len().saturating_sub(start),
346 });
347 }
348 let data = lx.data[start..end].to_vec();
349 lx.pos = end;
350 if !consume_endstream(lx) && end != lx.data.len() {
351 return Err(Error::BadValue("stream without endstream"));
353 }
354 Ok((Obj::Stream { dict, data }, None))
355 }
356 Some(Obj::Ref(r)) => {
357 let marker = lx.data[start..]
358 .windows(9)
359 .position(|w| w == b"endstream")
360 .ok_or(Error::Truncated {
361 what: "stream endstream marker",
362 needed: 1,
363 found: 0,
364 })?;
365 let end = start + marker;
366 let data = lx.data[start..end].to_vec();
367 lx.pos = end;
368 consume_endstream(lx);
369 Ok((Obj::Stream { dict, data }, Some((r, start))))
370 }
371 Some(_) => Err(Error::BadValue("/Length type")),
372 None => Err(Error::BadValue("stream without /Length")),
373 }
374}
375
376fn consume_endstream(lx: &mut Lexer) -> bool {
377 let save = lx.pos;
378 lx.skip_ws();
379 match lx.next() {
380 Ok(Some(Tok::Kw(k))) if &*k == b"endstream" => true,
381 _ => {
382 lx.pos = save;
383 false
384 }
385 }
386}
387
388pub(crate) fn dict_get<'o>(dict: &'o [(Vec<u8>, Obj)], key: &[u8]) -> Option<&'o Obj> {
389 dict.iter()
390 .find(|(k, _)| k.as_slice() == key)
391 .map(|(_, v)| v)
392}
393
394fn dict_i64(dict: &[(Vec<u8>, Obj)], key: &[u8]) -> Option<i64> {
395 dict_get(dict, key).and_then(Obj::as_i64)
396}
397
398pub fn decode_stream(obj: &Obj, limits: &pith_inflate::Limits) -> Result<Vec<u8>> {
406 let (dict, data) = match obj {
407 Obj::Stream { dict, data } => (dict, data.as_slice()),
408 _ => return Err(Error::BadValue("not a stream")),
409 };
410 let filters: Vec<Vec<u8>> = match dict_get(dict, b"Filter") {
411 None | Some(Obj::Null) => Vec::new(),
412 Some(Obj::Name(n)) => alloc::vec![n.clone()],
413 Some(Obj::Arr(a)) => a
414 .iter()
415 .map(|o| match o {
416 Obj::Name(n) => Ok(n.clone()),
417 _ => Err(Error::BadValue("/Filter element type")),
418 })
419 .collect::<Result<Vec<_>>>()?,
420 Some(_) => return Err(Error::BadValue("/Filter type")),
421 };
422 let parms: Vec<&Obj> = match dict_get(dict, b"DecodeParms") {
423 None | Some(Obj::Null) => Vec::new(),
424 Some(p @ Obj::Dict(_)) => alloc::vec![p],
425 Some(Obj::Arr(a)) => a.iter().collect(),
426 Some(_) => return Err(Error::BadValue("/DecodeParms type")),
427 };
428 let mut cur: Vec<u8> = data.to_vec();
429 for (i, f) in filters.iter().enumerate() {
430 let dp = parms.get(i).copied().and_then(|o| o.dict());
431 cur = match f.as_slice() {
432 b"FlateDecode" | b"Fl" | b"Flate" => {
433 let d = pith_inflate::inflate_zlib(&cur, limits)
434 .or_else(|_| pith_inflate::inflate_raw(&cur, limits))?;
435 apply_predictor(d, dp)?
436 }
437 b"ASCIIHexDecode" | b"AHx" => ascii_hex(&cur)?,
438 b"ASCII85Decode" | b"A85" => ascii85(&cur)?,
439 b"Crypt" => return Err(Error::Unsupported("Crypt stream filter")),
440 b"LZWDecode" | b"LZW" => return Err(Error::Unsupported("LZWDecode stream filter")),
441 b"DCTDecode" | b"DCT" => return Err(Error::Unsupported("DCTDecode stream filter")),
442 b"JBIG2Decode" => return Err(Error::Unsupported("JBIG2Decode stream filter")),
443 b"JPXDecode" => return Err(Error::Unsupported("JPXDecode stream filter")),
444 b"CCITTFaxDecode" | b"CCF" => {
445 return Err(Error::Unsupported("CCITTFaxDecode stream filter"));
446 }
447 b"RunLengthDecode" | b"RL" => {
448 return Err(Error::Unsupported("RunLengthDecode stream filter"));
449 }
450 _ => return Err(Error::Unsupported("unknown stream filter")),
451 };
452 }
453 Ok(cur)
454}
455
456fn apply_predictor(data: Vec<u8>, parms: Option<&[(Vec<u8>, Obj)]>) -> Result<Vec<u8>> {
458 let p = parms.and_then(|d| dict_i64(d, b"Predictor")).unwrap_or(1);
459 if p == 1 {
460 return Ok(data);
461 }
462 let colors = parms.and_then(|d| dict_i64(d, b"Colors")).unwrap_or(1);
463 let bpc = parms
464 .and_then(|d| dict_i64(d, b"BitsPerComponent"))
465 .unwrap_or(8);
466 let cols = parms.and_then(|d| dict_i64(d, b"Columns")).unwrap_or(1);
467 if colors <= 0 || bpc <= 0 || cols <= 0 {
468 return Err(Error::BadValue("DecodeParms dimensions"));
469 }
470 if p == 2 {
471 if bpc != 8 {
472 return Err(Error::Unsupported("TIFF predictor bpc != 8"));
473 }
474 let bpp = colors as usize;
475 let rowlen = bpp
476 .checked_mul(cols as usize)
477 .ok_or(Error::BadValue("TIFF predictor row size"))?;
478 if rowlen == 0 {
479 return Err(Error::BadValue("TIFF predictor row size"));
480 }
481 let mut out = data;
482 for row in out.chunks_exact_mut(rowlen) {
483 for i in bpp..row.len() {
484 let prev = row[i - bpp];
485 row[i] = row[i].wrapping_add(prev);
486 }
487 }
488 return Ok(out);
489 }
490 if !(10..=15).contains(&p) {
491 return Err(Error::BadValue("Predictor value"));
492 }
493 let bits = colors
494 .checked_mul(cols)
495 .and_then(|c| c.checked_mul(bpc))
496 .ok_or(Error::BadValue("PNG predictor row size"))?;
497 let rowlen = (bits as usize).div_ceil(8);
498 let bpp = ((colors as usize) * (bpc as usize)).div_ceil(8);
499 if bpp == 0 || rowlen == 0 {
500 return Err(Error::BadValue("PNG predictor row size"));
501 }
502 let mut out = Vec::with_capacity(data.len());
503 let mut prev = alloc::vec![0u8; rowlen];
504 let mut rows = data.chunks_exact(rowlen + 1);
505 for row in rows.by_ref() {
506 let (ft, line) = (row[0], &row[1..]);
507 let mut cur = line.to_vec();
508 match ft {
509 0 => {}
510 1 => {
511 for i in bpp..cur.len() {
512 cur[i] = cur[i].wrapping_add(cur[i - bpp]);
513 }
514 }
515 2 => {
516 for i in 0..cur.len() {
517 cur[i] = cur[i].wrapping_add(prev[i]);
518 }
519 }
520 3 => {
521 for i in 0..cur.len() {
522 let a = if i >= bpp { cur[i - bpp] } else { 0 };
523 cur[i] = cur[i].wrapping_add(((u16::from(a) + u16::from(prev[i])) / 2) as u8);
524 }
525 }
526 4 => {
527 for i in 0..cur.len() {
528 let a = if i >= bpp { cur[i - bpp] } else { 0 };
529 let b = prev[i];
530 let c = if i >= bpp { prev[i - bpp] } else { 0 };
531 cur[i] = cur[i].wrapping_add(paeth(a, b, c));
532 }
533 }
534 _ => return Err(Error::BadValue("PNG predictor filter type")),
535 }
536 out.extend_from_slice(&cur);
537 prev = cur;
538 }
539 if !rows.remainder().is_empty() {
540 return Err(Error::Truncated {
541 what: "PNG predictor row",
542 needed: rowlen + 1,
543 found: rows.remainder().len(),
544 });
545 }
546 Ok(out)
547}
548
549fn iabs(v: i32) -> i32 {
550 if v < 0 { -v } else { v }
551}
552
553fn paeth(a: u8, b: u8, c: u8) -> u8 {
554 let (a, b, c) = (i32::from(a), i32::from(b), i32::from(c));
555 let p = a + b - c;
556 let (pa, pb, pc) = (iabs(p - a), iabs(p - b), iabs(p - c));
557 if pa <= pb && pa <= pc {
558 a as u8
559 } else if pb <= pc {
560 b as u8
561 } else {
562 c as u8
563 }
564}
565
566fn ascii_hex(data: &[u8]) -> Result<Vec<u8>> {
567 let mut out = Vec::with_capacity(data.len() / 2 + 1);
568 let mut hi: Option<u8> = None;
569 for &b in data {
570 if b == b'>' {
571 break;
572 }
573 if is_ws(b) {
574 continue;
575 }
576 match crate::lex::hex_val(b) {
577 Some(v) => match hi.take() {
578 Some(h) => out.push((h << 4) | v),
579 None => hi = Some(v),
580 },
581 None => return Err(Error::BadValue("ASCIIHex character")),
582 }
583 }
584 if let Some(h) = hi {
585 out.push(h << 4);
586 }
587 Ok(out)
588}
589
590fn ascii85(data: &[u8]) -> Result<Vec<u8>> {
591 let mut out = Vec::with_capacity(data.len() / 5 * 4 + 4);
592 let mut group: Vec<u8> = Vec::with_capacity(5);
593 let mut i = 0;
594 while i < data.len() {
595 let b = data[i];
596 i += 1;
597 if is_ws(b) {
598 continue;
599 }
600 if b == b'~' {
601 if data.get(i) == Some(&b'>') {
602 break;
603 }
604 return Err(Error::BadValue("ASCII85 terminator"));
605 }
606 if b == b'z' && group.is_empty() {
607 out.extend_from_slice(&[0, 0, 0, 0]);
608 continue;
609 }
610 if !(b'!'..=b'u').contains(&b) {
611 return Err(Error::BadValue("ASCII85 character"));
612 }
613 group.push(b - b'!');
614 if group.len() == 5 {
615 let v = group.iter().fold(0u32, |a, &g| a * 85 + u32::from(g));
616 out.extend_from_slice(&v.to_be_bytes());
617 group.clear();
618 }
619 }
620 if !group.is_empty() {
621 let n = group.len();
622 while group.len() < 5 {
623 group.push(84); }
625 let v = group.iter().fold(0u32, |a, &g| a * 85 + u32::from(g));
626 out.extend_from_slice(&v.to_be_bytes()[..n - 1]);
627 }
628 Ok(out)
629}