Skip to content

Commit

Permalink
Merge branch 'main' into missing_flags
Browse files Browse the repository at this point in the history
  • Loading branch information
plusvic committed Aug 2, 2024
2 parents 6838515 + 1ba5dcc commit edd000b
Show file tree
Hide file tree
Showing 14 changed files with 237 additions and 79 deletions.
173 changes: 99 additions & 74 deletions Cargo.lock

Large diffs are not rendered by default.

47 changes: 46 additions & 1 deletion lib/src/compiler/ir/ast2ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,52 @@ pub(in crate::compiler) fn expr_from_ast(
ast::Expr::BitwiseXor(expr) => bitwise_xor_expr_from_ast(ctx, expr),

// Comparison operations
ast::Expr::Eq(expr) => eq_expr_from_ast(ctx, expr),
ast::Expr::Eq(expr) => {
let span = expr.span();

let lhs_span = expr.lhs.span();
let rhs_span = expr.rhs.span();

let lhs = expr_from_ast(ctx, &expr.lhs)?;
let rhs = expr_from_ast(ctx, &expr.rhs)?;

// Detect cases in which the equal operator is comparing a boolean
// expression with an integer constant (e.g: `pe.is_signed == 0`).
// This is quite common in YARA rules, it is accepted without
// errors, but a warning is raised.
let replacement = match (lhs.type_value(), rhs.type_value()) {
(TypeValue::Bool(_), TypeValue::Integer(Value::Const(0))) => {
Some((
Expr::Not { operand: Box::new(lhs) },
format!("not {}", ctx.report_builder.get_snippet(&lhs_span.into()))
))
}
(TypeValue::Integer(Value::Const(0)), TypeValue::Bool(_)) => {
Some((
Expr::Not { operand: Box::new(rhs) },
format!("not {}", ctx.report_builder.get_snippet(&rhs_span.into()))
))
}
(TypeValue::Bool(_), TypeValue::Integer(Value::Const(1))) => {
Some((lhs, ctx.report_builder.get_snippet(&lhs_span.into())))
}
(TypeValue::Integer(Value::Const(1)), TypeValue::Bool(_)) => {
Some((rhs, ctx.report_builder.get_snippet(&rhs_span.into())))
}
_ => None
};

if let Some((expr, msg)) = replacement {
ctx.warnings.add(|| Warning::boolean_integer_comparison(
ctx.report_builder,
span.into(),
msg,
));
Ok(expr)
} else {
eq_expr_from_ast(ctx, expr)
}
},
ast::Expr::Ne(expr) => ne_expr_from_ast(ctx, expr),
ast::Expr::Gt(expr) => gt_expr_from_ast(ctx, expr),
ast::Expr::Ge(expr) => ge_expr_from_ast(ctx, expr),
Expand Down
14 changes: 14 additions & 0 deletions lib/src/compiler/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,20 @@ impl ReportBuilder {
self
}

/// Returns the fragment of source code indicated by `source_ref`.
pub fn get_snippet(&self, source_ref: &SourceRef) -> String {
let source_id = source_ref
.source_id
.or_else(|| self.current_source_id())
.expect("create_report without registering any source code");

let cache = self.cache.borrow();
let cache_entry = cache.data.get(&source_id).unwrap();
let src = cache_entry.code.as_str();

src[source_ref.span.range()].to_string()
}

/// Creates a new error or warning report.
pub fn create_report(
&self,
Expand Down
5 changes: 5 additions & 0 deletions lib/src/compiler/tests/testdata/warnings/27.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import "test_proto2"

rule test {
condition: test_proto2.array_bool[0] == 1
}
6 changes: 6 additions & 0 deletions lib/src/compiler/tests/testdata/warnings/27.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
warning[bool_int_comparison]: comparison between boolean and integer
--> line:4:13
|
4 | condition: test_proto2.array_bool[0] == 1
| ------------------------------ this comparison can be replaced with: `test_proto2.array_bool[0]`
|
5 changes: 5 additions & 0 deletions lib/src/compiler/tests/testdata/warnings/28.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import "test_proto2"

rule test {
condition: test_proto2.array_bool[0] == 0
}
6 changes: 6 additions & 0 deletions lib/src/compiler/tests/testdata/warnings/28.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
warning[bool_int_comparison]: comparison between boolean and integer
--> line:4:13
|
4 | condition: test_proto2.array_bool[0] == 0
| ------------------------------ this comparison can be replaced with: `not test_proto2.array_bool[0]`
|
5 changes: 5 additions & 0 deletions lib/src/compiler/tests/testdata/warnings/29.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import "test_proto2"

rule test {
condition: 1 == test_proto2.array_bool[0]
}
6 changes: 6 additions & 0 deletions lib/src/compiler/tests/testdata/warnings/29.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
warning[bool_int_comparison]: comparison between boolean and integer
--> line:4:13
|
4 | condition: 1 == test_proto2.array_bool[0]
| ------------------------------ this comparison can be replaced with: `test_proto2.array_bool[0]`
|
5 changes: 5 additions & 0 deletions lib/src/compiler/tests/testdata/warnings/30.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import "test_proto2"

rule test {
condition: 0 == test_proto2.array_bool[0]
}
6 changes: 6 additions & 0 deletions lib/src/compiler/tests/testdata/warnings/30.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
warning[bool_int_comparison]: comparison between boolean and integer
--> line:4:13
|
4 | condition: 0 == test_proto2.array_bool[0]
| ------------------------------ this comparison can be replaced with: `not test_proto2.array_bool[0]`
|
8 changes: 8 additions & 0 deletions lib/src/compiler/warnings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ pub enum Warning {
note: Option<String>,
},

#[warning("bool_int_comparison", "comparison between boolean and integer")]
#[label("this comparison can be replaced with: `{replacement}`", span)]
BooleanIntegerComparison {
detailed_report: String,
span: SourceRef,
replacement: String,
},

#[warning("duplicate_import", "duplicate import statement")]
#[label(
"duplicate import",
Expand Down
25 changes: 21 additions & 4 deletions lib/src/modules/pe/authenticode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ use x509_parser::certificate::X509Certificate;
use x509_parser::der_parser::num_bigint::BigUint;
use x509_parser::x509::{AlgorithmIdentifier, SubjectPublicKeyInfo, X509Name};

#[cfg(feature = "logging")]
use log::error;

use crate::modules::pe::asn1::{
oid, oid_to_object_identifier, oid_to_str, Attribute, Certificate,
ContentInfo, DigestInfo, SignedData, SignerInfo, SpcIndirectDataContent,
Expand Down Expand Up @@ -749,7 +752,11 @@ fn verify_message_digest(
rfc5912::ID_MD_5 | rfc5912::MD_5_WITH_RSA_ENCRYPTION => {
Md5::digest(message).as_slice() == digest
}
_ => unimplemented!("{:?}", algorithm.oid()),
_ => {
#[cfg(feature = "logging")]
error!("unknown digest algorithm: {:?}", algorithm.oid());
false
}
}
}

Expand Down Expand Up @@ -884,8 +891,11 @@ fn verify_signer_info(si: &SignerInfo, certs: &[Certificate<'_>]) -> bool {
attrs_set.write_der(&mut sha512).unwrap();
key.verify_digest::<Sha512>(sha512.finalize(), si.signature)
}

oid => unimplemented!("{:?}", oid),
_ => {
#[cfg(feature = "logging")]
error!("unknown digest algorithm: {:?}", digest_algorithm);
false
}
}
}

Expand Down Expand Up @@ -1143,7 +1153,14 @@ impl PublicKey {
| rfc5912::ECDSA_WITH_SHA_512 => {
self.verify_impl::<Sha512>(message, signature)
}
_ => unimplemented!("{:?}", digest_algorithm.oid()),
_ => {
#[cfg(feature = "logging")]
error!(
"unknown digest algorithm: {:?}",
digest_algorithm.oid()
);
false
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions lib/src/modules/test_proto2/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ fn test_proto2_module() {
condition_false!(r#"test_proto2.array_bool[0]"#);
condition_true!(r#"test_proto2.array_bool[1]"#);

condition_false!(r#"test_proto2.array_bool[0] == 1"#);
condition_true!(r#"test_proto2.array_bool[0] == 0"#);
condition_false!(r#"1 == test_proto2.array_bool[0]"#);
condition_true!(r#"0 == test_proto2.array_bool[0]"#);

// array_int64[3] is undefined, so both conditions are false.
condition_false!(r#"test_proto2.array_int64[3] == 0"#);
condition_false!(r#"test_proto2.array_int64[3] != 0"#);
Expand Down

0 comments on commit edd000b

Please sign in to comment.