mirror of
https://github.com/storytold/craft-libs.git
synced 2026-10-31 15:49:54 +00:00
security: fallible bitmap allocation in vendored hayro-jbig2 (#242)
* security: fallible bitmap allocation in vendored hayro-jbig2 (follow-up to #239) * security: reinitialize allocates before mutating the jbig2 bitmap (CodeRabbit)
This commit is contained in:
1 parent
35d18945a9
commit
9def84d7a5
3 files changed
+29
-7
No files matched your search
Vendored
+2
-1
@@ -50,7 +50,8 @@ Hostile-input bounds (CodeRabbit findings):
|
||||
- Each object stream's `/N` header pairs are parsed once per document and cached beside its
|
||||
decoded data, instead of on every compressed-object lookup.
|
||||
- An embedded JBIG2 page over 2^28 pixels is refused before the output buffer is allocated,
|
||||
and that buffer is reserved fallibly. A `JBIG2Globals` stream with an image filter is
|
||||
and that buffer is reserved fallibly (`Bitmap::reinitialize` allocates before touching the
|
||||
existing bitmap, so a failed reservation leaves it intact). A `JBIG2Globals` stream with an image filter is
|
||||
ignored, so globals cannot recurse through further globals.
|
||||
- At most 4096 graphics states, holding at most 64 MiB together, are saved; a `q` past
|
||||
either limit is counted but not copied, and its `Q` still removes the clips added since.
|
||||
|
||||
Vendored
+1
-1
@@ -62,7 +62,7 @@
|
||||
"path": "src/bitmap.rs",
|
||||
"source_sha256": "59ed83d8bac6c39e40270a9856ca3faee628de7d9efae1b01f714e140e2b6b7e",
|
||||
"source_git_blob": "35ed97561597d30a70fe819cf8cfbd3780538f75",
|
||||
"sha256": "59ed83d8bac6c39e40270a9856ca3faee628de7d9efae1b01f714e140e2b6b7e"
|
||||
"sha256": "99dddbef5f7b36c55d0e914d07664326598919eb6d54cdfa93f300076a8ae69d"
|
||||
},
|
||||
{
|
||||
"path": "src/decode/generic.rs",
|
||||
|
||||
Vendored
+26
-5
@@ -7,7 +7,6 @@
|
||||
|
||||
use crate::decode::CombinationOperator;
|
||||
use crate::error::{OverflowError, Result, bail};
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
// To guard better against malicious files, we limit bitmap dimensions
|
||||
@@ -50,6 +49,14 @@ pub(crate) struct Bitmap {
|
||||
pub(crate) y_location: u32,
|
||||
}
|
||||
|
||||
/// PdfCraft patch: fallible replacement for `vec![word; len]` / `resize`.
|
||||
fn fill_words(data: &mut Vec<Word>, len: usize, word: Word) -> Result<()> {
|
||||
data.try_reserve_exact(len)
|
||||
.map_err(|_| OverflowError::BitmapDimension)?;
|
||||
data.resize(len, word);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Bitmap {
|
||||
/// Create a new bitmap filled with white pixels (false).
|
||||
///
|
||||
@@ -76,7 +83,9 @@ impl Bitmap {
|
||||
|
||||
let stride = width.div_ceil(WORD_BITS);
|
||||
let default_word: Word = if default_pixel { !0 } else { 0 };
|
||||
let data = vec![default_word; stride as usize * height as usize];
|
||||
// PdfCraft patch: reserve fallibly so hostile dimensions error instead of aborting.
|
||||
let mut data = Vec::new();
|
||||
fill_words(&mut data, stride as usize * height as usize, default_word)?;
|
||||
Ok(Self {
|
||||
width,
|
||||
height,
|
||||
@@ -103,14 +112,15 @@ impl Bitmap {
|
||||
|
||||
let stride = width.div_ceil(WORD_BITS);
|
||||
let default_word: Word = if default_pixel { !0 } else { 0 };
|
||||
// Allocate first so a failed reservation leaves the bitmap untouched.
|
||||
let mut data = Vec::new();
|
||||
fill_words(&mut data, stride as usize * height as usize, default_word)?;
|
||||
self.width = width;
|
||||
self.height = height;
|
||||
self.stride = stride;
|
||||
self.x_location = 0;
|
||||
self.y_location = 0;
|
||||
self.data.clear();
|
||||
self.data
|
||||
.resize(stride as usize * height as usize, default_word);
|
||||
self.data = data;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -225,3 +235,14 @@ impl Bitmap {
|
||||
self.data[(row * self.stride + word_idx) as usize]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn failed_reservation_is_an_error() {
|
||||
let mut data = Vec::new();
|
||||
assert!(fill_words(&mut data, usize::MAX / 2, 0).is_err());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user