Skip to content

Commit ae555f2

Browse files
committed
Rust: Add a test for uncontrolled allocation size.
1 parent 86ecef6 commit ae555f2

File tree

5 files changed

+232
-0
lines changed

5 files changed

+232
-0
lines changed

rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected

Whitespace-only changes.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
query: queries/security/CWE-770/UncontrolledAllocationSize.ql
2+
postprocess:
3+
- utils/test/InlineExpectationsTestQuery.ql
4+
- utils/test/PrettyPrintModels.ql
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
#![feature(alloc_layout_extra)]
2+
#![feature(allocator_api)]
3+
#![feature(try_with_capacity)]
4+
#![feature(box_vec_non_null)]
5+
#![feature(non_null_from_ref)]
6+
7+
struct MyStruct {
8+
_a: usize,
9+
_b: i64,
10+
}
11+
12+
unsafe fn test_std_alloc_from_size(v: usize) {
13+
let l1 = std::alloc::Layout::from_size_align(16, 1).unwrap();
14+
let m1 = std::alloc::alloc(l1);
15+
let _ = std::alloc::alloc(l1.align_to(8).unwrap());
16+
let _ = std::alloc::alloc(l1.align_to(8).unwrap().pad_to_align());
17+
let _ = std::alloc::alloc_zeroed(l1);
18+
let _ = std::alloc::realloc(m1, l1, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
19+
20+
let l2 = std::alloc::Layout::from_size_align(v, 1).unwrap();
21+
let _ = std::alloc::alloc(l2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
22+
let _ = std::alloc::alloc(l2.align_to(8).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
23+
let _ = std::alloc::alloc(l2.align_to(8).unwrap().pad_to_align()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
24+
let _ = std::alloc::alloc_zeroed(l2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
25+
26+
let l3 = std::alloc::Layout::from_size_align(1, v).unwrap(); // not obviously dangerous?
27+
let _ = std::alloc::alloc(l3);
28+
29+
let l4 = std::alloc::Layout::from_size_align_unchecked(v, 1);
30+
let _ = std::alloc::alloc(l4); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
31+
32+
let l5 = std::alloc::Layout::from_size_align_unchecked(v * std::mem::size_of::<i64>(), std::mem::size_of::<i64>());
33+
let _ = std::alloc::alloc(l5); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
34+
35+
let s6 = (std::mem::size_of::<MyStruct>() * v) + 1;
36+
let l6 = std::alloc::Layout::from_size_align_unchecked(s6, 4);
37+
let _ = std::alloc::alloc(l6); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
38+
39+
let l7 = std::alloc::Layout::from_size_align_unchecked(l6.size(), 8);
40+
let _ = std::alloc::alloc(l7); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
41+
}
42+
43+
unsafe fn test_std_alloc_new_repeat_extend(v: usize) {
44+
let l1 = std::alloc::Layout::new::<[u8; 10]>();
45+
let _ = std::alloc::alloc(l1);
46+
47+
let l2 = std::alloc::Layout::new::<MyStruct>();
48+
let _ = std::alloc::alloc(l2);
49+
let _ = std::alloc::alloc(l2.repeat(10).unwrap().0);
50+
let _ = std::alloc::alloc(l2.repeat(v).unwrap().0); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
51+
let _ = std::alloc::alloc(l2.repeat(v + 1).unwrap().0); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
52+
let _ = std::alloc::alloc(l2.repeat_packed(10).unwrap());
53+
let _ = std::alloc::alloc(l2.repeat_packed(v).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
54+
let _ = std::alloc::alloc(l2.repeat_packed(v * 10).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
55+
56+
let l3 = std::alloc::Layout::array::<u8>(10).unwrap();
57+
let _ = std::alloc::alloc(l3);
58+
let (k1, _offs1) = l3.repeat(v).expect("arithmetic overflow?");
59+
let _ = std::alloc::alloc(k1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
60+
let (k2, _offs2) = l3.extend(k1).unwrap();
61+
let _ = std::alloc::alloc(k2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
62+
let (k3, _offs3) = k1.extend(l3).unwrap();
63+
let _ = std::alloc::alloc(k3); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
64+
let _ = std::alloc::alloc(l3.extend_packed(k1).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
65+
let _ = std::alloc::alloc(k1.extend_packed(l3).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
66+
67+
let l4 = std::alloc::Layout::array::<u8>(v).unwrap();
68+
let _ = std::alloc::alloc(l4); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
69+
}
70+
71+
fn clamp<T: std::cmp::PartialOrd>(v: T, min: T, max: T) -> T {
72+
if v < min {
73+
return min;
74+
} else if v > max {
75+
return max;
76+
} else {
77+
return v;
78+
}
79+
}
80+
81+
unsafe fn test_std_alloc_with_bounds(v: usize) {
82+
let l1 = std::alloc::Layout::array::<u32>(v).unwrap();
83+
84+
if v < 100 {
85+
let _ = std::alloc::alloc(l1);
86+
} else {
87+
let _ = std::alloc::alloc(l1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
88+
}
89+
90+
if v == 100 {
91+
let _ = std::alloc::alloc(l1);
92+
} else {
93+
let _ = std::alloc::alloc(l1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
94+
}
95+
96+
{
97+
let mut v_mut = v;
98+
99+
if v_mut > 100 {
100+
v_mut = 100;
101+
}
102+
103+
let l2 = std::alloc::Layout::array::<u32>(v_mut).unwrap();
104+
let _ = std::alloc::alloc(l2);
105+
106+
let l3 = std::alloc::Layout::array::<u32>(v).unwrap();
107+
let _ = std::alloc::alloc(l3); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
108+
}
109+
110+
let l4 = std::alloc::Layout::array::<u32>(std::cmp::min(v, 100)).unwrap();
111+
let _ = std::alloc::alloc(l4);
112+
113+
let l5 = std::alloc::Layout::array::<u32>(std::cmp::max(v, 100)).unwrap();
114+
let _ = std::alloc::alloc(l5); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
115+
116+
let l6 = std::alloc::Layout::array::<u32>(clamp(v, 1, 100)).unwrap();
117+
let _ = std::alloc::alloc(l6);
118+
119+
let _ = std::alloc::alloc(l1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
120+
if v > 100 {
121+
return;
122+
}
123+
let _ = std::alloc::alloc(l1);
124+
}
125+
126+
use std::alloc::{GlobalAlloc, Allocator};
127+
128+
unsafe fn test_system_alloc(v: usize) {
129+
let l1 = std::alloc::Layout::array::<u8>(10).unwrap();
130+
let _ = std::alloc::System.alloc(l1);
131+
let _ = std::alloc::System.alloc_zeroed(l1);
132+
let _ = std::alloc::System.allocate(l1).unwrap();
133+
let _ = std::alloc::System.allocate_zeroed(l1).unwrap();
134+
let _ = std::alloc::Global.allocate(l1).unwrap();
135+
let _ = std::alloc::Global.allocate_zeroed(l1).unwrap();
136+
137+
let l2 = std::alloc::Layout::array::<u8>(v).unwrap();
138+
let _ = std::alloc::System.alloc(l2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
139+
let _ = std::alloc::System.alloc_zeroed(l2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
140+
let _ = std::alloc::System.allocate(l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
141+
let _ = std::alloc::System.allocate_zeroed(l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
142+
let _ = std::alloc::Global.allocate(l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
143+
let _ = std::alloc::Global.allocate_zeroed(l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
144+
145+
let l3 = std::alloc::Layout::array::<u8>(10).unwrap();
146+
let m3 = std::alloc::System.alloc(l3);
147+
let _ = std::alloc::System.realloc(m3, l3, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
148+
149+
let l4 = std::alloc::Layout::array::<u8>(10).unwrap();
150+
let m4 = std::ptr::NonNull::<u8>::new(std::alloc::alloc(l4)).unwrap();
151+
if v > 10 {
152+
if v % 2 == 0 {
153+
let _ = std::alloc::System.grow(m4, l4, l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
154+
} else {
155+
let _ = std::alloc::System.grow_zeroed(m4, l4, l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
156+
}
157+
} else {
158+
let _ = std::alloc::System.shrink(m4, l4, l2).unwrap();
159+
}
160+
}
161+
162+
unsafe fn test_libc_alloc(v: usize) {
163+
let m1 = libc::malloc(256);
164+
let _ = libc::malloc(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
165+
let _ = libc::aligned_alloc(8, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
166+
let _ = libc::aligned_alloc(v, 8);
167+
let _ = libc::calloc(64, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
168+
let _ = libc::calloc(v, std::mem::size_of::<i64>()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
169+
let _ = libc::realloc(m1, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
170+
}
171+
172+
unsafe fn test_vectors(v: usize) {
173+
let _ = Vec::<u64>::try_with_capacity(v).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
174+
let _ = Vec::<u64>::with_capacity(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
175+
let _ = Vec::<u64>::try_with_capacity_in(v, std::alloc::Global).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
176+
let _ = Vec::<u64>::with_capacity_in(v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
177+
178+
let mut v1 = Vec::<u64>::with_capacity(100);
179+
v1.reserve(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
180+
v1.reserve_exact(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
181+
let _ = v1.try_reserve(v).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
182+
let _ = v1.try_reserve_exact(v).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
183+
v1.resize(v, 1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
184+
v1.set_len(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
185+
186+
let l2 = std::alloc::Layout::new::<[u64; 200]>();
187+
let m2 = std::ptr::NonNull::<u64>::new(std::alloc::alloc(l2).cast::<u64>()).unwrap();
188+
let _ = Vec::<u64>::from_parts(m2, v, 200); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
189+
190+
let m3 = std::ptr::NonNull::<u64>::new(std::alloc::alloc(l2).cast::<u64>()).unwrap();
191+
let _ = Vec::<u64>::from_parts(m3, 100, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
192+
193+
let m4 = std::ptr::NonNull::<u64>::new(std::alloc::alloc(l2).cast::<u64>()).unwrap();
194+
let _ = Vec::<u64>::from_parts_in(m4, 100, v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
195+
196+
let m5 = std::alloc::alloc(l2).cast::<u64>();
197+
let _ = Vec::<u64>::from_raw_parts(m5, v, 200); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
198+
199+
let m6 = std::alloc::alloc(l2).cast::<u64>();
200+
let _ = Vec::<u64>::from_raw_parts(m6, 100, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
201+
202+
let m7 = std::alloc::alloc(l2).cast::<u64>();
203+
let _ = Vec::<u64>::from_raw_parts_in(m7, 100, v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
204+
}
205+
206+
// --- main ---
207+
208+
fn main() {
209+
println!("--- begin ---");
210+
211+
let v = std::env::args().nth(1).unwrap_or("1024".to_string()).parse::<usize>().unwrap(); // $ Source=arg1
212+
213+
unsafe {
214+
test_std_alloc_from_size(v);
215+
test_std_alloc_new_repeat_extend(v);
216+
test_std_alloc_with_bounds(v);
217+
test_system_alloc(v);
218+
test_libc_alloc(v);
219+
test_vectors(v);
220+
}
221+
222+
println!("--- end ---");
223+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
qltest_cargo_check: true
2+
qltest_dependencies:
3+
- libc = { version = "0.2.11" }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[toolchain]
2+
channel = "nightly-2025-03-17"

0 commit comments

Comments
 (0)