Skip to content

Commit

Permalink
feat: add divz policy-expr func and fix some policies in legacy confi…
Browse files Browse the repository at this point in the history
…g file conversion
  • Loading branch information
j-lanson authored and alilleybrinker committed Sep 10, 2024
1 parent fbb958e commit 0766a6a
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 15 deletions.
4 changes: 2 additions & 2 deletions config/Hipcheck.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ analyze {

analysis "mitre/entropy" policy="(eq 0 (count (filter (gt 8.0) $)))" {
langs-file "./config/Langs.toml"
}
analysis "mitre/churn" policy="(eq 0 (count (filter (gt 8.0) $)))" {
}
analysis "mitre/churn" policy="(lte (divz (count (filter (gt 3) $)) (count $)) 0.02)" {
langs-file "./config/Langs.toml"
}
}
Expand Down
10 changes: 5 additions & 5 deletions hipcheck/src/policy/config_to_policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ fn parse_activity(
// Cap the weight at 65,533
let weight = activity.weight.try_into().unwrap_or(u16::MAX);
let threshold = activity.week_count_threshold;
let expression = format!("(lte {} $/weeks)", threshold);
let expression = format!("(lte $ {})", threshold);

// Add the plugin
let plugin = PolicyPlugin::new(
Expand Down Expand Up @@ -228,7 +228,7 @@ fn parse_identity(
// Cap the weight at 65,533
let weight = identity.weight.try_into().unwrap_or(u16::MAX);
let threshold = identity.percent_threshold;
let expression = format!("(lte {} $/pct_match)", threshold);
let expression = format!("(lte $ {})", threshold);

// Add the plugin
let plugin = PolicyPlugin::new(
Expand Down Expand Up @@ -265,7 +265,7 @@ fn parse_review(
// Cap the weight at 65,533
let weight = review.weight.try_into().unwrap_or(u16::MAX);
let threshold = review.percent_threshold;
let expression = format!("(lte {} $/pct_reviewed)", threshold);
let expression = format!("(lte $ {})", threshold);

// Add the plugin
let plugin = PolicyPlugin::new(
Expand Down Expand Up @@ -380,8 +380,8 @@ fn parse_churn(plugins: &mut PolicyPluginList, commit: &mut PolicyCategory, chur
let value_threshold = churn.value_threshold;
let percent_threshold = churn.percent_threshold;
let expression = format!(
"(eq {} (count (filter (gt {}) $)))",
percent_threshold, value_threshold
"(lte (divz (count (filter (gt {}) $)) (count $)) {})",
value_threshold, percent_threshold,
);

// Add the plugin
Expand Down
8 changes: 4 additions & 4 deletions hipcheck/src/policy/test_example.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ analyze {
investigate policy="(gt 0.5 $)"

category "practices" weight=1 {
analysis "mitre/activity" policy="(lte 71 $/weeks)" weight=1
analysis "mitre/activity" policy="(lte $ 71)" weight=1
analysis "mitre/binary" policy="(eq 0 (count $))" weight=1
analysis "mitre/fuzz" policy="(eq #t $)" weight=1
analysis "mitre/identity" policy="(lte 0.2 $/pct_match)" weight=1
analysis "mitre/review" policy="(lte 0.05 $/pct_reviewed)" weight=1
analysis "mitre/identity" policy="(lte $ 0.2)" weight=1
analysis "mitre/review" policy="(lte $ 0.05)" weight=1
}

category "attacks" weight=1 {
Expand All @@ -31,7 +31,7 @@ analyze {
orgs-file "./config/Orgs.toml"
}

analysis "mitre/churn" policy="(eq 0.02 (count (filter (gt 3) $)))" weight=1
analysis "mitre/churn" policy="(lte (divz (count (filter (gt 3) $)) (count $)) 0.02)" weight=1
analysis "mitre/entropy" policy="(eq 0 (count (filter (gt 10) $)))" weight=1
}
}
Expand Down
26 changes: 26 additions & 0 deletions hipcheck/src/policy_exprs/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ impl<'parent> Env<'parent> {
// Math functions.
env.add_fn("add", add);
env.add_fn("sub", sub);
env.add_fn("divz", divz);

// Logical functions.
env.add_fn("and", and);
Expand Down Expand Up @@ -396,6 +397,31 @@ fn sub(env: &Env, args: &[Expr]) -> Result<Expr> {
binary_primitive_op(name, env, args, op)
}

// Attempts to divide the numbers, returning a float. If
// the divisor is zero, returns 0 instead
fn divz(env: &Env, args: &[Expr]) -> Result<Expr> {
let name = "divz";

let op = |arg_1, arg_2| match (arg_1, arg_2) {
(Int(arg_1), Int(arg_2)) => Ok(if arg_2 == 0 {
Float(F64::new(0.0)?)
} else {
let f_arg_1 = arg_1 as f64;
let f_arg_2 = arg_2 as f64;
Float(F64::new(f_arg_1 / f_arg_2)?)
}),
(Float(arg_1), Float(arg_2)) => Ok(if arg_2 == 0.0 {
Float(arg_2)
} else {
Float(arg_1 / arg_2)
}),
(Bool(_), Bool(_)) => Err(Error::BadType(name)),
_ => unreachable!(),
};

binary_primitive_op(name, env, args, op)
}

fn and(env: &Env, args: &[Expr]) -> Result<Expr> {
let name = "and";

Expand Down
44 changes: 44 additions & 0 deletions hipcheck/src/policy_exprs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,50 @@ mod tests {
assert_eq!(result, Expr::Primitive(Primitive::Int(3)));
}

#[test]
fn eval_divz_int_zero() {
let program = "(divz 1 0)";
let context = Value::Null;
let result = Executor::std().parse_and_eval(program, &context).unwrap();
assert_eq!(
result,
Expr::Primitive(Primitive::Float(F64::new(0.0).unwrap()))
);
}

#[test]
fn eval_divz_int() {
let program = "(divz 1 2)";
let context = Value::Null;
let result = Executor::std().parse_and_eval(program, &context).unwrap();
assert_eq!(
result,
Expr::Primitive(Primitive::Float(F64::new(0.5).unwrap()))
);
}

#[test]
fn eval_divz_float() {
let program = "(divz 1.0 2.0)";
let context = Value::Null;
let result = Executor::std().parse_and_eval(program, &context).unwrap();
assert_eq!(
result,
Expr::Primitive(Primitive::Float(F64::new(0.5).unwrap()))
);
}

#[test]
fn eval_divz_float_zero() {
let program = "(divz 1.0 0.0)";
let context = Value::Null;
let result = Executor::std().parse_and_eval(program, &context).unwrap();
assert_eq!(
result,
Expr::Primitive(Primitive::Float(F64::new(0.0).unwrap()))
);
}

#[test]
fn eval_bools() {
let program = "(neq 1 2)";
Expand Down
6 changes: 2 additions & 4 deletions hipcheck/src/report/report_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,10 @@ pub fn build_report(session: &Session, scoring: &ScoringResults) -> Result<Repor
match &stored.response {
Ok(res) => {
let deps = {
let Value::Number(opt_deps) = &res.value else {
let Value::Array(opt_deps) = &res.value else {
return Err(hc_error!("typo analysis has a non-numeric value"));
};
opt_deps
.as_u64()
.ok_or(hc_error!("typo analysis has a non-u64 value"))?
opt_deps.len() as u64
};
let analysis = Analysis::typo(deps, stored.policy.clone(), stored.passed);
builder.add_analysis(analysis, res.concerns.clone())?;
Expand Down

0 comments on commit 0766a6a

Please sign in to comment.