mirror of
https://github.com/github/codeql.git
synced 2025-12-22 11:46:32 +01:00
Rust: Add qhelp, examples, and tests of examples.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
|
||||
<p>Allocating memory with a size based on user input may allow arbitrary amounts of memory to be
|
||||
allocated, leading to a crash or denial of service incident.</p>
|
||||
|
||||
<p>If the user input is multiplied by a constant, such as the size of a type, the result may
|
||||
overflow. In a build with the <code>--release</code> flag Rust performs two's complement wrapping,
|
||||
with the result that less memory may be allocated than expected. This can lead to buffer overflow
|
||||
incidents.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>Implement a guard to limit the amount of memory that is allocated, and reject the request if
|
||||
the guard is not met. Ensure that any multiplications in the calculation cannot overflow, either
|
||||
by guarding their inputs, or using a multiplication routine such as <code>checked_mul</code> that
|
||||
does not wrap around.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>In the following example, an arbitrary amount of memory is allocated based on user input. In
|
||||
addition, due to the multiplication operation the result may overflow if a very large value is
|
||||
provided, leading to less memory being allocated than other parts of the program expect.</p>
|
||||
<sample src="UncontrolledAllocationSizeBad.rs" />
|
||||
|
||||
<p>In the fixed example, the user input is checked against a maximum value. If the check fails an
|
||||
error is returned, and both the multiplication and alloaction do not take place.</p>
|
||||
<sample src="UncontrolledAllocationSizeGood.rs" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>The Rust Programming Language: <a href="https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-overflow">Data Types - Integer Overflow</a>.</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
fn allocate_buffer(user_input: String) -> Result<*mut u8, Error> {
|
||||
let num_bytes = user_input.parse::<usize>()? * std::mem::size_of::<u64>();
|
||||
|
||||
let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap();
|
||||
unsafe {
|
||||
let buffer = std::alloc::alloc(layout); // BAD: uncontrolled allocation size
|
||||
|
||||
Ok(buffer)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
const BUFFER_LIMIT: usize = 10 * 1024;
|
||||
|
||||
fn allocate_buffer(user_input: String) -> Result<*mut u8, Error> {
|
||||
let size = user_input.parse::<usize>()?;
|
||||
if (size > BUFFER_LIMIT) {
|
||||
return Err("Size exceeds limit".into());
|
||||
}
|
||||
let num_bytes = size * std::mem::size_of::<u64>();
|
||||
|
||||
let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap();
|
||||
unsafe {
|
||||
let buffer = std::alloc::alloc(layout); // GOOD
|
||||
|
||||
Ok(buffer)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user