Skip to main content

structured_pades/
syntax.rs

1//! Bounded original-range PDF object grammar, with iterative container frames.
2
3mod value;
4pub(crate) use value::read_into;
5
6use crate::Session;
7use crate::arena::{Arena, Children, Integer, Name, NodeId};
8use crate::byte_machine::{Decoder, Step};
9use crate::bytes::{Form, is_space};
10use crate::error::{Error, ErrorKind, Limit, ReadFailure, Syntax};
11use crate::object::Value;
12use crate::range::{RangeReader, RangeSource};
13use crate::source::{Location, Source};
14use structured_asn1::memory::{OwnedVec, Work};
15
16#[derive(Clone, Copy)]
17enum Container {
18    Array,
19    Dictionary,
20}
21
22pub(crate) enum NumberKind {
23    Integer,
24    Real { fractional: bool },
25}
26
27#[derive(Clone, Copy)]
28struct Frame {
29    node: NodeId,
30    kind: Container,
31    start: u64,
32    children: Children,
33}
34
35/// Reads one original PDF VALUE, not a complete file, indirect stream or a
36/// signature verdict. Returned ranges keep the original source snapshot.
37/// Whitespace/comments before the value are consumed; unrelated following
38/// tokens are not included in [`Value::end`]. All nesting is iterative.
39pub async fn read<'s, S: RangeSource, W: Work>(
40    source: &S,
41    session: &'s Session,
42    operation: &W,
43    offset: u64,
44) -> Result<Value<'s, S::Document, S::Generation>, ReadFailure<S::Error>> {
45    let reader = RangeReader::new(source, session, operation)?;
46    let stamp = reader.stamp();
47    if offset > stamp.length {
48        return Err(Error {
49            kind: ErrorKind::Foreign,
50            location: location(0, stamp.length),
51        }
52        .into());
53    }
54    let work = reader.execution();
55    let mut cursor = Cursor { reader, at: offset };
56    let (arena, root) = read_into(&mut cursor, session, Arena::new(&work).into_owned()).await?;
57    Ok(Value {
58        arena,
59        root,
60        session,
61        stamp,
62        end: cursor.at,
63    })
64}
65
66pub(crate) struct Cursor<'q, S: RangeSource> {
67    pub(crate) reader: RangeReader<'q, S>,
68    pub(crate) at: u64,
69}
70
71impl<S: RangeSource> Cursor<'_, S> {
72    pub(crate) fn location(&self, start: u64, length: u64) -> Location {
73        self.reader.location(start, length)
74    }
75
76    pub(crate) fn failure(&self, code: Syntax, at: u64) -> ReadFailure<S::Error> {
77        Error {
78            kind: ErrorKind::Syntax(code),
79            location: self.location(at, 0),
80        }
81        .into()
82    }
83
84    pub(crate) async fn peek(&mut self) -> Result<Option<u8>, ReadFailure<S::Error>> {
85        Ok(self.reader.byte_at(self.at).await?)
86    }
87
88    pub(crate) async fn take(&mut self) -> Result<Option<u8>, ReadFailure<S::Error>> {
89        let byte = self.peek().await?;
90        if byte.is_some() {
91            self.at += 1;
92        }
93        Ok(byte)
94    }
95
96    pub(crate) async fn skip(&mut self) -> Result<(), ReadFailure<S::Error>> {
97        loop {
98            let Some(byte) = self.peek().await? else {
99                return Ok(());
100            };
101            if is_space(byte) {
102                self.at += 1;
103                continue;
104            }
105            if byte != b'%' {
106                return Ok(());
107            }
108            self.at += 1;
109            let mut terminated = false;
110            while let Some(byte) = self.take().await? {
111                if byte == b'\r' || byte == b'\n' {
112                    terminated = true;
113                    break;
114                }
115            }
116            if !terminated && self.at < self.reader.stamp().length {
117                return Err(self.failure(Syntax::End, self.at));
118            }
119        }
120    }
121
122    pub(crate) async fn keyword(&mut self, expected: &[u8]) -> Result<(), ReadFailure<S::Error>> {
123        let start = self.at;
124        for &byte in expected {
125            if self.take().await? != Some(byte) {
126                return Err(self.failure(Syntax::Token, start));
127            }
128        }
129        if let Some(next) = self.peek().await?
130            && !boundary(next)
131        {
132            return Err(self.failure(Syntax::Token, self.at));
133        }
134        Ok(())
135    }
136
137    pub(crate) async fn looking(&mut self, expected: &[u8]) -> Result<bool, ReadFailure<S::Error>> {
138        let start = self.at;
139        for (index, &byte) in expected.iter().enumerate() {
140            let Some(at) = start.checked_add(index as u64) else {
141                return Ok(false);
142            };
143            if self.reader.byte_at(at).await? != Some(byte) {
144                return Ok(false);
145            }
146        }
147        Ok(true)
148    }
149
150    pub(crate) async fn natural(&mut self) -> Result<u64, ReadFailure<S::Error>> {
151        let at = self.at;
152        let (integer, real) = self.number().await?;
153        if !matches!(real, NumberKind::Integer) || integer.negative {
154            return Err(self.failure(Syntax::Number, at));
155        }
156        integer.magnitude.ok_or_else(|| {
157            Error {
158                kind: ErrorKind::Unsupported(crate::error::Unsupported::NumericRange),
159                location: self.location(at, self.at - at),
160            }
161            .into()
162        })
163    }
164
165    pub(crate) async fn space(&mut self) -> Result<(), ReadFailure<S::Error>> {
166        while self.peek().await?.is_some_and(is_space) {
167            self.at += 1;
168        }
169        Ok(())
170    }
171
172    async fn name<W: Work>(
173        &mut self,
174        names: &mut OwnedVec<u8, W>,
175    ) -> Result<Name, ReadFailure<S::Error>> {
176        let start = names.len();
177        self.at += 1; // leading slash was already inspected
178        let mut decoder = Decoder::new(Form::Name);
179        loop {
180            let input = match self.peek().await? {
181                Some(byte) if !boundary(byte) => Some(byte),
182                _ => None,
183            };
184            match decoder.step(input) {
185                Step::More => {
186                    debug_assert!(input.is_some());
187                    self.at += 1;
188                }
189                Step::Byte { value, consumed } => {
190                    if consumed {
191                        self.at += 1;
192                    }
193                    names
194                        .try_push(value)
195                        .map_err(|cause| refused(cause, self.location(self.at, 0)))?;
196                }
197                Step::End => break,
198                Step::Malformed => return Err(self.failure(Syntax::Name, self.at)),
199            }
200        }
201        Ok(Name {
202            start,
203            length: names.len() - start,
204        })
205    }
206
207    async fn literal(
208        &mut self,
209        session: &Session,
210        outer_depth: u64,
211    ) -> Result<(), ReadFailure<S::Error>> {
212        let start = self.at;
213        self.at += 1;
214        let mut depth = 1;
215        let mut escaped = false;
216        check_depth(session, outer_depth + depth, self.location(start, 1))?;
217        while let Some(byte) = self.take().await? {
218            if escaped {
219                escaped = false;
220                continue;
221            }
222            match byte {
223                b'\\' => escaped = true,
224                b'(' => {
225                    depth += 1;
226                    check_depth(session, outer_depth + depth, self.location(self.at - 1, 1))?;
227                }
228                b')' => {
229                    depth -= 1;
230                    if depth == 0 {
231                        return Ok(());
232                    }
233                }
234                _ => {}
235            }
236        }
237        Err(self.failure(Syntax::String, self.at))
238    }
239
240    async fn hexadecimal(&mut self) -> Result<(), ReadFailure<S::Error>> {
241        let mut decoder = Decoder::new(Form::Hexadecimal);
242        loop {
243            let Some(byte) = self.take().await? else {
244                return Err(self.failure(Syntax::String, self.at));
245            };
246            if byte == b'>' {
247                match decoder.step(None) {
248                    Step::End | Step::Byte { .. } => return Ok(()),
249                    _ => return Err(self.failure(Syntax::String, self.at - 1)),
250                }
251            }
252            if matches!(decoder.step(Some(byte)), Step::Malformed) {
253                return Err(self.failure(Syntax::String, self.at - 1));
254            }
255        }
256    }
257
258    pub(crate) async fn number(&mut self) -> Result<(Integer, NumberKind), ReadFailure<S::Error>> {
259        let start = self.at;
260        let negative = self.peek().await? == Some(b'-');
261        if matches!(self.peek().await?, Some(b'+' | b'-')) {
262            self.at += 1;
263        }
264        let mut magnitude = Some(0_u64);
265        let mut real = false;
266        let mut fractional = false;
267        let mut digits = 0_u64;
268        while let Some(byte) = self.peek().await? {
269            if byte.is_ascii_digit() {
270                if real {
271                    fractional |= byte != b'0';
272                } else {
273                    magnitude = magnitude.and_then(|value| {
274                        value
275                            .checked_mul(10)
276                            .and_then(|value| value.checked_add(u64::from(byte - b'0')))
277                    });
278                }
279                digits += 1;
280                self.at += 1;
281                continue;
282            }
283            if byte == b'.' && !real {
284                real = true;
285                self.at += 1;
286                continue;
287            }
288            if boundary(byte) {
289                break;
290            }
291            return Err(self.failure(Syntax::Number, self.at));
292        }
293        if digits == 0 {
294            return Err(self.failure(Syntax::Number, start));
295        }
296        Ok((
297            Integer {
298                negative,
299                magnitude,
300            },
301            if real {
302                NumberKind::Real { fractional }
303            } else {
304                NumberKind::Integer
305            },
306        ))
307    }
308
309    async fn reference(
310        &mut self,
311        first: Integer,
312    ) -> Result<Option<(u64, u16)>, ReadFailure<S::Error>> {
313        let after_first = self.at;
314        self.skip().await?;
315        if self.at == after_first || !matches!(self.peek().await?, Some(b'0'..=b'9')) {
316            return Ok(None);
317        }
318        let generation = match self.number().await {
319            Ok((integer, NumberKind::Integer)) => integer,
320            Ok(_) => return Ok(None),
321            // This is lookahead for a reference, not recovery from a parsed
322            // reference. The first INTEGER is independently valid; its caller
323            // will parse any unrelated malformed following token normally.
324            Err(ReadFailure::Format(error)) if error.kind == ErrorKind::Syntax(Syntax::Number) => {
325                return Ok(None);
326            }
327            Err(error) => return Err(error),
328        };
329        let after_generation = self.at;
330        self.skip().await?;
331        if self.at == after_generation || self.peek().await? != Some(b'R') {
332            return Ok(None);
333        }
334        self.at += 1;
335        if let Some(next) = self.peek().await?
336            && !boundary(next)
337        {
338            return Ok(None);
339        }
340        let (Some(number), Some(generation)) = (first.magnitude, generation.magnitude) else {
341            return Err(Error {
342                kind: ErrorKind::Unsupported(crate::error::Unsupported::NumericRange),
343                location: self.location(after_first, self.at - after_first),
344            }
345            .into());
346        };
347        let generation =
348            u16::try_from(generation).map_err(|_| self.failure(Syntax::Object, after_first))?;
349        Ok(Some((number, generation)))
350    }
351}
352
353fn boundary(byte: u8) -> bool {
354    is_space(byte)
355        || matches!(
356            byte,
357            b'(' | b')' | b'<' | b'>' | b'[' | b']' | b'{' | b'}' | b'/' | b'%'
358        )
359}
360
361fn location(start: u64, length: u64) -> Location {
362    Location::new(Source::File, start, length).expect("bounded original object range")
363}
364
365fn refused(cause: structured_asn1::memory::MemoryError, location: Location) -> Error {
366    Error {
367        kind: ErrorKind::Resource(cause),
368        location,
369    }
370}
371
372fn check_depth(session: &Session, depth: u64, location: Location) -> crate::Result<()> {
373    if depth > u64::from(session.limits().processing.max_depth) {
374        return Err(Error {
375            kind: ErrorKind::Limit(Limit::Depth),
376            location,
377        });
378    }
379    Ok(())
380}