mirror of
https://github.com/storytold/figcraft.git
synced 2026-11-02 16:29:34 -06:00
#821: text.loadFont reads at most MAX_FONT_FILE (the font scan's 256 MiB cap)
This commit is contained in:
@@ -362,15 +362,13 @@ fn free_spot(s: &Session, w: f64, h: f64) -> Result<(f64, f64)> {
|
||||
})
|
||||
}
|
||||
|
||||
/// The bytes of the file at `path`, within the session's allowed file roots.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(super) fn read_path(path: &str) -> Result<Vec<u8>> {
|
||||
fn read_path(path: &str) -> Result<Vec<u8>> {
|
||||
crate::file_access::read(path)
|
||||
}
|
||||
|
||||
/// The browser has no files to read: always an error.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub(super) fn read_path(path: &str) -> Result<Vec<u8>> {
|
||||
fn read_path(path: &str) -> Result<Vec<u8>> {
|
||||
Err(crate::EngineError::Other(format!("{path}: files can't be read in the browser")))
|
||||
}
|
||||
|
||||
|
||||
@@ -497,7 +497,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
let b64 = b64.split_once(',').map(|(_, d)| d.to_string()).unwrap_or(b64);
|
||||
base64::engine::general_purpose::STANDARD.decode(b64.trim()).map_err(|e| bad(cmd, format!("`data`: {e}")))?
|
||||
} else if let Some(path) = string(p, "path") {
|
||||
super::create::read_path(&path)?
|
||||
super::file::read_capped(&path, figcraft_text::fontdb::MAX_FONT_FILE)?
|
||||
} else {
|
||||
return Err(bad(cmd, "pass `path` or `data` (base64)"));
|
||||
};
|
||||
|
||||
@@ -819,13 +819,19 @@ fn scan_dir(dir: &std::path::Path, depth: usize, out: &mut BTreeMap<String, (Str
|
||||
// Very large files are indexed all the same (Apple Color Emoji is ~180 MB and is where the
|
||||
// system's colour emoji live): `index_bytes` reads headers and name tables out of a zeroed
|
||||
// buffer, so only those parts are ever touched.
|
||||
let Some(bytes) = usize::try_from(meta.len()).ok().filter(|l| *l <= 256 * 1024 * 1024).and_then(|l| index_bytes(&path, l)) else { continue };
|
||||
if meta.len() > MAX_FONT_FILE {
|
||||
continue;
|
||||
}
|
||||
let Some(bytes) = usize::try_from(meta.len()).ok().and_then(|l| index_bytes(&path, l)) else { continue };
|
||||
for (index, family, style) in faces_in(&bytes) {
|
||||
out.entry(family.to_lowercase()).or_insert_with(|| (family.clone(), Vec::new())).1.push(Pending { path: path.clone(), index, style });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The largest font file read (CJK collections run to ~120 MB, Apple Color Emoji ~180 MB).
|
||||
pub const MAX_FONT_FILE: u64 = 256 * 1024 * 1024;
|
||||
|
||||
/// The parts of a font file the scan reads: headers, table directories and `name` tables, at their
|
||||
/// offsets in a zeroed buffer of the file's length (reading whole files was most of the scan).
|
||||
fn index_bytes(path: &std::path::Path, len: usize) -> Option<Vec<u8>> {
|
||||
|
||||
Reference in New Issue
Block a user