Skip to content

Commit 2f79413

Browse files
Merge pull request #2395 from multiversx/boxed-bytes-empty-fix
Fix: Undefined Behavior in BoxedBytes::from_concat on Zero-Length Input
2 parents 4267d66 + eba6564 commit 2f79413

1 file changed

Lines changed: 39 additions & 0 deletions

File tree

chain/core/src/types/boxed_bytes.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ impl BoxedBytes {
7474
index -= 1;
7575
result_len += slices[index].len();
7676
}
77+
// Calling `alloc` with a zero-sized layout is undefined behavior.
78+
// Return a valid empty instance directly instead of entering the unsafe path.
79+
if result_len == 0 {
80+
return BoxedBytes::empty();
81+
}
7782
unsafe {
7883
let layout = Layout::from_size_align(result_len, core::mem::align_of::<u8>()).unwrap();
7984
let result_ptr = alloc(layout);
@@ -256,6 +261,40 @@ mod tests {
256261
assert_eq!(bb, BoxedBytes::from(&b""[..]));
257262
}
258263

264+
/// Regression test: previously triggered UB by calling `alloc(size=0)`.
265+
#[test]
266+
fn test_concat_single_empty_slice() {
267+
let bb = BoxedBytes::from_concat(&[&b""[..]]);
268+
assert_eq!(bb, BoxedBytes::empty());
269+
assert!(bb.is_empty());
270+
}
271+
272+
#[test]
273+
fn test_concat_single_nonempty_slice() {
274+
let bb = BoxedBytes::from_concat(&[&b"hello"[..]]);
275+
assert_eq!(bb, BoxedBytes::from(&b"hello"[..]));
276+
}
277+
278+
#[test]
279+
fn test_concat_leading_empty_slices() {
280+
let bb = BoxedBytes::from_concat(&[&b""[..], &b""[..], &b"abc"[..]]);
281+
assert_eq!(bb, BoxedBytes::from(&b"abc"[..]));
282+
}
283+
284+
#[test]
285+
fn test_concat_trailing_empty_slices() {
286+
let bb = BoxedBytes::from_concat(&[&b"abc"[..], &b""[..], &b""[..]]);
287+
assert_eq!(bb, BoxedBytes::from(&b"abc"[..]));
288+
}
289+
290+
#[test]
291+
fn test_concat_result_is_empty_instance() {
292+
// All-empty concat must return a proper empty BoxedBytes, not a dangling pointer.
293+
let bb = BoxedBytes::from_concat(&[&b""[..], &b""[..]]);
294+
assert_eq!(bb.len(), 0);
295+
assert_eq!(bb.as_slice(), &b""[..]);
296+
}
297+
259298
#[test]
260299
fn test_is_empty() {
261300
assert!(BoxedBytes::empty().is_empty());

0 commit comments

Comments
 (0)