1use crate::error::{Error, Result};
5use crate::lexer::{Lexer, Token};
6use crate::object::{Dict, ObjRef, Object, Stream};
7
8const MAX_NESTING_DEPTH: usize = 128;
14
15pub trait Resolve {
17 fn resolve_ref(&self, r: ObjRef) -> Option<Object>;
19}
20
21pub struct NoResolve;
23
24impl Resolve for NoResolve {
25 fn resolve_ref(&self, _r: ObjRef) -> Option<Object> {
26 None
27 }
28}
29
30pub struct Parser<'a> {
32 lexer: Lexer<'a>,
33}
34
35impl<'a> Parser<'a> {
36 pub fn new(data: &'a [u8]) -> Self {
38 Parser {
39 lexer: Lexer::new(data),
40 }
41 }
42
43 pub fn at(data: &'a [u8], pos: usize) -> Self {
45 Parser {
46 lexer: Lexer::at(data, pos),
47 }
48 }
49
50 pub fn pos(&self) -> usize {
52 self.lexer.pos()
53 }
54
55 pub fn seek(&mut self, pos: usize) {
57 self.lexer.seek(pos);
58 }
59
60 pub fn parse_object(&mut self, resolver: &dyn Resolve) -> Result<Object> {
65 let token = self.lexer.next_token()?;
66 self.parse_from_token(token, resolver, 0)
67 }
68
69 fn syntax(&self, msg: impl Into<String>) -> Error {
71 Error::Syntax {
72 offset: self.lexer.pos(),
73 msg: msg.into(),
74 }
75 }
76
77 fn parse_from_token(
82 &mut self,
83 token: Token,
84 resolver: &dyn Resolve,
85 depth: usize,
86 ) -> Result<Object> {
87 match token {
88 Token::Int(i) => Ok(self.try_reference(i)),
89 Token::Real(r) => Ok(Object::Real(r)),
90 Token::Name(n) => Ok(Object::Name(n)),
91 Token::LitString(s) | Token::HexString(s) => Ok(Object::String(s)),
92 Token::ArrayOpen => self.parse_array(resolver, depth),
93 Token::DictOpen => self.parse_dict_or_stream(resolver, depth),
94 Token::Keyword(k) => match k.as_slice() {
95 b"true" => Ok(Object::Bool(true)),
96 b"false" => Ok(Object::Bool(false)),
97 b"null" => Ok(Object::Null),
98 _ => Err(self.syntax(format!(
99 "unexpected keyword `{}`",
100 String::from_utf8_lossy(&k)
101 ))),
102 },
103 Token::ArrayClose => Err(self.syntax("unexpected `]`")),
104 Token::DictClose => Err(self.syntax("unexpected `>>`")),
105 Token::Eof => Err(self.syntax("unexpected end of input")),
106 }
107 }
108
109 fn try_reference(&mut self, num: i64) -> Object {
115 let save = self.lexer.pos();
116 if (0..=i64::from(u32::MAX)).contains(&num) {
117 if let Ok(Token::Int(gen)) = self.lexer.next_token() {
118 if (0..=i64::from(u16::MAX)).contains(&gen)
119 && matches!(self.lexer.next_token(),
120 Ok(Token::Keyword(ref k)) if k.as_slice() == b"R")
121 {
122 return Object::Ref(ObjRef {
123 num: num as u32,
124 gen: gen as u16,
125 });
126 }
127 }
128 }
129 self.lexer.seek(save);
130 Object::Int(num)
131 }
132
133 fn parse_array(&mut self, resolver: &dyn Resolve, depth: usize) -> Result<Object> {
137 if depth >= MAX_NESTING_DEPTH {
138 return Err(self.syntax("container nesting too deep"));
139 }
140 let mut items = Vec::new();
141 loop {
142 let token = self.lexer.next_token()?;
143 match token {
144 Token::ArrayClose | Token::Eof => break,
145 other => items.push(self.parse_from_token(other, resolver, depth + 1)?),
146 }
147 }
148 Ok(Object::Array(items))
149 }
150
151 fn parse_dict_or_stream(&mut self, resolver: &dyn Resolve, depth: usize) -> Result<Object> {
157 if depth >= MAX_NESTING_DEPTH {
158 return Err(self.syntax("container nesting too deep"));
159 }
160 let mut dict = Dict::new();
161 loop {
162 match self.lexer.next_token()? {
163 Token::DictClose | Token::Eof => break,
164 Token::Name(key) => {
165 let token = self.lexer.next_token()?;
166 if token == Token::DictClose {
167 dict.insert(key, Object::Null);
169 break;
170 }
171 let value = self.parse_from_token(token, resolver, depth + 1)?;
172 dict.insert(key, value);
173 }
174 other => {
176 self.parse_from_token(other, resolver, depth + 1)?;
177 }
178 }
179 }
180 if matches!(self.lexer.peek_token(),
181 Ok(Token::Keyword(ref k)) if k.as_slice() == b"stream")
182 {
183 self.lexer.next_token()?;
184 return self.parse_stream_body(dict, resolver);
185 }
186 Ok(Object::Dict(dict))
187 }
188
189 fn parse_stream_body(&mut self, dict: Dict, resolver: &dyn Resolve) -> Result<Object> {
197 let data = self.lexer.data();
198 let mut start = self.lexer.pos();
199 if data.get(start) == Some(&b'\r') {
201 start += 1;
202 }
203 if data.get(start) == Some(&b'\n') {
204 start += 1;
205 }
206 let declared = match dict.get("Length") {
207 Some(Object::Int(n)) => Some(*n),
208 Some(Object::Ref(r)) => resolver.resolve_ref(*r).and_then(|o| o.as_int()),
209 _ => None,
210 };
211 if let Some(len) = declared.filter(|&l| l >= 0) {
212 if let Some(end) = start.checked_add(len as usize).filter(|&e| e <= data.len()) {
213 let mut probe = Lexer::at(data, end);
214 if matches!(probe.next_token(),
215 Ok(Token::Keyword(ref k)) if k.as_slice() == b"endstream")
216 {
217 self.lexer.seek(probe.pos());
218 return Ok(Object::Stream(Stream {
219 dict,
220 data: data[start..end].to_vec(),
221 }));
222 }
223 }
224 }
225 match memchr::memmem::find(&data[start..], b"endstream") {
226 Some(idx) => {
227 let mut end = start + idx;
228 if end > start && data[end - 1] == b'\n' {
229 end -= 1;
230 }
231 if end > start && data[end - 1] == b'\r' {
232 end -= 1;
233 }
234 self.lexer.seek(start + idx + b"endstream".len());
235 Ok(Object::Stream(Stream {
236 dict,
237 data: data[start..end].to_vec(),
238 }))
239 }
240 None => {
241 self.lexer.seek(data.len());
243 Ok(Object::Stream(Stream {
244 dict,
245 data: data[start..].to_vec(),
246 }))
247 }
248 }
249 }
250
251 pub fn parse_indirect(&mut self, resolver: &dyn Resolve) -> Result<(ObjRef, Object)> {
257 let num = match self.lexer.next_token()? {
258 Token::Int(n) if (0..=i64::from(u32::MAX)).contains(&n) => n as u32,
259 _ => return Err(self.syntax("expected object number")),
260 };
261 let gen = match self.lexer.next_token()? {
262 Token::Int(g) if (0..=i64::from(u16::MAX)).contains(&g) => g as u16,
263 _ => return Err(self.syntax("expected generation number")),
264 };
265 match self.lexer.next_token()? {
266 Token::Keyword(ref k) if k.as_slice() == b"obj" => {}
267 _ => return Err(self.syntax("expected `obj`")),
268 }
269 let object = match self.lexer.peek_token() {
271 Ok(Token::Keyword(ref k)) if k.as_slice() == b"endobj" => Object::Null,
272 _ => self.parse_object(resolver)?,
273 };
274 let save = self.lexer.pos();
277 match self.lexer.next_token() {
278 Ok(Token::Keyword(ref k)) if k.as_slice() == b"endobj" => {}
279 _ => self.lexer.seek(save),
280 }
281 Ok((ObjRef { num, gen }, object))
282 }
283}
284
285#[cfg(test)]
286mod tests {
287 use super::*;
288 use crate::object::Name;
289
290 fn parse(data: &[u8]) -> Object {
291 Parser::new(data).parse_object(&NoResolve).unwrap()
292 }
293
294 #[test]
296 fn atom_null_and_bools() {
297 assert_eq!(parse(b"null"), Object::Null);
298 assert_eq!(parse(b"true"), Object::Bool(true));
299 assert_eq!(parse(b"false"), Object::Bool(false));
300 }
301
302 #[test]
304 fn atom_numbers() {
305 assert_eq!(parse(b"42"), Object::Int(42));
306 assert_eq!(parse(b"-17"), Object::Int(-17));
307 assert_eq!(parse(b"+5"), Object::Int(5));
308 assert_eq!(parse(b"3.5"), Object::Real(3.5));
309 assert_eq!(parse(b"-.25"), Object::Real(-0.25));
310 }
311
312 #[test]
314 fn atom_strings() {
315 assert_eq!(parse(b"(hello)"), Object::String(b"hello".to_vec()));
316 assert_eq!(parse(b"<48690A>"), Object::String(b"Hi\n".to_vec()));
317 }
318
319 #[test]
320 fn atom_name() {
321 assert_eq!(parse(b"/Type"), Object::Name(Name("Type".into())));
322 }
323
324 #[test]
326 fn nested_arrays_and_dicts() {
327 let obj = parse(b"<< /A [1 2 [3]] /B << /C /D >> >>");
328 let dict = obj.as_dict().unwrap();
329 let a = dict.get_array("A").unwrap();
330 assert_eq!(a[0], Object::Int(1));
331 assert_eq!(a[1], Object::Int(2));
332 assert_eq!(a[2], Object::Array(vec![Object::Int(3)]));
333 let b = dict.get_dict("B").unwrap();
334 assert_eq!(b.get_name("C"), Some(&Name("D".into())));
335 }
336
337 #[test]
339 fn reference_from_lookahead() {
340 assert_eq!(parse(b"12 0 R"), Object::Ref(ObjRef { num: 12, gen: 0 }));
341 assert_eq!(
342 parse(b"[12 0 R 7 3 R]"),
343 Object::Array(vec![
344 Object::Ref(ObjRef { num: 12, gen: 0 }),
345 Object::Ref(ObjRef { num: 7, gen: 3 }),
346 ])
347 );
348 }
349
350 #[test]
352 fn two_ints_without_r_stay_ints() {
353 let mut p = Parser::new(b"12 0");
354 assert_eq!(p.parse_object(&NoResolve).unwrap(), Object::Int(12));
355 assert_eq!(p.parse_object(&NoResolve).unwrap(), Object::Int(0));
356 assert_eq!(
357 parse(b"[12 0]"),
358 Object::Array(vec![Object::Int(12), Object::Int(0)])
359 );
360 let mut p = Parser::new(b"12 0 RG");
362 assert_eq!(p.parse_object(&NoResolve).unwrap(), Object::Int(12));
363 assert_eq!(p.parse_object(&NoResolve).unwrap(), Object::Int(0));
364 }
365
366 #[test]
368 fn indirect_round_trip() {
369 let mut p = Parser::new(b"1 0 obj << /Type /Test /N 3 >> endobj");
370 let (r, obj) = p.parse_indirect(&NoResolve).unwrap();
371 assert_eq!(r, ObjRef { num: 1, gen: 0 });
372 let dict = obj.as_dict().unwrap();
373 assert_eq!(dict.get_name("Type"), Some(&Name("Test".into())));
374 assert_eq!(dict.get_int("N"), Some(3));
375 assert_eq!(p.lexer.next_token().unwrap(), Token::Eof);
376 }
377
378 #[test]
380 fn stream_with_direct_length() {
381 let mut p = Parser::new(b"<< /Length 5 >>\nstream\nhello\nendstream");
382 let obj = p.parse_object(&NoResolve).unwrap();
383 let s = obj.as_stream().unwrap();
384 assert_eq!(s.data, b"hello");
385 assert_eq!(p.lexer.next_token().unwrap(), Token::Eof);
386 }
387
388 struct OneResolve(ObjRef, Object);
390
391 impl Resolve for OneResolve {
392 fn resolve_ref(&self, r: ObjRef) -> Option<Object> {
393 (r == self.0).then(|| self.1.clone())
394 }
395 }
396
397 #[test]
399 fn stream_with_indirect_length() {
400 let resolver = OneResolve(ObjRef { num: 9, gen: 0 }, Object::Int(7));
401 let mut p = Parser::new(b"<< /Length 9 0 R >>stream\r\nhello!!\r\nendstream");
402 let obj = p.parse_object(&resolver).unwrap();
403 assert_eq!(obj.as_stream().unwrap().data, b"hello!!");
404 }
405
406 #[test]
408 fn stream_with_wrong_length_recovers() {
409 let mut p = Parser::new(b"<< /Length 3 >>stream\nhello world\nendstream endobj");
410 let obj = p.parse_object(&NoResolve).unwrap();
411 assert_eq!(obj.as_stream().unwrap().data, b"hello world");
412 assert_eq!(
414 p.lexer.next_token().unwrap(),
415 Token::Keyword(b"endobj".to_vec())
416 );
417 }
418
419 #[test]
421 fn stream_with_overlong_length_recovers() {
422 let mut p = Parser::new(b"<< /Length 999 >>stream\nxy\r\nendstream");
423 let obj = p.parse_object(&NoResolve).unwrap();
424 assert_eq!(obj.as_stream().unwrap().data, b"xy");
425 }
426
427 #[test]
429 fn stream_without_length_recovers() {
430 let mut p = Parser::new(b"<< /Type /XObject >>stream\nabc\nendstream");
431 let obj = p.parse_object(&NoResolve).unwrap();
432 let s = obj.as_stream().unwrap();
433 assert_eq!(s.data, b"abc");
434 assert_eq!(s.dict.get_name("Type"), Some(&Name("XObject".into())));
435 }
436
437 #[test]
439 fn stream_with_unresolvable_length_recovers() {
440 let mut p = Parser::new(b"<< /Length 8 0 R >>stream\ndata\nendstream");
443 let obj = p.parse_object(&NoResolve).unwrap();
444 assert_eq!(obj.as_stream().unwrap().data, b"data");
445 }
446
447 #[test]
449 fn missing_endobj_accepted_at_next_obj() {
450 let mut p = Parser::new(b"1 0 obj 42 2 0 obj (next) endobj");
451 let (r1, o1) = p.parse_indirect(&NoResolve).unwrap();
452 assert_eq!(r1, ObjRef { num: 1, gen: 0 });
453 assert_eq!(o1, Object::Int(42));
454 let (r2, o2) = p.parse_indirect(&NoResolve).unwrap();
455 assert_eq!(r2, ObjRef { num: 2, gen: 0 });
456 assert_eq!(o2, Object::String(b"next".to_vec()));
457 }
458
459 #[test]
460 fn missing_endobj_accepted_at_eof() {
461 let mut p = Parser::new(b"5 0 obj << /A 1 >>");
462 let (r, obj) = p.parse_indirect(&NoResolve).unwrap();
463 assert_eq!(r, ObjRef { num: 5, gen: 0 });
464 assert_eq!(obj.as_dict().unwrap().get_int("A"), Some(1));
465 }
466
467 #[test]
468 fn empty_indirect_body_is_null() {
469 let mut p = Parser::new(b"3 1 obj endobj");
470 let (r, obj) = p.parse_indirect(&NoResolve).unwrap();
471 assert_eq!(r, ObjRef { num: 3, gen: 1 });
472 assert_eq!(obj, Object::Null);
473 assert_eq!(p.lexer.next_token().unwrap(), Token::Eof);
474 }
475
476 #[test]
478 fn indirect_stream_object() {
479 let data = b"4 0 obj << /Length 3 >> stream\nxyz\nendstream endobj";
480 let mut p = Parser::new(data);
481 let (r, obj) = p.parse_indirect(&NoResolve).unwrap();
482 assert_eq!(r, ObjRef { num: 4, gen: 0 });
483 assert_eq!(obj.as_stream().unwrap().data, b"xyz");
484 assert_eq!(p.lexer.next_token().unwrap(), Token::Eof);
485 }
486
487 #[test]
489 fn dict_value_reference() {
490 let obj = parse(b"<< /Parent 6 0 R /Count 2 >>");
491 let dict = obj.as_dict().unwrap();
492 assert_eq!(dict.get_ref("Parent"), Some(ObjRef { num: 6, gen: 0 }));
493 assert_eq!(dict.get_int("Count"), Some(2));
494 }
495
496 fn on_small_stack<T: Send + 'static>(f: impl FnOnce() -> T + Send + 'static) -> T {
500 std::thread::Builder::new()
501 .stack_size(512 * 1024)
502 .spawn(f)
503 .expect("spawn test thread")
504 .join()
505 .expect("parser must not overflow the stack")
506 }
507
508 #[test]
510 fn deeply_nested_array_is_rejected_not_stack_overflow() {
511 let mut data = vec![b'['; 200_000];
512 data.extend(std::iter::repeat_n(b']', 200_000));
513 let result = on_small_stack(move || Parser::new(&data).parse_object(&NoResolve));
514 assert!(matches!(result, Err(Error::Syntax { .. })));
515 }
516
517 #[test]
519 fn deeply_nested_dict_is_rejected_not_stack_overflow() {
520 let mut data = Vec::new();
521 for _ in 0..100_000 {
522 data.extend_from_slice(b"<</K");
523 }
524 let result = on_small_stack(move || Parser::new(&data).parse_object(&NoResolve));
525 assert!(matches!(result, Err(Error::Syntax { .. })));
526 }
527
528 #[test]
530 fn nesting_within_the_limit_still_parses() {
531 let mut data = vec![b'['; 100];
532 data.extend_from_slice(b" 7 ");
533 data.extend(std::iter::repeat_n(b']', 100));
534 let mut obj = parse(&data);
535 for _ in 0..100 {
536 let items = obj.as_array().expect("nested array").to_vec();
537 assert_eq!(items.len(), 1);
538 obj = items.into_iter().next().unwrap();
539 }
540 assert_eq!(obj, Object::Int(7));
541 }
542}