Merge pull request #16 from storytold/pr/never-crash-small
Never crash: filters, fonts, js, optimize and a11y deny the panic lints
This commit is contained in:
commit
414060a3ff
|
|
@ -141,7 +141,7 @@ fn content_bbox(doc: &Document, page: &Dict, ids: &HashSet<i64>) -> Option<[f64;
|
|||
let mut path: Vec<(f64, f64)> = Vec::new();
|
||||
for op in printcraft_content::parse(&page_content(doc, page)).ops {
|
||||
let inside = marks.iter().any(|m| *m);
|
||||
let top = *ctm.last().expect("never empty");
|
||||
let top = ctm.last().copied().unwrap_or(Matrix([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]));
|
||||
match op.op.as_slice() {
|
||||
b"q" => ctm.push(top),
|
||||
b"Q" => {
|
||||
|
|
@ -150,8 +150,10 @@ fn content_bbox(doc: &Document, page: &Dict, ids: &HashSet<i64>) -> Option<[f64;
|
|||
}
|
||||
}
|
||||
b"cm" => {
|
||||
if let Some(m) = Matrix::from_operands(&op.operands) {
|
||||
*ctm.last_mut().expect("never empty") = m.then(&top);
|
||||
if let Some(m) = Matrix::from_operands(&op.operands)
|
||||
&& let Some(t) = ctm.last_mut()
|
||||
{
|
||||
*t = m.then(&top);
|
||||
}
|
||||
}
|
||||
b"BMC" => marks.push(false),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
//! accessibility report. Rules read the document only; the fixes that need edits (language,
|
||||
//! title, tab order) are applied by the engine.
|
||||
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use printcraft_cos::Document;
|
||||
|
|
|
|||
|
|
@ -67,9 +67,10 @@ fn inflate_raw(input: &[u8], max: usize) -> Step {
|
|||
}
|
||||
|
||||
/// zlib at level 6.
|
||||
// The documented never-crash exception: writing into a `Vec` cannot fail.
|
||||
#[allow(clippy::expect_used)]
|
||||
pub(crate) fn encode(data: &[u8]) -> Vec<u8> {
|
||||
let mut e = flate2::write::ZlibEncoder::new(Vec::with_capacity(data.len() / 2 + 64), Compression::new(6));
|
||||
// Writing into a Vec cannot fail.
|
||||
e.write_all(data).expect("in-memory write");
|
||||
e.finish().expect("in-memory write")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
//! Every decoder is bounded by a caller-supplied `max_output` (decompression-bomb
|
||||
//! defence) and never panics on malformed input.
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||||
|
||||
mod ascii85;
|
||||
mod asciihex;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
//! See the README: the metrics are approximations by character class (no vendor metrics files
|
||||
//! are bundled). The full font subsystem lands in M2.2/M7.
|
||||
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||||
|
||||
mod encodings;
|
||||
pub mod pdf;
|
||||
mod script;
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ impl Metrics {
|
|||
ascent: 0.9,
|
||||
descent: -0.25,
|
||||
composite: false,
|
||||
unicode: (32..127u32).map(|c| (c, char::from_u32(c).expect("ascii").to_string())).collect(),
|
||||
unicode: (32..127u8).map(|c| (u32::from(c), char::from(c).to_string())).collect(),
|
||||
base_font: "Helvetica".into(),
|
||||
subset: false,
|
||||
code_len: 1,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
//! are bounded. Side effects (alerts, field changes, resets, printing, navigation) are returned
|
||||
//! in an [`Outcome`] for the caller to apply.
|
||||
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
|
|
@ -200,8 +202,9 @@ struct Host {
|
|||
|
||||
type Shared = RefCell<Host>;
|
||||
|
||||
fn host(ctx: &Context) -> &Shared {
|
||||
ctx.get_data::<Shared>().expect("host state is installed before scripts run")
|
||||
/// The host state, installed before scripts run.
|
||||
fn host(ctx: &Context) -> JsResult<&Shared> {
|
||||
ctx.get_data::<Shared>().ok_or_else(|| error("the script host is not set up"))
|
||||
}
|
||||
|
||||
fn s(v: &str) -> JsValue {
|
||||
|
|
@ -267,17 +270,17 @@ fn colour(c: &Option<Vec<String>>, ctx: &mut Context) -> JsValue {
|
|||
|
||||
fn field_index(ctx: &Context, name: &JsString) -> JsResult<usize> {
|
||||
let n = name.to_std_string_escaped();
|
||||
host(ctx).borrow().fields.iter().position(|f| f.name == n).ok_or_else(|| error(format!("no field named {n}")))
|
||||
host(ctx)?.borrow().fields.iter().position(|f| f.name == n).ok_or_else(|| error(format!("no field named {n}")))
|
||||
}
|
||||
|
||||
fn read(ctx: &Context, name: &JsString) -> JsResult<FieldState> {
|
||||
let i = field_index(ctx, name)?;
|
||||
Ok(host(ctx).borrow().fields[i].clone())
|
||||
Ok(host(ctx)?.borrow().fields[i].clone())
|
||||
}
|
||||
|
||||
fn write(ctx: &Context, name: &JsString, change: impl FnOnce(&mut FieldState)) -> JsResult<()> {
|
||||
let i = field_index(ctx, name)?;
|
||||
let mut h = host(ctx).borrow_mut();
|
||||
let mut h = host(ctx)?.borrow_mut();
|
||||
change(&mut h.fields[i]);
|
||||
h.changed.insert(i);
|
||||
Ok(())
|
||||
|
|
@ -428,7 +431,7 @@ fn field_object(ctx: &mut Context, name: &str) -> JsObject {
|
|||
Ok(JsValue::undefined())
|
||||
}
|
||||
fn set_focus(_: &JsValue, _: &[JsValue], name: &JsString, c: &mut Context) -> JsResult<JsValue> {
|
||||
host(c).borrow_mut().requests.push(Request::Focus(name.to_std_string_escaped()));
|
||||
host(c)?.borrow_mut().requests.push(Request::Focus(name.to_std_string_escaped()));
|
||||
Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
|
|
@ -464,30 +467,30 @@ fn field_object(ctx: &mut Context, name: &str) -> JsObject {
|
|||
|
||||
fn get_field(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
|
||||
let name = text(&arg(args, 0), ctx)?;
|
||||
let exists = host(ctx).borrow().fields.iter().any(|f| f.name == name);
|
||||
let exists = host(ctx)?.borrow().fields.iter().any(|f| f.name == name);
|
||||
if exists {
|
||||
return Ok(field_object(ctx, &name).into());
|
||||
}
|
||||
// A parent name (e.g. "total" for "total.0"): its first kid stands in, as for groups.
|
||||
let prefix = format!("{name}.");
|
||||
let kid = host(ctx).borrow().fields.iter().find(|f| f.name.starts_with(&prefix)).map(|f| f.name.clone());
|
||||
let kid = host(ctx)?.borrow().fields.iter().find(|f| f.name.starts_with(&prefix)).map(|f| f.name.clone());
|
||||
Ok(kid.map_or(JsValue::null(), |k| field_object(ctx, &k).into()))
|
||||
}
|
||||
|
||||
fn get_nth_field_name(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
|
||||
let i = arg(args, 0).to_number(ctx)?;
|
||||
let name = host(ctx).borrow().fields.get(i.max(0.0) as usize).map(|f| f.name.clone());
|
||||
let name = host(ctx)?.borrow().fields.get(i.max(0.0) as usize).map(|f| f.name.clone());
|
||||
Ok(name.map_or(JsValue::null(), |n| s(&n)))
|
||||
}
|
||||
|
||||
fn reset_form(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
|
||||
let names = strings(&arg(args, 0), ctx)?;
|
||||
host(ctx).borrow_mut().requests.push(Request::Reset(names));
|
||||
host(ctx)?.borrow_mut().requests.push(Request::Reset(names));
|
||||
Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
fn print(_: &JsValue, _: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
|
||||
host(ctx).borrow_mut().requests.push(Request::Print);
|
||||
host(ctx)?.borrow_mut().requests.push(Request::Print);
|
||||
Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
|
|
@ -500,7 +503,7 @@ fn submit_form(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsV
|
|||
}
|
||||
_ => text(&a, ctx)?,
|
||||
};
|
||||
host(ctx).borrow_mut().requests.push(Request::Submit(url));
|
||||
host(ctx)?.borrow_mut().requests.push(Request::Submit(url));
|
||||
Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
|
|
@ -509,16 +512,16 @@ fn noop(_: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult<JsValue> {
|
|||
}
|
||||
|
||||
fn num_fields(_: &JsValue, _: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
|
||||
Ok(JsValue::from(host(ctx).borrow().fields.len() as f64))
|
||||
Ok(JsValue::from(host(ctx)?.borrow().fields.len() as f64))
|
||||
}
|
||||
|
||||
fn page_num_get(_: &JsValue, _: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
|
||||
Ok(JsValue::from(host(ctx).borrow().doc.page as f64))
|
||||
Ok(JsValue::from(host(ctx)?.borrow().doc.page as f64))
|
||||
}
|
||||
|
||||
fn page_num_set(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
|
||||
let n = arg(args, 0).to_number(ctx)?;
|
||||
let mut h = host(ctx).borrow_mut();
|
||||
let mut h = host(ctx)?.borrow_mut();
|
||||
let last = h.doc.num_pages.saturating_sub(1);
|
||||
let p = (n.max(0.0) as usize).min(last);
|
||||
h.doc.page = p;
|
||||
|
|
@ -541,19 +544,19 @@ fn message(v: &JsValue, key: &str, ctx: &mut Context) -> JsResult<String> {
|
|||
|
||||
fn alert(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
|
||||
let m = message(&arg(args, 0), "cMsg", ctx)?;
|
||||
host(ctx).borrow_mut().alerts.push(m);
|
||||
host(ctx)?.borrow_mut().alerts.push(m);
|
||||
// The OK button.
|
||||
Ok(JsValue::from(1))
|
||||
}
|
||||
|
||||
fn beep(_: &JsValue, _: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
|
||||
host(ctx).borrow_mut().requests.push(Request::Beep);
|
||||
host(ctx)?.borrow_mut().requests.push(Request::Beep);
|
||||
Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
fn launch_url(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
|
||||
let u = message(&arg(args, 0), "cURL", ctx)?;
|
||||
host(ctx).borrow_mut().requests.push(Request::LaunchUrl(u));
|
||||
host(ctx)?.borrow_mut().requests.push(Request::LaunchUrl(u));
|
||||
Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
|
|
@ -564,12 +567,12 @@ fn response(_: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult<JsValue> {
|
|||
|
||||
fn println(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
|
||||
let m = text(&arg(args, 0), ctx)?;
|
||||
host(ctx).borrow_mut().console.push(m);
|
||||
host(ctx)?.borrow_mut().console.push(m);
|
||||
Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
fn console_clear(_: &JsValue, _: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
|
||||
host(ctx).borrow_mut().console.clear();
|
||||
host(ctx)?.borrow_mut().console.clear();
|
||||
Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
|
|
@ -889,7 +892,7 @@ fn install(ctx: &mut Context) -> JsResult<()> {
|
|||
let pg = function(ctx, NativeFunction::from_fn_ptr(page_num_get));
|
||||
let ps = function(ctx, NativeFunction::from_fn_ptr(page_num_set));
|
||||
let (file, pages, info) = {
|
||||
let h = host(ctx).borrow();
|
||||
let h = host(ctx)?.borrow();
|
||||
(h.doc.file_name.clone(), h.doc.num_pages, h.doc.info.clone())
|
||||
};
|
||||
let mut io = ObjectInitializer::new(ctx);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ fn walk(doc: &Document, data: &[u8], resources: &Dict, ctm: Matrix, depth: usize
|
|||
let xobjects = resources.get(b"XObject").map(|x| doc.resolve(x)).and_then(|x| x.as_dict().cloned()).unwrap_or_default();
|
||||
let mut stack = vec![ctm];
|
||||
for op in printcraft_content::parse(data).ops {
|
||||
let top = *stack.last().expect("never empty");
|
||||
let top = stack.last().copied().unwrap_or(ctm);
|
||||
match op.op.as_slice() {
|
||||
b"q" => stack.push(top),
|
||||
b"Q" => {
|
||||
|
|
@ -59,8 +59,10 @@ fn walk(doc: &Document, data: &[u8], resources: &Dict, ctm: Matrix, depth: usize
|
|||
}
|
||||
}
|
||||
b"cm" => {
|
||||
if let Some(m) = Matrix::from_operands(&op.operands) {
|
||||
*stack.last_mut().expect("never empty") = m.then(&top);
|
||||
if let Some(m) = Matrix::from_operands(&op.operands)
|
||||
&& let Some(t) = stack.last_mut()
|
||||
{
|
||||
*t = m.then(&top);
|
||||
}
|
||||
}
|
||||
b"Do" => {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
//! fields are discarded by `printcraft-redact`'s Remove Hidden Information, which the engine
|
||||
//! runs alongside.
|
||||
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||||
|
||||
mod audit;
|
||||
mod images;
|
||||
mod links;
|
||||
|
|
|
|||
Loading…
Reference in New Issue