Unverified Commit 395f933c by Enkelmann Committed by GitHub

generate log messages for zero-sized allocations instead of CWE warnings (#399)

parent 7afcd9e8
...@@ -106,10 +106,13 @@ impl<'a> Context<'a> { ...@@ -106,10 +106,13 @@ impl<'a> Context<'a> {
Bitvector::from_i64(upper_bound) Bitvector::from_i64(upper_bound)
.into_resize_signed(object_size.bytesize()), .into_resize_signed(object_size.bytesize()),
); );
if upper_bound.sign_bit().to_bool() { if lower_bound.is_zero() || upper_bound.is_zero() {
// Both bounds seem to be bogus values (because both are negative values). self.log_info(object_id.get_tid(), "Heap object may have size zero. This may indicate an instance of CWE-687.");
}
if upper_bound.sign_bit().to_bool() || upper_bound.is_zero() {
// Both bounds seem to be bogus values (because both are non-positive values).
BitvectorDomain::new_top(object_size.bytesize()) BitvectorDomain::new_top(object_size.bytesize())
} else if lower_bound.sign_bit().to_bool() { } else if lower_bound.sign_bit().to_bool() || lower_bound.is_zero() {
// The lower bound is bogus, but we can approximate by the upper bound instead. // The lower bound is bogus, but we can approximate by the upper bound instead.
upper_bound.into() upper_bound.into()
} else { } else {
...@@ -139,6 +142,17 @@ impl<'a> Context<'a> { ...@@ -139,6 +142,17 @@ impl<'a> Context<'a> {
self.log_collector.send(log_msg.into()).unwrap(); self.log_collector.send(log_msg.into()).unwrap();
} }
/// Log an info log message in the log collector of `self`.
pub fn log_info(&self, tid: &Tid, msg: impl ToString) {
let log_msg = LogMessage {
text: msg.to_string(),
level: crate::utils::log::LogLevel::Info,
location: Some(tid.clone()),
source: Some(super::CWE_MODULE.name.to_string()),
};
self.log_collector.send(log_msg.into()).unwrap();
}
/// Check whether the given parameter at the given callsite may point outside of its corresponding memory object. /// Check whether the given parameter at the given callsite may point outside of its corresponding memory object.
/// If yes, then generate a CWE warning. /// If yes, then generate a CWE warning.
pub fn check_param_at_call( pub fn check_param_at_call(
......
...@@ -50,3 +50,25 @@ fn test_compute_size_value_of_malloc_like_call() { ...@@ -50,3 +50,25 @@ fn test_compute_size_value_of_malloc_like_call() {
) )
.is_none()); .is_none());
} }
#[test]
fn test_malloc_zero_case() {
let mut context = Context::mock_x64();
let (sender, _receiver) = crossbeam_channel::unbounded();
context.log_collector = sender; // So that log messages can be sent and received.
let object_size = IntervalDomain::mock(0, 32);
let object_size = DataDomain::from(object_size);
let object_id = AbstractIdentifier::mock("object_tid", "RAX", 8);
context
.call_to_caller_fn_map
.insert(object_id.get_tid().clone(), Tid::new("func_tid"));
context
.malloc_tid_to_object_size_map
.insert(object_id.get_tid().clone(), object_size);
// Since zero sizes usually result in implementation-specific behavior for allocators,
// the fallback of taking the maximum object size in `context.compute_size_of_heap_object()` should trigger.
let size_domain = context.compute_size_of_heap_object(&object_id);
assert_eq!(size_domain.try_to_offset().unwrap(), 32);
}
...@@ -155,7 +155,7 @@ impl<'a, 'b> ExternCallHandler<'a, 'b> { ...@@ -155,7 +155,7 @@ impl<'a, 'b> ExternCallHandler<'a, 'b> {
/// Compute the size of a buffer from a corresponding size value. /// Compute the size of a buffer from a corresponding size value.
/// Returns `None` if no absolute size value could be determined for any reason. /// Returns `None` if no absolute size value could be determined for any reason.
/// ///
/// If a range of posible sizes is detected, use the smallest possible size, /// If a range of possible sizes is detected, use the smallest possible size,
/// as using larger sizes would lead to too many false positive CWE warnings. /// as using larger sizes would lead to too many false positive CWE warnings.
fn compute_buffer_size_from_data_domain(&self, size: Data) -> Option<ByteSize> { fn compute_buffer_size_from_data_domain(&self, size: Data) -> Option<ByteSize> {
let size = self.context.recursively_substitute_param_values(&size); let size = self.context.recursively_substitute_param_values(&size);
......
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