Skip to content

Commit 913aa49

Browse files
Oppenpefontana
andauthored
fix(security)!: avoid DoS on malicious insert to memory (#1099)
Co-authored-by: Pedro Fontana <[email protected]>
1 parent 72065eb commit 913aa49

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@
144144
%}
145145
```
146146

147+
* fix(security)!: avoid DoS on malicious insertion to memory [#1099](https://github.com/lambdaclass/cairo-rs/pull/1099)
148+
* A program could crash the library by attempting to insert a value at an address with a big offset; fixed by trying to reserve to check for allocation failure
149+
* A program could crash the program by exploiting an integer overflow when attempting to insert a value at an address with offset `usize::MAX`
150+
151+
BREAKING: added a new error variant `MemoryError::VecCapacityExceeded`
152+
147153
* fix(starknet-crypto): bump version to `0.5.0` [#1088](https://github.com/lambdaclass/cairo-rs/pull/1088)
148154
* This includes the fix for a `panic!` in `ecdsa::verify`.
149155
See: [#365](https://github.com/xJonathanLEI/starknet-rs/issues/365) and [#366](https://github.com/xJonathanLEI/starknet-rs/pulls/366)

src/vm/errors/memory_errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ pub enum MemoryError {
9494
// SegmentArenaBuiltin
9595
#[error("segment_arena_builtin: assert used >= INITIAL_SEGMENT_SIZE")]
9696
InvalidUsedSizeSegmentArena,
97+
#[error("Vector capacity exceeded")]
98+
VecCapacityExceeded,
9799
}
98100

99101
#[derive(Debug, PartialEq, Eq, Error)]

src/vm/vm_memory/memory.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,15 @@ impl Memory {
136136

137137
//Check if the element is inserted next to the last one on the segment
138138
//Forgoing this check would allow data to be inserted in a different index
139-
if segment.len() <= value_offset {
140-
segment.resize(value_offset + 1, None);
139+
let (len, capacity) = (segment.len(), segment.capacity());
140+
if len <= value_offset {
141+
let new_len = value_offset
142+
.checked_add(1)
143+
.ok_or(MemoryError::VecCapacityExceeded)?;
144+
segment
145+
.try_reserve(new_len.saturating_sub(capacity))
146+
.map_err(|_| MemoryError::VecCapacityExceeded)?;
147+
segment.resize(new_len, None);
141148
}
142149
// At this point there's *something* in there
143150

@@ -1523,6 +1530,20 @@ mod memory_tests {
15231530
assert_eq!((ord, pos), mem.memcmp(lhs.into(), rhs.into(), len));
15241531
}
15251532

1533+
#[test]
1534+
fn insert_alloc_fails_gracefully() {
1535+
let mut mem = memory![((0, 0), 1)];
1536+
let err = mem.insert((0, usize::MAX >> 1).into(), Felt252::one());
1537+
assert_eq!(err, Err(MemoryError::VecCapacityExceeded));
1538+
}
1539+
1540+
#[test]
1541+
fn insert_overflow_fails_gracefully() {
1542+
let mut mem = memory![((0, 0), 1)];
1543+
let err = mem.insert((0, usize::MAX).into(), Felt252::one());
1544+
assert_eq!(err, Err(MemoryError::VecCapacityExceeded));
1545+
}
1546+
15261547
#[test]
15271548
fn memcmp() {
15281549
check_memcmp((0, 0), (0, 0), 3, Equal, 3);

0 commit comments

Comments
 (0)