Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 0 additions & 70 deletions aderyn_core/src/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,74 +27,4 @@ macro_rules! capture {
};
}

#[macro_export]
macro_rules! issue_detector {
(
$detector_struct:ident;

severity: $detector_severity:ident,
title: $detector_title:tt,
desc: $detector_desc:tt,
name: $detector_name:ident,

|$context: ident| $e:expr_2021
) => {

#[derive(Default)]
pub struct $detector_struct {
found_instances: std::collections::BTreeMap<(String, usize, String), $crate::ast::NodeID>,
}

impl $crate::detect::detector::IssueDetector for $detector_struct {

fn detect(&mut self, context: &$crate::context::workspace::WorkspaceContext) -> Result<bool, Box<dyn std::error::Error>> {

let $context = context;

macro_rules! grab {
($item:expr_2021) => {
if let Some(id) = context.get_node_id_of_capturable(&$item.clone().into()) {
self.found_instances.insert(
$context.get_node_sort_key_from_capturable(&$item.clone().into()),
id,
);
} else {
self.found_instances.insert(
$context.get_node_sort_key_from_capturable(&$item.clone().into()),
0,
);
}
};
}

$e
Ok(!self.found_instances.is_empty())
}

fn severity(&self) -> $crate::detect::detector::IssueSeverity {
$crate::detect::detector::IssueSeverity::$detector_severity
}

fn title(&self) -> String {
String::from($detector_title)
}

fn description(&self) -> String {
String::from($detector_desc)
}

fn instances(&self) -> std::collections::BTreeMap<(String, usize, String), $crate::ast::NodeID> {
self.found_instances.clone()
}

fn name(&self) -> String {
$crate::detect::detector::IssueDetectorNamePool::$detector_name.to_string()
}
}

};
}

pub use capture;

pub use issue_detector;
61 changes: 47 additions & 14 deletions aderyn_core/src/detect/high/misused_boolean.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
use crate::{detect::helpers::is_constant_boolean, issue_detector};
use eyre::Result;
use std::{collections::BTreeMap, error::Error};

issue_detector! {
MisusedBooleanDetector;
use crate::{
ast::NodeID,
capture,
context::workspace::WorkspaceContext,
detect::{
detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
helpers::is_constant_boolean,
},
};
use eyre::Result;

severity: High,
title: "Misused boolean with logical operators",
desc: "The patterns `if (… || true)` and `if (.. && false)` will always evaluate to true and false respectively.",
name: MisusedBoolean,
#[derive(Default)]
pub struct MisusedBooleanDetector {
// Keys are: [0] source file name, [1] line number, [2] character location of node.
// Do not add items manually, use `capture!` to add nodes to this BTreeMap.
found_instances: BTreeMap<(String, usize, String), NodeID>,
}

|context| {
impl IssueDetector for MisusedBooleanDetector {
fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
for binary_operation in context.binary_operations() {
if (binary_operation.operator == "||" || binary_operation.operator == "&&")
&& [
Expand All @@ -19,19 +29,42 @@ issue_detector! {
.iter()
.any(|&operand| is_constant_boolean(context, operand))
{
grab!(binary_operation);
capture!(self, context, binary_operation);
}

}

for if_statement in context.if_statements()
for if_statement in context
.if_statements()
.iter()
.filter(|statement| is_constant_boolean(context, &statement.condition)) {
grab!(if_statement);
.filter(|statement| is_constant_boolean(context, &statement.condition))
{
capture!(self, context, if_statement);
}

Ok(!self.found_instances.is_empty())
}

fn severity(&self) -> IssueSeverity {
IssueSeverity::High
}

fn title(&self) -> String {
String::from("Misused boolean with logical operators")
}

fn description(&self) -> String {
String::from(
"The patterns `if (… || true)` and `if (.. && false)` will always evaluate to true and false respectively.",
)
}

fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
self.found_instances.clone()
}

fn name(&self) -> String {
format!("{}", IssueDetectorNamePool::MisusedBoolean)
}
}

#[cfg(test)]
Expand Down
52 changes: 42 additions & 10 deletions aderyn_core/src/detect/low/boolean_equality.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
use crate::{detect::helpers::is_constant_boolean, issue_detector};
use eyre::Result;
use std::{collections::BTreeMap, error::Error};

issue_detector! {
BooleanEqualityDetector;
use crate::{
ast::NodeID,
capture,
context::workspace::WorkspaceContext,
detect::{
detector::{IssueDetector, IssueDetectorNamePool, IssueSeverity},
helpers::is_constant_boolean,
},
};
use eyre::Result;

severity: Low,
title: "Boolean equality is not required",
desc: "If `x` is a boolean, use `if(x)` and `if(!x)` instead of `if(x == true)` or `if(x == false)`.",
name: BooleanEquality,
#[derive(Default)]
pub struct BooleanEqualityDetector {
// Keys are: [0] source file name, [1] line number, [2] character location of node.
// Do not add items manually, use `capture!` to add nodes to this BTreeMap.
found_instances: BTreeMap<(String, usize, String), NodeID>,
}

|context| {
impl IssueDetector for BooleanEqualityDetector {
fn detect(&mut self, context: &WorkspaceContext) -> Result<bool, Box<dyn Error>> {
for binary_operation in context.binary_operations() {
if binary_operation.operator == "=="
&& [
Expand All @@ -19,11 +29,33 @@ issue_detector! {
.iter()
.any(|&operand| is_constant_boolean(context, operand))
{
grab!(binary_operation);
capture!(self, context, binary_operation);
}
}
Ok(!self.found_instances.is_empty())
}

fn severity(&self) -> IssueSeverity {
IssueSeverity::Low
}

fn title(&self) -> String {
String::from("Boolean equality is not required")
}

fn description(&self) -> String {
String::from(
"If `x` is a boolean, use `if(x)` and `if(!x)` instead of `if(x == true)` or `if(x == false)`.",
)
}

fn instances(&self) -> BTreeMap<(String, usize, String), NodeID> {
self.found_instances.clone()
}

fn name(&self) -> String {
format!("{}", IssueDetectorNamePool::BooleanEquality)
}
}

#[cfg(test)]
Expand Down
Loading