Skip to content

Commit addc1d3

Browse files
committed
Rust: Add qhelp, examples, and tests of examples.
1 parent 64aa4e8 commit addc1d3

File tree

5 files changed

+255
-76
lines changed

5 files changed

+255
-76
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
7+
<p>Allocating memory with a size based on user input may allow arbitrary amounts of memory to be
8+
allocated, leading to a crash or denial of service incident.</p>
9+
10+
<p>If the user input is multiplied by a constant, such as the size of a type, the result may
11+
overflow. In a build with the <code>--release</code> flag Rust performs two's complement wrapping,
12+
with the result that less memory may be allocated than expected. This can lead to buffer overflow
13+
incidents.</p>
14+
15+
</overview>
16+
<recommendation>
17+
18+
<p>Implement a guard to limit the amount of memory that is allocated, and reject the request if
19+
the guard is not met. Ensure that any multiplications in the calculation cannot overflow, either
20+
by guarding their inputs, or using a multiplication routine such as <code>checked_mul</code> that
21+
does not wrap around.</p>
22+
23+
</recommendation>
24+
<example>
25+
26+
<p>In the following example, an arbitrary amount of memory is allocated based on user input. In
27+
addition, due to the multiplication operation the result may overflow if a very large value is
28+
provided, leading to less memory being allocated than other parts of the program expect.</p>
29+
<sample src="UncontrolledAllocationSizeBad.rs" />
30+
31+
<p>In the fixed example, the user input is checked against a maximum value. If the check fails an
32+
error is returned, and both the multiplication and alloaction do not take place.</p>
33+
<sample src="UncontrolledAllocationSizeGood.rs" />
34+
35+
</example>
36+
<references>
37+
38+
<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>
39+
40+
</references>
41+
</qhelp>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
fn allocate_buffer(user_input: String) -> Result<*mut u8, Error> {
3+
let num_bytes = user_input.parse::<usize>()? * std::mem::size_of::<u64>();
4+
5+
let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap();
6+
unsafe {
7+
let buffer = std::alloc::alloc(layout); // BAD: uncontrolled allocation size
8+
9+
Ok(buffer)
10+
}
11+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
const BUFFER_LIMIT: usize = 10 * 1024;
3+
4+
fn allocate_buffer(user_input: String) -> Result<*mut u8, Error> {
5+
let size = user_input.parse::<usize>()?;
6+
if (size > BUFFER_LIMIT) {
7+
return Err("Size exceeds limit".into());
8+
}
9+
let num_bytes = size * std::mem::size_of::<u64>();
10+
11+
let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap();
12+
unsafe {
13+
let buffer = std::alloc::alloc(layout); // GOOD
14+
15+
Ok(buffer)
16+
}
17+
}

0 commit comments

Comments
 (0)