Unverified Commit a3a73e8d by Enkelmann Committed by GitHub

Implement more checks in Rust. (#102)

parent 6b93b698
pub mod cwe_190;
pub mod cwe_332;
pub mod cwe_426;
pub mod cwe_467; pub mod cwe_467;
pub mod cwe_560; pub mod cwe_560;
pub mod cwe_676; pub mod cwe_676;
......
//! This module implements a check for CWE-190: Integer overflow or wraparound.
//!
//! An integer overflow can lead to undefined behaviour and is especially dangerous
//! in conjunction with memory management functions.
//!
//! See <https://cwe.mitre.org/data/definitions/190.html> for a detailed description.
//!
//! ## How the check works
//!
//! For each call to a function from the CWE190 symbol list we check whether the
//! basic block directly before the call contains a multiplication instruction.
//! If one is found, the call gets flagged as a CWE hit, as there is no overflow
//! check corresponding to the multiplication before the call. The default CWE190
//! symbol list contains the memory allocation functions *malloc*, *xmalloc*,
//! *calloc* and *realloc*. The list is configurable in config.json.
//!
//! ## False Positives
//!
//! - There is no check whether the result of the multiplication is actually used
//! as input to the function call. However, this does not seem to generate a lot
//! of false positives in practice.
//! - There is no value set analysis in place to determine whether an overflow is
//! possible or not at the specific instruction.
//!
//! ## False Negatives
//!
//! - All integer overflows not in a basic block right before a call to a function
//! from the CWE190 symbol list.
//! - All integer overflows caused by addition or subtraction.
use crate::intermediate_representation::*;
use crate::prelude::*;
use crate::utils::log::{CweWarning, LogMessage};
use crate::utils::symbol_utils::{get_callsites, get_symbol_map};
use crate::CweModule;
pub static CWE_MODULE: CweModule = CweModule {
name: "CWE190",
version: "0.1",
run: check_cwe,
};
/// The configuration struct.
/// The `symbols` are extern function names.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
pub struct Config {
symbols: Vec<String>,
}
/// Check whether the given expression contains an integer multiplication subexpression,
/// i.e. an `IntMult` or `IntLeft` (left shift) binary operation.
fn expression_contains_multiplication(expr: &Expression) -> bool {
use Expression::*;
match expr {
BinOp {
op: BinOpType::IntMult,
..
}
| BinOp {
op: BinOpType::IntLeft,
..
} => true,
Var(_) | Const(_) | Unknown { .. } => false,
BinOp { lhs, rhs, .. } => {
expression_contains_multiplication(lhs) || expression_contains_multiplication(rhs)
}
UnOp { arg, .. } | Cast { arg, .. } | Subpiece { arg, .. } => {
expression_contains_multiplication(arg)
}
}
}
/// Check whether the given block contains a multiplication expression.
/// Expressions computing the address of a `Load` or `Store` instruction are ignored
/// since the addresses themselves cannot be inputs to the call at the end of the block.
fn block_contains_multiplication(block: &Term<Blk>) -> bool {
block.term.defs.iter().any(|def| match &def.term {
Def::Assign { value, .. } | Def::Store { value, .. } => {
expression_contains_multiplication(value)
}
Def::Load { .. } => false,
})
}
/// Generate the CWE warning for a detected instance of the CWE.
fn generate_cwe_warning(callsite: &Tid, called_symbol: &ExternSymbol) -> CweWarning {
CweWarning::new(
CWE_MODULE.name,
CWE_MODULE.version,
format!(
"(Integer Overflow or Wraparound) Potential overflow due to multiplication before call to {} at {}",
called_symbol.name, callsite.address
))
.tids(vec![format!("{}", callsite)])
.addresses(vec![callsite.address.clone()])
.symbols(vec!(called_symbol.name.clone()))
}
/// Run the CWE check.
/// For each call to one of the symbols configured in config.json
/// we check whether the block containing the call also contains a multiplication instruction.
pub fn check_cwe(
project: &Project,
cwe_params: &serde_json::Value,
) -> (Vec<LogMessage>, Vec<CweWarning>) {
let config: Config = serde_json::from_value(cwe_params.clone()).unwrap();
let mut cwe_warnings = Vec::new();
let symbol_map = get_symbol_map(project, &config.symbols);
for sub in project.program.term.subs.iter() {
for (block, jump, symbol) in get_callsites(sub, &symbol_map) {
if block_contains_multiplication(block) {
cwe_warnings.push(generate_cwe_warning(&jump.tid, symbol));
}
}
}
(Vec::new(), cwe_warnings)
}
//! This module implements a check for CWE332: Insufficient Entropy in PRNG.
//!
//! This can happen, for instance, if the PRNG is not seeded. A classical example
//! would be calling rand without srand. This could lead to predictable random
//! numbers and could, for example, weaken crypto functionality.
//!
//! See <https://cwe.mitre.org/data/definitions/332.html> for a detailed description.
//!
//! ## How the check works
//!
//! For pairs of a secure seeding function and a corresponding random number generator function
//! (e.g. the pair `(srand, rand)`, configurable in `config.json`)
//! we check whether the program calls the random number generator without calling the seeding function.
//!
//! ## False Positives
//!
//! None known
//!
//! ## False Negatives
//!
//! - It is not checked whether the seeding function gets called before the random number generator function.
use crate::intermediate_representation::*;
use crate::prelude::*;
use crate::utils::log::{CweWarning, LogMessage};
use crate::utils::symbol_utils::find_symbol;
use crate::CweModule;
pub static CWE_MODULE: CweModule = CweModule {
name: "CWE332",
version: "0.1",
run: check_cwe,
};
/// The configuration struct contains pairs of symbol names,
/// where the first name is the name of a seeding function
/// and the second name is the name of a corresponding random number generator access function.
/// It is assumed that a program has to call the seeding function first
/// to ensure that the RNG does not generate predictable random numbers.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
pub struct Config {
pairs: Vec<(String, String)>,
}
/// Generate the CWE warning for a detected instance of the CWE.
fn generate_cwe_warning(secure_initializer_func: &str, rand_func: &str) -> CweWarning {
CweWarning::new(
CWE_MODULE.name,
CWE_MODULE.version,
format!(
"(Insufficient Entropy in PRNG) program uses {} without calling {} before",
rand_func, secure_initializer_func
),
)
}
/// Run the CWE check. See the module-level description for more information.
pub fn check_cwe(
project: &Project,
cwe_params: &serde_json::Value,
) -> (Vec<LogMessage>, Vec<CweWarning>) {
let config: Config = serde_json::from_value(cwe_params.clone()).unwrap();
let mut cwe_warnings = Vec::new();
for (secure_initializer_func, rand_func) in config.pairs.iter() {
if find_symbol(&project.program, rand_func).is_some()
&& find_symbol(&project.program, secure_initializer_func).is_none()
{
cwe_warnings.push(generate_cwe_warning(secure_initializer_func, rand_func));
}
}
(Vec::new(), cwe_warnings)
}
//! This module implements a check for CWE-426: Untrusted Search Path.
//!
//! Basically, the program searches for critical resources on an untrusted search
//! path that can be adjusted by an adversary. For example, see Nebula Level 1
//! (<https://exploit-exercises.com/nebula/level01/>).
//!
//! According to the manual page of system() the following problems can arise:
//! "Do not use system() from a program with set-user-ID or set-group-ID privileges,
//! because strange values for some environment variables might be used to subvert
//! system integrity. Use the exec(3) family of functions instead, but not execlp(3)
//! or execvp(3). system() will not, in fact, work properly from programs with set-user-ID
//! or set-group-ID privileges on systems on which /bin/sh is bash version 2, since bash 2
//! drops privileges on startup. (Debian uses a modified bash which does not do this when invoked as sh.)"
//!
//! See <https://cwe.mitre.org/data/definitions/426.html> for a detailed description.
//!
//! ## How the check works
//!
//! We check whether a function that calls a privilege-changing function (configurable
//! in config.json) also calls system().
//!
//! ## False Positives
//!
//! - If the call to system() happens before the privilege-changing function, the call
//! may not be used for privilege escalation
//!
//! ## False Negatives
//!
//! - If the calls to the privilege-changing function and system() happen in different
//! functions, the calls will not be flagged as a CWE-hit.
//! - This check only finds potential privilege escalation bugs, but other types of
//! bugs can also be triggered by untrusted search paths.
use crate::intermediate_representation::*;
use crate::prelude::*;
use crate::utils::log::{CweWarning, LogMessage};
use crate::utils::symbol_utils::{find_symbol, get_calls_to_symbols};
use crate::CweModule;
use std::collections::HashMap;
pub static CWE_MODULE: CweModule = CweModule {
name: "CWE426",
version: "0.1",
run: check_cwe,
};
/// Function symbols read from *config.json*.
/// The symbols are functions that change or drop privileges.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
pub struct Config {
symbols: Vec<String>,
}
/// Generate the CWE warning for a detected instance of the CWE.
fn generate_cwe_warning(sub: &Term<Sub>) -> CweWarning {
CweWarning::new(
CWE_MODULE.name,
CWE_MODULE.version,
format!(
"(Untrusted Search Path) sub {} at {} may be vulnerable to PATH manipulation.",
sub.term.name, sub.tid.address
),
)
.tids(vec![format!("{}", sub.tid)])
.addresses(vec![sub.tid.address.clone()])
.symbols(vec![sub.term.name.clone()])
}
/// Run the CWE check.
/// We check whether a function calls both `system(..)` and a privilege changing function.
/// For each such function a CWE warning is generated.
pub fn check_cwe(
project: &Project,
cwe_params: &serde_json::Value,
) -> (Vec<LogMessage>, Vec<CweWarning>) {
let config: Config = serde_json::from_value(cwe_params.clone()).unwrap();
let mut cwe_warnings = Vec::new();
let mut privilege_changing_symbols = HashMap::new();
for symbol in config.symbols.iter() {
if let Some((tid, name)) = find_symbol(&project.program, symbol) {
privilege_changing_symbols.insert(tid, name);
}
}
let mut system_symbol = HashMap::new();
if let Some((tid, name)) = find_symbol(&project.program, "system") {
system_symbol.insert(tid, name);
}
if !system_symbol.is_empty() && !privilege_changing_symbols.is_empty() {
for sub in project.program.term.subs.iter() {
if !get_calls_to_symbols(sub, &system_symbol).is_empty()
&& !get_calls_to_symbols(sub, &privilege_changing_symbols).is_empty()
{
cwe_warnings.push(generate_cwe_warning(sub));
}
}
}
(Vec::new(), cwe_warnings)
}
...@@ -25,8 +25,8 @@ use crate::analysis::pointer_inference::State; ...@@ -25,8 +25,8 @@ use crate::analysis::pointer_inference::State;
use crate::intermediate_representation::*; use crate::intermediate_representation::*;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::log::{CweWarning, LogMessage}; use crate::utils::log::{CweWarning, LogMessage};
use crate::utils::symbol_utils::{get_callsites, get_symbol_map};
use crate::CweModule; use crate::CweModule;
use std::collections::HashMap;
pub static CWE_MODULE: CweModule = CweModule { pub static CWE_MODULE: CweModule = CweModule {
name: "CWE467", name: "CWE467",
...@@ -41,33 +41,6 @@ pub struct Config { ...@@ -41,33 +41,6 @@ pub struct Config {
symbols: Vec<String>, symbols: Vec<String>,
} }
/// Get a map from TIDs to the corresponding extern symbol struct.
/// Only symbols contained in `symbols_to_check` are contained in the map.
fn get_symbol_map<'a>(
project: &'a Project,
symbols_to_check: &[String],
) -> HashMap<Tid, &'a ExternSymbol> {
let mut tid_map = HashMap::new();
for symbol_name in symbols_to_check {
if let Some((tid, symbol)) = project
.program
.term
.extern_symbols
.iter()
.find_map(|symbol| {
if symbol.name == *symbol_name {
Some((symbol.tid.clone(), symbol))
} else {
None
}
})
{
tid_map.insert(tid, symbol);
}
}
tid_map
}
/// Compute the program state at the end of the given basic block /// Compute the program state at the end of the given basic block
/// assuming nothing is known about the state at the start of the block. /// assuming nothing is known about the state at the start of the block.
fn compute_block_end_state(project: &Project, block: &Term<Blk>) -> State { fn compute_block_end_state(project: &Project, block: &Term<Blk>) -> State {
...@@ -124,21 +97,6 @@ fn generate_cwe_warning(jmp: &Term<Jmp>, extern_symbol: &ExternSymbol) -> CweWar ...@@ -124,21 +97,6 @@ fn generate_cwe_warning(jmp: &Term<Jmp>, extern_symbol: &ExternSymbol) -> CweWar
.addresses(vec![jmp.tid.address.clone()]) .addresses(vec![jmp.tid.address.clone()])
} }
/// Check whether a symbol contained in `symbol_map` is called at the end of the given basic block.
fn block_calls_symbol<'a>(
block: &'a Term<Blk>,
symbol_map: &HashMap<Tid, &'a ExternSymbol>,
) -> Option<(&'a Term<Jmp>, &'a ExternSymbol)> {
for jump in block.term.jmps.iter() {
if let Jmp::Call { target, .. } = &jump.term {
if let Some(symbol) = symbol_map.get(target) {
return Some((jump, symbol));
}
}
}
None
}
/// Execute the CWE check. /// Execute the CWE check.
/// ///
/// For each call to an extern symbol from the symbol list configured in the configuration file /// For each call to an extern symbol from the symbol list configured in the configuration file
...@@ -153,13 +111,11 @@ pub fn check_cwe( ...@@ -153,13 +111,11 @@ pub fn check_cwe(
let symbol_map = get_symbol_map(project, &config.symbols); let symbol_map = get_symbol_map(project, &config.symbols);
for sub in project.program.term.subs.iter() { for sub in project.program.term.subs.iter() {
for block in sub.term.blocks.iter() { for (block, jmp, symbol) in get_callsites(sub, &symbol_map) {
if let Some((jmp, symbol)) = block_calls_symbol(block, &symbol_map) {
if check_for_pointer_sized_arg(project, block, symbol) { if check_for_pointer_sized_arg(project, block, symbol) {
cwe_warnings.push(generate_cwe_warning(jmp, symbol)) cwe_warnings.push(generate_cwe_warning(jmp, symbol))
} }
} }
} }
}
(Vec::new(), cwe_warnings) (Vec::new(), cwe_warnings)
} }
...@@ -27,6 +27,7 @@ use crate::analysis::pointer_inference::State; ...@@ -27,6 +27,7 @@ use crate::analysis::pointer_inference::State;
use crate::intermediate_representation::*; use crate::intermediate_representation::*;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::log::{CweWarning, LogMessage}; use crate::utils::log::{CweWarning, LogMessage};
use crate::utils::symbol_utils::{get_callsites, get_symbol_map};
use crate::CweModule; use crate::CweModule;
pub static CWE_MODULE: CweModule = CweModule { pub static CWE_MODULE: CweModule = CweModule {
...@@ -72,11 +73,6 @@ fn get_umask_permission_arg( ...@@ -72,11 +73,6 @@ fn get_umask_permission_arg(
} }
} }
/// Determine whether the given jump is a call to umask.
fn is_call_to_umask(jmp: &Term<Jmp>, umask_tid: &Tid) -> bool {
matches!(&jmp.term, Jmp::Call { target, .. } if target == umask_tid)
}
/// Is the given argument value considered to be a chmod-style argument? /// Is the given argument value considered to be a chmod-style argument?
fn is_chmod_style_arg(arg: u64) -> bool { fn is_chmod_style_arg(arg: u64) -> bool {
arg > UPPER_BOUND_CORRECT_UMASK_ARG_VALUE && arg <= UPPER_BOUND_CORRECT_CHMOD_ARG_VALUE arg > UPPER_BOUND_CORRECT_UMASK_ARG_VALUE && arg <= UPPER_BOUND_CORRECT_CHMOD_ARG_VALUE
...@@ -107,22 +103,10 @@ pub fn check_cwe( ...@@ -107,22 +103,10 @@ pub fn check_cwe(
) -> (Vec<LogMessage>, Vec<CweWarning>) { ) -> (Vec<LogMessage>, Vec<CweWarning>) {
let mut cwes = Vec::new(); let mut cwes = Vec::new();
let mut log_messages = Vec::new(); let mut log_messages = Vec::new();
if let Some(umask_symbol) = project let umask_symbol_map = get_symbol_map(project, &["umask".to_string()]);
.program if !umask_symbol_map.is_empty() {
.term
.extern_symbols
.iter()
.find(|symbol| symbol.name == "umask")
{
let umask_tid = &umask_symbol.tid;
for sub in project.program.term.subs.iter() { for sub in project.program.term.subs.iter() {
for block in sub.term.blocks.iter() { for (block, jmp, umask_symbol) in get_callsites(sub, &umask_symbol_map) {
if let Some(jmp) = block
.term
.jmps
.iter()
.find(|jmp| is_call_to_umask(jmp, umask_tid))
{
match get_umask_permission_arg(block, umask_symbol, project) { match get_umask_permission_arg(block, umask_symbol, project) {
Ok(permission_const) => { Ok(permission_const) => {
if is_chmod_style_arg(permission_const) { if is_chmod_style_arg(permission_const) {
...@@ -142,7 +126,6 @@ pub fn check_cwe( ...@@ -142,7 +126,6 @@ pub fn check_cwe(
} }
} }
} }
}
(log_messages, cwes) (log_messages, cwes)
} }
...@@ -51,6 +51,9 @@ impl std::fmt::Display for CweModule { ...@@ -51,6 +51,9 @@ impl std::fmt::Display for CweModule {
/// Get a list of all known analysis modules. /// Get a list of all known analysis modules.
pub fn get_modules() -> Vec<&'static CweModule> { pub fn get_modules() -> Vec<&'static CweModule> {
vec![ vec![
&crate::checkers::cwe_190::CWE_MODULE,
&crate::checkers::cwe_332::CWE_MODULE,
&crate::checkers::cwe_426::CWE_MODULE,
&crate::checkers::cwe_467::CWE_MODULE, &crate::checkers::cwe_467::CWE_MODULE,
&crate::checkers::cwe_560::CWE_MODULE, &crate::checkers::cwe_560::CWE_MODULE,
&crate::checkers::cwe_782::CWE_MODULE, &crate::checkers::cwe_782::CWE_MODULE,
......
use std::collections::HashMap; use std::collections::HashMap;
use crate::intermediate_representation::{Jmp, Program, Sub, Term, Tid}; use crate::intermediate_representation::*;
/// Find the extern symbol object for a symbol name and return the symbol tid and name. /// Find the extern symbol object for a symbol name and return the symbol tid and name.
pub fn find_symbol<'a>(prog: &'a Term<Program>, name: &str) -> Option<(&'a Tid, &'a str)> { pub fn find_symbol<'a>(prog: &'a Term<Program>, name: &str) -> Option<(&'a Tid, &'a str)> {
...@@ -14,7 +14,7 @@ pub fn find_symbol<'a>(prog: &'a Term<Program>, name: &str) -> Option<(&'a Tid, ...@@ -14,7 +14,7 @@ pub fn find_symbol<'a>(prog: &'a Term<Program>, name: &str) -> Option<(&'a Tid,
symbol symbol
} }
/// Match direct calls' target tids in the program's subroutines with /// Match direct calls' target tids in the program's subroutines
/// with the tids of the external symbols given to the function. /// with the tids of the external symbols given to the function.
/// When a match was found, add a triple of (caller name, callsite tid, callee name) /// When a match was found, add a triple of (caller name, callsite tid, callee name)
/// to a vector. Lastly, return the vector with all callsites of all given external symbols. /// to a vector. Lastly, return the vector with all callsites of all given external symbols.
...@@ -38,3 +38,50 @@ pub fn get_calls_to_symbols<'a, 'b>( ...@@ -38,3 +38,50 @@ pub fn get_calls_to_symbols<'a, 'b>(
} }
calls calls
} }
/// Get a map from TIDs to the corresponding extern symbol struct.
/// Only symbols with names contained in `symbols_to_find` are contained in the map.
pub fn get_symbol_map<'a>(
project: &'a Project,
symbols_to_find: &[String],
) -> HashMap<Tid, &'a ExternSymbol> {
let mut tid_map = HashMap::new();
for symbol_name in symbols_to_find {
if let Some((tid, symbol)) = project
.program
.term
.extern_symbols
.iter()
.find_map(|symbol| {
if symbol.name == *symbol_name {
Some((symbol.tid.clone(), symbol))
} else {
None
}
})
{
tid_map.insert(tid, symbol);
}
}
tid_map
}
/// Find calls to TIDs contained as keys in the given symbol map.
/// For each match return the block containing the call,
/// the jump term representing the call itself and the symbol corresponding to the TID from the symbol map.
pub fn get_callsites<'a>(
sub: &'a Term<Sub>,
symbol_map: &HashMap<Tid, &'a ExternSymbol>,
) -> Vec<(&'a Term<Blk>, &'a Term<Jmp>, &'a ExternSymbol)> {
let mut callsites = Vec::new();
for blk in sub.term.blocks.iter() {
for jmp in blk.term.jmps.iter() {
if let Jmp::Call { target: dst, .. } = &jmp.term {
if let Some(symbol) = symbol_map.get(dst) {
callsites.push((blk, jmp, *symbol));
}
}
}
}
callsites
}
...@@ -170,6 +170,59 @@ mod tests { ...@@ -170,6 +170,59 @@ mod tests {
#[test] #[test]
#[ignore] #[ignore]
fn cwe_190() {
let mut error_log = Vec::new();
let mut tests = all_test_cases("cwe_190", "CWE190");
// Ghidra does not recognize all extern function calls in the disassembly step for MIPS.
// Needs own control flow graph analysis to be fixed.
mark_skipped(&mut tests, "mips64", "clang");
mark_skipped(&mut tests, "mips64el", "clang");
mark_skipped(&mut tests, "mips", "gcc");
mark_skipped(&mut tests, "mipsel", "gcc");
mark_architecture_skipped(&mut tests, "ppc64"); // Ghidra generates mangled function names here for some reason.
mark_architecture_skipped(&mut tests, "ppc64le"); // Ghidra generates mangled function names here for some reason.
mark_compiler_skipped(&mut tests, "mingw32-gcc"); // TODO: Check reason for failure!
for test_case in tests {
let num_expected_occurences = 3;
if let Err(error) = test_case.run_test("[CWE190]", num_expected_occurences) {
error_log.push((test_case.get_filepath(), error));
}
}
if !error_log.is_empty() {
print_errors(error_log);
panic!();
}
}
#[test]
#[ignore]
fn cwe_332() {
let mut error_log = Vec::new();
let mut tests = all_test_cases("cwe_332", "CWE332");
mark_architecture_skipped(&mut tests, "ppc64"); // Ghidra generates mangled function names here for some reason.
mark_architecture_skipped(&mut tests, "ppc64le"); // Ghidra generates mangled function names here for some reason.
mark_compiler_skipped(&mut tests, "mingw32-gcc"); // TODO: Check reason for failure!
for test_case in tests {
let num_expected_occurences = 1;
if let Err(error) = test_case.run_test("[CWE332]", num_expected_occurences) {
error_log.push((test_case.get_filepath(), error));
}
}
if !error_log.is_empty() {
print_errors(error_log);
panic!();
}
}
#[test]
#[ignore]
fn cwe_415() { fn cwe_415() {
let mut error_log = Vec::new(); let mut error_log = Vec::new();
let mut tests = all_test_cases("cwe_415", "Memory"); let mut tests = all_test_cases("cwe_415", "Memory");
...@@ -240,9 +293,39 @@ mod tests { ...@@ -240,9 +293,39 @@ mod tests {
#[test] #[test]
#[ignore] #[ignore]
fn cwe_426() {
let mut error_log = Vec::new();
let mut tests = all_test_cases("cwe_426", "CWE426");
// Ghidra does not recognize all extern function calls in the disassembly step for MIPS.
// Needs own control flow graph analysis to be fixed.
mark_skipped(&mut tests, "mips64", "clang");
mark_skipped(&mut tests, "mips64el", "clang");
mark_skipped(&mut tests, "mips", "gcc");
mark_skipped(&mut tests, "mipsel", "gcc");
mark_architecture_skipped(&mut tests, "ppc64"); // Ghidra generates mangled function names here for some reason.
mark_architecture_skipped(&mut tests, "ppc64le"); // Ghidra generates mangled function names here for some reason.
mark_compiler_skipped(&mut tests, "mingw32-gcc"); // TODO: Check reason for failure!
for test_case in tests {
let num_expected_occurences = 1;
if let Err(error) = test_case.run_test("[CWE426]", num_expected_occurences) {
error_log.push((test_case.get_filepath(), error));
}
}
if !error_log.is_empty() {
print_errors(error_log);
panic!();
}
}
#[test]
#[ignore]
fn cwe_467() { fn cwe_467() {
let mut error_log = Vec::new(); let mut error_log = Vec::new();
let mut tests = linux_test_cases("cwe_467", "CWE467"); let mut tests = all_test_cases("cwe_467", "CWE467");
// Only one instance is found. // Only one instance is found.
// Other instance cannot be found, since the constant is not defined in the basic block of the call instruction. // Other instance cannot be found, since the constant is not defined in the basic block of the call instruction.
...@@ -264,6 +347,8 @@ mod tests { ...@@ -264,6 +347,8 @@ mod tests {
// Register `ECX` is read, but the analysis doesn't know that `ECX` is a sub-register of `RCX`. // Register `ECX` is read, but the analysis doesn't know that `ECX` is a sub-register of `RCX`.
mark_skipped(&mut tests, "x64", "clang"); mark_skipped(&mut tests, "x64", "clang");
mark_compiler_skipped(&mut tests, "mingw32-gcc"); // TODO: Check reason for failure!
for test_case in tests { for test_case in tests {
let num_expected_occurences = 2; let num_expected_occurences = 2;
if let Err(error) = test_case.run_test("[CWE467]", num_expected_occurences) { if let Err(error) = test_case.run_test("[CWE467]", num_expected_occurences) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment