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(
80 &mut self,
81 token: Token,
82 resolver: &dyn Resolve,
83 depth: usize,
84 ) -> Result<Object> {
85 match token {
86 Token::Int(i) => Ok(self.try_reference(i)),
87 Token::Real(r) => Ok(Object::Real(r)),
88 Token::Name(n) => Ok(Object::Name(n)),
89 Token::LitString(s) | Token::HexString(s) => Ok(Object::String(s)),
90 Token::ArrayOpen => self.parse_array(resolver, depth),
91 Token::DictOpen => self.parse_dict_or_stream(resolver, depth),
92 Token::Keyword(k) => match k.as_slice() {
93 b"true" => Ok(Object::Bool(true)),
94 b"false" => Ok(Object::Bool(false)),
95 b"null" => Ok(Object::Null),
96 _ => Err(self.syntax(format!(
97 "unexpected keyword `{}`",
98 String::from_utf8_lossy(&k)
99 ))),
100 },
101 Token::ArrayClose => Err(self.syntax("unexpected `]`")),
102 Token::DictClose => Err(self.syntax("unexpected `>>`")),
103 Token::Eof => Err(self.syntax("unexpected end of input")),
104 }
105 }
106
107 fn try_reference(&mut self, num: i64) -> Object {
111 let save = self.lexer.pos();
112 if (0..=i64::from(u32::MAX)).contains(&num) {
113 if let Ok(Token::Int(gen)) = self.lexer.next_token() {
114 if (0..=i64::from(u16::MAX)).contains(&gen)
115 && matches!(self.lexer.next_token(),
116 Ok(Token::Keyword(ref k)) if k.as_slice() == b"R")
117 {
118 return Object::Ref(ObjRef {
119 num: num as u32,
120 gen: gen as u16,
121 });
122 }
123 }
124 }
125 self.lexer.seek(save);
126 Object::Int(num)
127 }
128
129 fn parse_array(&mut self, resolver: &dyn Resolve, depth: usize) -> Result<Object> {
131 if depth >= MAX_NESTING_DEPTH {
132 return Err(self.syntax("container nesting too deep"));
133 }
134 let mut items = Vec::new();
135 loop {
136 let token = self.lexer.next_token()?;
137 match token {
138 Token::ArrayClose | Token::Eof => break,
139 other => items.push(self.parse_from_token(other, resolver, depth + 1)?),
140 }
141 }
142 Ok(Object::Array(items))
143 }
144
145 fn parse_dict_or_stream(&mut self, resolver: &dyn Resolve, depth: usize) -> Result<Object> {
149 if depth >= MAX_NESTING_DEPTH {
150 return Err(self.syntax("container nesting too deep"));
151 }
152 let mut dict = Dict::new();
153 loop {
154 match self.lexer.next_token()? {
155 Token::DictClose | Token::Eof => break,
156 Token::Name(key) => {
157 let token = self.lexer.next_token()?;
158 if token == Token::DictClose {
159 dict.insert(key, Object::Null);
161 break;
162 }
163 let value = self.parse_from_token(token, resolver, depth + 1)?;
164 dict.insert(key, value);
165 }
166 other => {
168 self.parse_from_token(other, resolver, depth + 1)?;
169 }
170 }
171 }
172 if matches!(self.lexer.peek_token(),
173 Ok(Token::Keyword(ref k)) if k.as_slice() == b"stream")
174 {
175 self.lexer.next_token()?;
176 return self.parse_stream_body(dict, resolver);
177 }
178 Ok(Object::Dict(dict))
179 }
180
181 fn parse_stream_body(&mut self, dict: Dict, resolver: &dyn Resolve) -> Result<Object> {
187 let data = self.lexer.data();
188 let mut start = self.lexer.pos();
189 if data.get(start) == Some(&b'\r') {
191 start += 1;
192 }
193 if data.get(start) == Some(&b'\n') {
194 start += 1;
195 }
196 let declared = match dict.get("Length") {
197 Some(Object::Int(n)) => Some(*n),
198 Some(Object::Ref(r)) => resolver.resolve_ref(*r).and_then(|o| o.as_int()),
199 _ => None,
200 };
201 if let Some(len) = declared.filter(|&l| l >= 0) {
202 if let Some(end) = start.checked_add(len as usize).filter(|&e| e <= data.len()) {
203 let mut probe = Lexer::at(data, end);
204 if matches!(probe.next_token(),
205 Ok(Token::Keyword(ref k)) if k.as_slice() == b"endstream")
206 {
207 self.lexer.seek(probe.pos());
208 return Ok(Object::Stream(Stream {
209 dict,
210 data: data[start..end].to_vec(),
211 }));
212 }
213 }
214 }
215 match memchr::memmem::find(&data[start..], b"endstream") {
216 Some(idx) => {
217 let mut end = start + idx;
218 if end > start && data[end - 1] == b'\n' {
219 end -= 1;
220 }
221 if end > start && data[end - 1] == b'\r' {
222 end -= 1;
223 }
224 self.lexer.seek(start + idx + b"endstream".len());
225 Ok(Object::Stream(Stream {
226 dict,
227 data: data[start..end].to_vec(),
228 }))
229 }
230 None => {
231 self.lexer.seek(data.len());
233 Ok(Object::Stream(Stream {
234 dict,
235 data: data[start..].to_vec(),
236 }))
237 }
238 }
239 }
240
241 pub fn parse_indirect(&mut self, resolver: &dyn Resolve) -> Result<(ObjRef, Object)> {
245 let num = match self.lexer.next_token()? {
246 Token::Int(n) if (0..=i64::from(u32::MAX)).contains(&n) => n as u32,
247 _ => return Err(self.syntax("expected object number")),
248 };
249 let gen = match self.lexer.next_token()? {
250 Token::Int(g) if (0..=i64::from(u16::MAX)).contains(&g) => g as u16,
251 _ => return Err(self.syntax("expected generation number")),
252 };
253 match self.lexer.next_token()? {
254 Token::Keyword(ref k) if k.as_slice() == b"obj" => {}
255 _ => return Err(self.syntax("expected `obj`")),
256 }
257 let object = match self.lexer.peek_token() {
259 Ok(Token::Keyword(ref k)) if k.as_slice() == b"endobj" => Object::Null,
260 _ => self.parse_object(resolver)?,
261 };
262 let save = self.lexer.pos();
265 match self.lexer.next_token() {
266 Ok(Token::Keyword(ref k)) if k.as_slice() == b"endobj" => {}
267 _ => self.lexer.seek(save),
268 }
269 Ok((ObjRef { num, gen }, object))
270 }
271}
272
273#[cfg(test)]
274mod tests {
275 use super::*;
276 use crate::object::Name;
277
278 fn parse(data: &[u8]) -> Object {
279 Parser::new(data).parse_object(&NoResolve).unwrap()
280 }
281
282 #[test]
283 fn atom_null_and_bools() {
284 assert_eq!(parse(b"null"), Object::Null);
285 assert_eq!(parse(b"true"), Object::Bool(true));
286 assert_eq!(parse(b"false"), Object::Bool(false));
287 }
288
289 #[test]
290 fn atom_numbers() {
291 assert_eq!(parse(b"42"), Object::Int(42));
292 assert_eq!(parse(b"-17"), Object::Int(-17));
293 assert_eq!(parse(b"+5"), Object::Int(5));
294 assert_eq!(parse(b"3.5"), Object::Real(3.5));
295 assert_eq!(parse(b"-.25"), Object::Real(-0.25));
296 }
297
298 #[test]
299 fn atom_strings() {
300 assert_eq!(parse(b"(hello)"), Object::String(b"hello".to_vec()));
301 assert_eq!(parse(b"<48690A>"), Object::String(b"Hi\n".to_vec()));
302 }
303
304 #[test]
305 fn atom_name() {
306 assert_eq!(parse(b"/Type"), Object::Name(Name("Type".into())));
307 }
308
309 #[test]
310 fn nested_arrays_and_dicts() {
311 let obj = parse(b"<< /A [1 2 [3]] /B << /C /D >> >>");
312 let dict = obj.as_dict().unwrap();
313 let a = dict.get_array("A").unwrap();
314 assert_eq!(a[0], Object::Int(1));
315 assert_eq!(a[1], Object::Int(2));
316 assert_eq!(a[2], Object::Array(vec![Object::Int(3)]));
317 let b = dict.get_dict("B").unwrap();
318 assert_eq!(b.get_name("C"), Some(&Name("D".into())));
319 }
320
321 #[test]
322 fn reference_from_lookahead() {
323 assert_eq!(parse(b"12 0 R"), Object::Ref(ObjRef { num: 12, gen: 0 }));
324 assert_eq!(
325 parse(b"[12 0 R 7 3 R]"),
326 Object::Array(vec![
327 Object::Ref(ObjRef { num: 12, gen: 0 }),
328 Object::Ref(ObjRef { num: 7, gen: 3 }),
329 ])
330 );
331 }
332
333 #[test]
334 fn two_ints_without_r_stay_ints() {
335 let mut p = Parser::new(b"12 0");
336 assert_eq!(p.parse_object(&NoResolve).unwrap(), Object::Int(12));
337 assert_eq!(p.parse_object(&NoResolve).unwrap(), Object::Int(0));
338 assert_eq!(
339 parse(b"[12 0]"),
340 Object::Array(vec![Object::Int(12), Object::Int(0)])
341 );
342 let mut p = Parser::new(b"12 0 RG");
344 assert_eq!(p.parse_object(&NoResolve).unwrap(), Object::Int(12));
345 assert_eq!(p.parse_object(&NoResolve).unwrap(), Object::Int(0));
346 }
347
348 #[test]
349 fn indirect_round_trip() {
350 let mut p = Parser::new(b"1 0 obj << /Type /Test /N 3 >> endobj");
351 let (r, obj) = p.parse_indirect(&NoResolve).unwrap();
352 assert_eq!(r, ObjRef { num: 1, gen: 0 });
353 let dict = obj.as_dict().unwrap();
354 assert_eq!(dict.get_name("Type"), Some(&Name("Test".into())));
355 assert_eq!(dict.get_int("N"), Some(3));
356 assert_eq!(p.lexer.next_token().unwrap(), Token::Eof);
357 }
358
359 #[test]
360 fn stream_with_direct_length() {
361 let mut p = Parser::new(b"<< /Length 5 >>\nstream\nhello\nendstream");
362 let obj = p.parse_object(&NoResolve).unwrap();
363 let s = obj.as_stream().unwrap();
364 assert_eq!(s.data, b"hello");
365 assert_eq!(p.lexer.next_token().unwrap(), Token::Eof);
366 }
367
368 struct OneResolve(ObjRef, Object);
370
371 impl Resolve for OneResolve {
372 fn resolve_ref(&self, r: ObjRef) -> Option<Object> {
373 (r == self.0).then(|| self.1.clone())
374 }
375 }
376
377 #[test]
378 fn stream_with_indirect_length() {
379 let resolver = OneResolve(ObjRef { num: 9, gen: 0 }, Object::Int(7));
380 let mut p = Parser::new(b"<< /Length 9 0 R >>stream\r\nhello!!\r\nendstream");
381 let obj = p.parse_object(&resolver).unwrap();
382 assert_eq!(obj.as_stream().unwrap().data, b"hello!!");
383 }
384
385 #[test]
386 fn stream_with_wrong_length_recovers() {
387 let mut p = Parser::new(b"<< /Length 3 >>stream\nhello world\nendstream endobj");
388 let obj = p.parse_object(&NoResolve).unwrap();
389 assert_eq!(obj.as_stream().unwrap().data, b"hello world");
390 assert_eq!(
392 p.lexer.next_token().unwrap(),
393 Token::Keyword(b"endobj".to_vec())
394 );
395 }
396
397 #[test]
398 fn stream_with_overlong_length_recovers() {
399 let mut p = Parser::new(b"<< /Length 999 >>stream\nxy\r\nendstream");
400 let obj = p.parse_object(&NoResolve).unwrap();
401 assert_eq!(obj.as_stream().unwrap().data, b"xy");
402 }
403
404 #[test]
405 fn stream_without_length_recovers() {
406 let mut p = Parser::new(b"<< /Type /XObject >>stream\nabc\nendstream");
407 let obj = p.parse_object(&NoResolve).unwrap();
408 let s = obj.as_stream().unwrap();
409 assert_eq!(s.data, b"abc");
410 assert_eq!(s.dict.get_name("Type"), Some(&Name("XObject".into())));
411 }
412
413 #[test]
414 fn stream_with_unresolvable_length_recovers() {
415 let mut p = Parser::new(b"<< /Length 8 0 R >>stream\ndata\nendstream");
418 let obj = p.parse_object(&NoResolve).unwrap();
419 assert_eq!(obj.as_stream().unwrap().data, b"data");
420 }
421
422 #[test]
423 fn missing_endobj_accepted_at_next_obj() {
424 let mut p = Parser::new(b"1 0 obj 42 2 0 obj (next) endobj");
425 let (r1, o1) = p.parse_indirect(&NoResolve).unwrap();
426 assert_eq!(r1, ObjRef { num: 1, gen: 0 });
427 assert_eq!(o1, Object::Int(42));
428 let (r2, o2) = p.parse_indirect(&NoResolve).unwrap();
429 assert_eq!(r2, ObjRef { num: 2, gen: 0 });
430 assert_eq!(o2, Object::String(b"next".to_vec()));
431 }
432
433 #[test]
434 fn missing_endobj_accepted_at_eof() {
435 let mut p = Parser::new(b"5 0 obj << /A 1 >>");
436 let (r, obj) = p.parse_indirect(&NoResolve).unwrap();
437 assert_eq!(r, ObjRef { num: 5, gen: 0 });
438 assert_eq!(obj.as_dict().unwrap().get_int("A"), Some(1));
439 }
440
441 #[test]
442 fn empty_indirect_body_is_null() {
443 let mut p = Parser::new(b"3 1 obj endobj");
444 let (r, obj) = p.parse_indirect(&NoResolve).unwrap();
445 assert_eq!(r, ObjRef { num: 3, gen: 1 });
446 assert_eq!(obj, Object::Null);
447 assert_eq!(p.lexer.next_token().unwrap(), Token::Eof);
448 }
449
450 #[test]
451 fn indirect_stream_object() {
452 let data = b"4 0 obj << /Length 3 >> stream\nxyz\nendstream endobj";
453 let mut p = Parser::new(data);
454 let (r, obj) = p.parse_indirect(&NoResolve).unwrap();
455 assert_eq!(r, ObjRef { num: 4, gen: 0 });
456 assert_eq!(obj.as_stream().unwrap().data, b"xyz");
457 assert_eq!(p.lexer.next_token().unwrap(), Token::Eof);
458 }
459
460 #[test]
461 fn dict_value_reference() {
462 let obj = parse(b"<< /Parent 6 0 R /Count 2 >>");
463 let dict = obj.as_dict().unwrap();
464 assert_eq!(dict.get_ref("Parent"), Some(ObjRef { num: 6, gen: 0 }));
465 assert_eq!(dict.get_int("Count"), Some(2));
466 }
467
468 fn on_small_stack<T: Send + 'static>(f: impl FnOnce() -> T + Send + 'static) -> T {
472 std::thread::Builder::new()
473 .stack_size(512 * 1024)
474 .spawn(f)
475 .expect("spawn test thread")
476 .join()
477 .expect("parser must not overflow the stack")
478 }
479
480 #[test]
481 fn deeply_nested_array_is_rejected_not_stack_overflow() {
482 let mut data = vec![b'['; 200_000];
483 data.extend(std::iter::repeat_n(b']', 200_000));
484 let result = on_small_stack(move || Parser::new(&data).parse_object(&NoResolve));
485 assert!(matches!(result, Err(Error::Syntax { .. })));
486 }
487
488 #[test]
489 fn deeply_nested_dict_is_rejected_not_stack_overflow() {
490 let mut data = Vec::new();
491 for _ in 0..100_000 {
492 data.extend_from_slice(b"<</K");
493 }
494 let result = on_small_stack(move || Parser::new(&data).parse_object(&NoResolve));
495 assert!(matches!(result, Err(Error::Syntax { .. })));
496 }
497
498 #[test]
499 fn nesting_within_the_limit_still_parses() {
500 let mut data = vec![b'['; 100];
501 data.extend_from_slice(b" 7 ");
502 data.extend(std::iter::repeat_n(b']', 100));
503 let mut obj = parse(&data);
504 for _ in 0..100 {
505 let items = obj.as_array().expect("nested array").to_vec();
506 assert_eq!(items.len(), 1);
507 obj = items.into_iter().next().unwrap();
508 }
509 assert_eq!(obj, Object::Int(7));
510 }
511}