mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 10:08:00 -06:00
M1.3: number parser cut a multi-byte token mid-character and panicked (found by fuzzing)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
6ea1402424
commit
24418ae3c5
@@ -323,7 +323,11 @@ impl<'a> Lexer<'a> {
|
||||
let cleaned: String = s.trim_start_matches('+').replacen("--", "-", 1);
|
||||
let mut end = cleaned.len();
|
||||
while end > 0 {
|
||||
if let Ok(v) = cleaned[..end].parse::<f64>() {
|
||||
// Only cut at character boundaries: a token can hold multi-byte UTF-8 (fuzzing
|
||||
// found ".—", which panicked here).
|
||||
if cleaned.is_char_boundary(end)
|
||||
&& let Ok(v) = cleaned[..end].parse::<f64>()
|
||||
{
|
||||
return Ok(Object::Real(v));
|
||||
}
|
||||
end -= 1;
|
||||
@@ -429,6 +433,17 @@ fn find_endstream(data: &[u8], from: usize) -> Option<usize> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn numbers_with_multibyte_garbage_do_not_panic() {
|
||||
// From `cargo xtask fuzz`: "2 0 obj\n.\u{2014}" (an em dash after a dot).
|
||||
let doc = crate::Document::open(std::sync::Arc::new("2 0 obj\n.\u{2014}\n".as_bytes().to_vec()));
|
||||
assert!(doc.is_err());
|
||||
for t in [".\u{2014}", "1.\u{e9}5", "-.\u{1F600}", "+.5\u{2014}"] {
|
||||
let _ = Lexer::new(t.as_bytes(), 0).object();
|
||||
}
|
||||
assert_eq!(Lexer::new("1.5\u{2014}".as_bytes(), 0).object().unwrap(), Object::Real(1.5));
|
||||
}
|
||||
|
||||
fn obj(s: &str) -> Object {
|
||||
Lexer::new(s.as_bytes(), 0).object().unwrap_or_else(|e| panic!("{s}: {e}"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user