diff --git a/hipcheck/src/config.rs b/hipcheck/src/config.rs index 720ee535..fa7f9d8c 100644 --- a/hipcheck/src/config.rs +++ b/hipcheck/src/config.rs @@ -13,13 +13,12 @@ use crate::{ policy_exprs::{std_parse, Expr}, score::*, util::fs as file, - BINARY_CONFIG_FILE, F64, LANGS_FILE, ORGS_FILE, TYPO_FILE, + F64, }; use indextree::{Arena, NodeEdge, NodeId}; use num_traits::identities::Zero; use pathbuf::pathbuf; use serde::{Deserialize, Serialize}; -use serde_json::Value; use smart_default::SmartDefault; use std::{ collections::HashMap, @@ -472,47 +471,6 @@ pub trait RiskConfigQuery: ConfigSource { fn risk_policy(&self) -> Result>; } -/// Query for accessing the languages analysis config -#[salsa::query_group(LanguagesConfigQueryStorage)] -pub trait LanguagesConfigQuery: ConfigSource { - /// Returns the langs file path relative to the config file - fn langs_file_rel(&self) -> Rc; - /// Returns the langs file absolute path - fn langs_file(&self) -> Result>; -} - -/// Queries for accessing the practices analysis config -#[salsa::query_group(PracticesConfigQueryStorage)] -pub trait PracticesConfigQuery: ConfigSource { - /// Returns the binary formats file path relative to the - /// config file - fn binary_formats_file_rel(&self) -> Rc; - /// Returns the binary formats file absolute path - fn binary_formats_file(&self) -> Result>; -} - -/// Queries for accessing the attacks analysis config -#[salsa::query_group(AttacksConfigQueryStorage)] -pub trait AttacksConfigQuery: CommitConfigQuery { - /// Returns the typo file path relative to the config file - fn typo_file_rel(&self) -> Rc; - /// Returns the typo file absolute path - fn typo_file(&self) -> Result>; -} - -/// Queries for accessing the commit analysis config -#[salsa::query_group(CommitConfigQueryStorage)] -pub trait CommitConfigQuery: ConfigSource { - /// Returns the orgs file path relative to the config file - fn orgs_file_rel(&self) -> Rc; - /// Returns the orgs file absolute path - fn orgs_file(&self) -> Result>; - /// Returns the contributor trust analysis count threshold - fn contributor_trust_value_threshold(&self) -> Result; - /// Returns the contributor trust analysis month threshold - fn contributor_trust_month_count_threshold(&self) -> Result; -} - pub static DEFAULT_QUERY: &str = ""; #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -875,138 +833,3 @@ fn risk_policy(db: &dyn RiskConfigQuery) -> Result> { Ok(Rc::new(expr)) } - -fn langs_file_rel(_db: &dyn LanguagesConfigQuery) -> Rc { - Rc::new(LANGS_FILE.to_string()) -} - -fn langs_file(db: &dyn LanguagesConfigQuery) -> Result> { - if let Some(config_dir) = db.config_dir() { - return Ok(Rc::new(pathbuf![ - config_dir.as_ref(), - db.langs_file_rel().as_ref() - ])); - } - - let options = vec!["mitre/churn", "mitre/entropy"]; - let policy_file = db.policy(); - for opt in options { - if let Some(langs_config) = policy_file.get_config(opt) { - if let Some(v_filepath) = langs_config.get("langs-file") { - let Value::String(filepath) = v_filepath else { - return Err(hc_error!("'langs-file' was not a string")); - }; - return Ok(Rc::new(Path::new(&filepath).to_path_buf())); - } - }; - } - - Err(hc_error!("Cannot find path to languages config file in policy file. This file is necessary for running the linguist analysis.")) -} - -fn binary_formats_file_rel(_db: &dyn PracticesConfigQuery) -> Rc { - Rc::new(BINARY_CONFIG_FILE.to_string()) -} - -fn binary_formats_file(db: &dyn PracticesConfigQuery) -> Result> { - if let Some(config_dir) = db.config_dir() { - return Ok(Rc::new(pathbuf![ - config_dir.as_ref(), - db.binary_formats_file_rel().as_ref() - ])); - } - - let policy_file = db.policy(); - if let Some(binary_config) = policy_file.get_config("mitre/binary") { - if let Some(v_filepath) = binary_config.get("binary-file") { - let Value::String(filepath) = v_filepath else { - return Err(hc_error!("'binary-file' was not a string")); - }; - return Ok(Rc::new(Path::new(&filepath).to_path_buf())); - } - }; - - Err(hc_error!("Cannot find path to binary config file in policy file. This file is necessary for running the binary analysis.")) -} - -fn typo_file_rel(_db: &dyn AttacksConfigQuery) -> Rc { - Rc::new(TYPO_FILE.to_string()) -} - -fn typo_file(db: &dyn AttacksConfigQuery) -> Result> { - if let Some(config_dir) = db.config_dir() { - return Ok(Rc::new(pathbuf![ - config_dir.as_ref(), - db.typo_file_rel().as_ref() - ])); - } - - let policy_file = db.policy(); - if let Some(typo_config) = policy_file.get_config("mitre/typo") { - if let Some(v_filepath) = typo_config.get("typo-file") { - let Value::String(filepath) = v_filepath else { - return Err(hc_error!("'typo-file' was not a string")); - }; - return Ok(Rc::new(Path::new(&filepath).to_path_buf())); - } - }; - - Err(hc_error!("Cannot find path to typo config file in policy file. This file is necessary for running the typo analysis.")) -} - -fn orgs_file_rel(_db: &dyn CommitConfigQuery) -> Rc { - Rc::new(ORGS_FILE.to_string()) -} - -fn orgs_file(db: &dyn CommitConfigQuery) -> Result> { - if let Some(config_dir) = db.config_dir() { - return Ok(Rc::new(pathbuf![ - config_dir.as_ref(), - db.orgs_file_rel().as_ref() - ])); - } - - let policy_file = db.policy(); - if let Some(affiliation_config) = policy_file.get_config("mitre/affiliation") { - if let Some(v_filepath) = affiliation_config.get("orgs-file") { - let Value::String(filepath) = v_filepath else { - return Err(hc_error!("'orgs-file' was not a string")); - }; - return Ok(Rc::new(Path::new(&filepath).to_path_buf())); - } - }; - - Err(hc_error!("Cannot find path to orgs config file in policy file. This file is necessary for running the affiliation analysis.")) -} - -fn contributor_trust_value_threshold(db: &dyn CommitConfigQuery) -> Result { - let policy_file = db.policy(); - if let Some(trust_config) = policy_file.get_config("mitre/contributor-trust") { - if let Some(v_threshold) = trust_config.get("value-threshold") { - let Value::Number(threshold) = v_threshold else { - return Err(hc_error!("'value-threshold' was not a number")); - }; - return threshold - .as_u64() - .ok_or_else(|| hc_error!("'value-threshold' was too large to be a u64")); - } - }; - - Err(hc_error!("Cannot find config for contributor trust value in policy file. This file is necessary for running the commit trust analysis.")) -} - -fn contributor_trust_month_count_threshold(db: &dyn CommitConfigQuery) -> Result { - let policy_file = db.policy(); - if let Some(trust_config) = policy_file.get_config("mitre/contributor-trust") { - if let Some(v_threshold) = trust_config.get("month-count-threshold") { - let Value::Number(threshold) = v_threshold else { - return Err(hc_error!("'month-count-threshold' was not a number")); - }; - return threshold - .as_u64() - .ok_or_else(|| hc_error!("'month-count-threshold' was too large to be a u64")); - } - }; - - Err(hc_error!("Cannot find config for contributor trust month threshold in policy file. This file is necessary for running the commit trust analysis.")) -} diff --git a/hipcheck/src/main.rs b/hipcheck/src/main.rs index b3304ed0..d5dcd17e 100644 --- a/hipcheck/src/main.rs +++ b/hipcheck/src/main.rs @@ -755,12 +755,6 @@ fn print_missing() { /// An `f64` that is never `NaN`. type F64 = ordered_float::NotNan; -// Global variables for toml files per issue 157 config updates -const LANGS_FILE: &str = "Langs.toml"; -const BINARY_CONFIG_FILE: &str = "Binary.toml"; -const TYPO_FILE: &str = "Typos.toml"; -const ORGS_FILE: &str = "Orgs.toml"; - // Constants for exiting with error codes. /// Indicates the program failed. const EXIT_FAILURE: i32 = 1; diff --git a/hipcheck/src/policy_exprs/env.rs b/hipcheck/src/policy_exprs/env.rs index 3358b985..31f0db6c 100644 --- a/hipcheck/src/policy_exprs/env.rs +++ b/hipcheck/src/policy_exprs/env.rs @@ -2,20 +2,16 @@ use crate::policy_exprs::{ expr::{ - ArrayType as ExprArrayType, FuncReturnType, Function, FunctionDef, FunctionType, Op, - OpInfo, PrimitiveType, ReturnableType, Type, TypeChecker, Typed, + ArrayType as ExprArrayType, Function, FunctionDef, FunctionType, Op, PrimitiveType, + ReturnableType, Type, TypeChecker, Typed, }, pass::ExprMutator, - Array as StructArray, Error, Expr, ExprVisitor, Function as StructFunction, Ident, - Lambda as StructLambda, Primitive, Result, F64, + Array as StructArray, Error, Expr, Function as StructFunction, Ident, Lambda as StructLambda, + Primitive, Result, F64, }; use itertools::Itertools as _; use jiff::{Span, Zoned}; -use std::{ - cmp::{Ordering, PartialEq}, - collections::HashMap, - ops::Not as _, -}; +use std::{cmp::Ordering, collections::HashMap, ops::Not as _}; use Expr::*; use Primitive::*; @@ -80,7 +76,7 @@ fn ty_filter(args: &[Type]) -> Result { ReturnableType::Primitive(PrimitiveType::Bool) | ReturnableType::Unknown => { Ok(ReturnableType::Array(arr_ty)) } - a => Err(Error::BadFuncArgType { + _ => Err(Error::BadFuncArgType { name: "".to_owned(), idx: 0, expected: "a bool-returning lambda".to_owned(), @@ -110,7 +106,7 @@ fn ty_higher_order_bool_fn(args: &[Type]) -> Result { ReturnableType::Primitive(PrimitiveType::Bool) | ReturnableType::Unknown => { Ok(ReturnableType::Primitive(PrimitiveType::Bool)) } - a => Err(Error::BadFuncArgType { + _ => Err(Error::BadFuncArgType { name: "".to_owned(), idx: 0, expected: "a bool-returning lambda".to_owned(), @@ -180,7 +176,6 @@ fn ty_divz(args: &[Type]) -> Result { let opt_ty_1 = expect_primitive_at(args, 0)?; let opt_ty_2 = expect_primitive_at(args, 1)?; use PrimitiveType::*; - use ReturnableType::*; let (bad, idx) = match (opt_ty_1, opt_ty_2) { (None | Some(Int | Float), None | Some(Int | Float)) => return Ok(Float.into()), @@ -265,13 +260,12 @@ fn ty_comp(args: &[Type]) -> Result { }) } -fn ty_count(args: &[Type]) -> Result { +fn ty_count(_args: &[Type]) -> Result { Ok(PrimitiveType::Int.into()) } fn ty_avg(args: &[Type]) -> Result { use PrimitiveType::*; - use ReturnableType::*; let arr_ty = expect_array_at(args, 0)?; match arr_ty { None | Some(Int) | Some(Float) => Ok(Float.into()), @@ -286,11 +280,10 @@ fn ty_avg(args: &[Type]) -> Result { fn ty_duration(args: &[Type]) -> Result { use PrimitiveType::*; - use ReturnableType::*; let opt_ty_1 = expect_primitive_at(args, 0)?; let opt_ty_2 = expect_primitive_at(args, 1)?; match opt_ty_1 { - None | (Some(DateTime)) => (), + None | Some(DateTime) => (), Some(got) => { return Err(Error::BadFuncArgType { name: "".to_owned(), @@ -301,7 +294,7 @@ fn ty_duration(args: &[Type]) -> Result { } } match opt_ty_2 { - None | (Some(DateTime)) => (), + None | Some(DateTime) => (), Some(got) => { return Err(Error::BadFuncArgType { name: "".to_owned(), @@ -316,9 +309,8 @@ fn ty_duration(args: &[Type]) -> Result { fn ty_bool_unary(args: &[Type]) -> Result { use PrimitiveType::*; - use ReturnableType::*; match expect_primitive_at(args, 0)? { - None | (Some(Bool)) => Ok(PrimitiveType::Bool.into()), + None | Some(Bool) => Ok(PrimitiveType::Bool.into()), Some(got) => Err(Error::BadFuncArgType { name: "".to_owned(), idx: 0, @@ -330,11 +322,10 @@ fn ty_bool_unary(args: &[Type]) -> Result { fn ty_bool_binary(args: &[Type]) -> Result { use PrimitiveType::*; - use ReturnableType::*; let opt_ty_1 = expect_primitive_at(args, 0)?; let opt_ty_2 = expect_primitive_at(args, 1)?; match opt_ty_1 { - None | (Some(Bool)) => (), + None | Some(Bool) => (), Some(got) => { return Err(Error::BadFuncArgType { name: "".to_owned(), @@ -345,7 +336,7 @@ fn ty_bool_binary(args: &[Type]) -> Result { } } match opt_ty_2 { - None | (Some(Bool)) => (), + None | Some(Bool) => (), Some(got) => { return Err(Error::BadFuncArgType { name: "".to_owned(), @@ -369,8 +360,6 @@ impl Env<'_> { /// Create the standard environment. pub fn std() -> Self { - use FuncReturnType::*; - use PrimitiveType::*; let mut env = Env::empty(); // Comparison functions. @@ -821,7 +810,6 @@ fn add(env: &Env, args: &[Expr]) -> Result { .map_err(|err| Error::Datetime(err.to_string()))?, )), (_, _) => Err(Error::BadType(name)), - _ => unreachable!(), }; binary_primitive_op(name, env, args, op) @@ -847,7 +835,6 @@ fn sub(env: &Env, args: &[Expr]) -> Result { .map_err(|err| Error::Datetime(err.to_string()))?, )), (_, _) => Err(Error::BadType(name)), - _ => unreachable!(), }; binary_primitive_op(name, env, args, op) @@ -872,7 +859,6 @@ fn divz(env: &Env, args: &[Expr]) -> Result { Float(arg_1 / arg_2) }), (_, _) => Err(Error::BadType(name)), - _ => unreachable!(), }; binary_primitive_op(name, env, args, op) @@ -889,7 +875,6 @@ fn duration(env: &Env, args: &[Expr]) -> Result { .map_err(|err| Error::Datetime(err.to_string()))?, )), (_, _) => Err(Error::BadType(name)), - _ => unreachable!(), }; binary_primitive_op(name, env, args, op) @@ -901,7 +886,6 @@ fn and(env: &Env, args: &[Expr]) -> Result { let op = |arg_1, arg_2| match (arg_1, arg_2) { (Bool(arg_1), Bool(arg_2)) => Ok(Bool(arg_1 && arg_2)), (_, _) => Err(Error::BadType(name)), - _ => unreachable!(), }; binary_primitive_op(name, env, args, op) @@ -913,7 +897,6 @@ fn or(env: &Env, args: &[Expr]) -> Result { let op = |arg_1, arg_2| match (arg_1, arg_2) { (Bool(arg_1), Bool(arg_2)) => Ok(Bool(arg_1 || arg_2)), (_, _) => Err(Error::BadType(name)), - _ => unreachable!(), }; binary_primitive_op(name, env, args, op) diff --git a/hipcheck/src/policy_exprs/expr.rs b/hipcheck/src/policy_exprs/expr.rs index a8ffdaac..4d2bbdad 100644 --- a/hipcheck/src/policy_exprs/expr.rs +++ b/hipcheck/src/policy_exprs/expr.rs @@ -16,13 +16,7 @@ use nom::{ }; use ordered_float::NotNan; use serde_with::{DeserializeFromStr, SerializeDisplay}; -use std::{ - cmp::Ordering, - fmt::Display, - mem::{discriminant, Discriminant}, - ops::Deref, - sync::LazyLock, -}; +use std::{cmp::Ordering, fmt::Display, ops::Deref}; #[cfg(test)] use jiff::civil::Date; @@ -65,13 +59,6 @@ impl From for Expr { /// Helper type for operation function pointer. pub type Op = fn(&Env, &[Expr]) -> Result; -#[derive(Clone, PartialEq, Debug, Eq)] -pub struct OpInfo { - pub fn_ty: FuncReturnType, - pub expected_args: usize, - pub op: Op, -} - pub type TypeChecker = fn(&[Type]) -> Result; #[derive(Clone, PartialEq, Debug, Eq)] @@ -114,7 +101,7 @@ impl FunctionDef { .iter() .map(|a| a.get_type()) .collect::>>()?; - self.type_check(types.as_slice()); + self.type_check(types.as_slice())?; (self.op)(env, args) } } @@ -261,15 +248,6 @@ impl From for ReturnableType { } } -// We allow overloaded functions, such that the returned type is dependent on -// the input operand types. This enum encapsulates both static and dynamically -// determined return types. -#[derive(Debug, Clone, PartialEq, Eq, Copy)] -pub enum FuncReturnType { - Dynamic(fn(&[Type]) -> Result), - Static(ReturnableType), -} - // A function signature is the combination of the return type and the arg types #[derive(Debug, Clone, PartialEq, Eq)] pub struct FunctionType { @@ -355,8 +333,6 @@ impl Typed for Array { impl Typed for Function { fn get_type(&self) -> Result { - use FuncReturnType::*; - // Can't get a type if we haven't resolved the function let Some(def) = self.opt_def.clone() else { return Err(Error::UnknownFunction(self.ident.0.clone())); @@ -632,13 +608,9 @@ pub fn json_ptr(name: &str) -> Expr { #[cfg(test)] mod tests { use super::*; - use crate::policy_exprs::LexingError; use test_log::test; - use jiff::{ - tz::{self, TimeZone}, - Span, Timestamp, Zoned, - }; + use jiff::{tz::TimeZone, Span, Timestamp, Zoned}; trait IntoExpr { fn into_expr(self) -> Expr; diff --git a/hipcheck/src/policy_exprs/mod.rs b/hipcheck/src/policy_exprs/mod.rs index 9d654327..f897e1de 100644 --- a/hipcheck/src/policy_exprs/mod.rs +++ b/hipcheck/src/policy_exprs/mod.rs @@ -1,7 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -#![allow(unused)] - mod bridge; mod env; mod error; @@ -14,10 +12,7 @@ use crate::policy_exprs::env::Env; pub(crate) use crate::policy_exprs::{bridge::Tokens, expr::F64}; pub use crate::policy_exprs::{ error::{Error, Result}, - expr::{ - Array, Expr, Function, Ident, JsonPointer, Lambda, PrimitiveType, ReturnableType, Type, - Typed, - }, + expr::{Array, Expr, Function, Ident, JsonPointer, Lambda}, pass::{ExprMutator, ExprVisitor, FunctionResolver, TypeChecker, TypeFixer}, token::LexingError, }; @@ -64,7 +59,7 @@ pub fn std_parse(raw_program: &str) -> Result { std_pre_analysis_pipeline(parse(raw_program)?) } -pub fn std_exec(mut expr: Expr, context: Option<&Value>) -> Result { +pub fn std_exec(expr: Expr, context: Option<&Value>) -> Result { match std_post_analysis_pipeline(expr, context, false)? { Expr::Primitive(Primitive::Bool(b)) => Ok(b), result => Err(Error::DidNotReturnBool(result)), @@ -80,10 +75,12 @@ impl FromStr for Expr { } /// Evaluates `deke` expressions. +#[cfg(test)] pub struct Executor { env: Env<'static>, } +#[cfg(test)] impl Executor { /// Create an `Executor` with the standard set of functions defined. pub fn std() -> Self { @@ -162,6 +159,7 @@ impl ExprMutator for Env<'_> { #[cfg(test)] mod tests { use super::*; + use crate::policy_exprs::expr::{PrimitiveType, ReturnableType, Type}; use test_log::test; #[test] @@ -336,7 +334,6 @@ mod tests { fn eval_datetime_span_add() { let date = "2024-09-26"; let span = "P1w"; - let eval_fmt = "(add {} {})"; let context = Value::Null; let expected = parse("2024-10-03").unwrap(); let result1 = Executor::std() @@ -417,7 +414,6 @@ mod tests { let mut expr = parse(program).unwrap(); expr = FunctionResolver::std().run(expr).unwrap(); let res_ty = TypeChecker::default().run(&expr); - println!("RESTY: {res_ty:?}"); let Ok(Type::Function(f_ty)) = res_ty else { panic!() }; diff --git a/hipcheck/src/policy_exprs/pass.rs b/hipcheck/src/policy_exprs/pass.rs index 0e398402..28bb999a 100644 --- a/hipcheck/src/policy_exprs/pass.rs +++ b/hipcheck/src/policy_exprs/pass.rs @@ -99,7 +99,7 @@ impl ExprMutator for FunctionResolver { let new_body = self.visit_function(func.body)?; func.body = match new_body { Expr::Function(f) => f, - other => { + _ => { return Err(Error::InternalError( "FunctionResolver's `visit_function` impl should always return a function" .to_owned(), @@ -169,14 +169,13 @@ impl ExprMutator for TypeFixer { let fn_ty = func.get_type()?; // At this point we know it has info match fn_ty { - Type::Function(ft) => Ok(func.into()), - Type::Lambda(lt) => { + Type::Function(_) => Ok(func.into()), + Type::Lambda(_) => { // Have to feed the new expr through the current pass again // for any additional transformations let res = partially_evaluate(&self.env, &func.ident.0, func.args.remove(0))?; self.visit_expr(res) } - _ => unreachable!(), } } diff --git a/hipcheck/src/policy_exprs/token.rs b/hipcheck/src/policy_exprs/token.rs index a3ae119e..d9776c3b 100644 --- a/hipcheck/src/policy_exprs/token.rs +++ b/hipcheck/src/policy_exprs/token.rs @@ -2,10 +2,9 @@ use crate::policy_exprs::error::JiffError; use crate::policy_exprs::F64; -use git2::Time; use jiff::{ civil::{Date, DateTime}, - tz::{self, TimeZone}, + tz::TimeZone, Span, Timestamp, Zoned, }; use logos::{Lexer, Logos}; @@ -221,10 +220,7 @@ pub enum LexingError { #[cfg(test)] mod tests { use crate::policy_exprs::{token::Token, Error::Lex, LexingError, Result, F64}; - use jiff::{ - tz::{self, TimeZone}, - Span, Timestamp, Zoned, - }; + use jiff::{tz::TimeZone, Span, Timestamp, Zoned}; use logos::Logos as _; use test_log::test; diff --git a/hipcheck/src/session/mod.rs b/hipcheck/src/session/mod.rs index 1ae5fcae..0edca44a 100644 --- a/hipcheck/src/session/mod.rs +++ b/hipcheck/src/session/mod.rs @@ -8,9 +8,8 @@ use crate::{ cache::plugin::HcPluginCache, cli::Format, config::{ - AttacksConfigQueryStorage, CommitConfigQueryStorage, Config, ConfigSource, - ConfigSourceStorage, LanguagesConfigQueryStorage, PracticesConfigQueryStorage, - RiskConfigQuery, RiskConfigQueryStorage, WeightTreeQueryStorage, + Config, ConfigSource, ConfigSourceStorage, RiskConfigQuery, RiskConfigQueryStorage, + WeightTreeQueryStorage, }, engine::{start_plugins, HcEngine, HcEngineStorage}, error::{Context as _, Error, Result}, @@ -44,12 +43,8 @@ use url::Url; /// Immutable configuration and base data for a run of Hipcheck. #[salsa::database( - AttacksConfigQueryStorage, - CommitConfigQueryStorage, ConfigSourceStorage, HcEngineStorage, - LanguagesConfigQueryStorage, - PracticesConfigQueryStorage, ReportParamsStorage, RiskConfigQueryStorage, ScoringProviderStorage,