Skip to content

VecDeque::append() forgets ZSTs on capacity overflow #108454

Closed
@LegionMammal978

Description

@LegionMammal978

I tried this code:

// compile with opt-level=2 or higher
use std::collections::VecDeque;

#[derive(Clone)]
struct Droppy;

impl Drop for Droppy {
    fn drop(&mut self) {
        println!("dropped!");
    }
}

fn main() {
    let mut buf1 = VecDeque::from(vec![Droppy; usize::MAX]);
    let mut buf2 = VecDeque::from(vec![Droppy]);

    let total = buf1.len() as u128 + buf2.len() as u128;
    println!("{} + {} = {}", buf1.len(), buf2.len(), total);

    buf1.append(&mut buf2);

    let total = buf1.len() as u128 + buf2.len() as u128;
    println!("{} + {} = {}", buf1.len(), buf2.len(), total);
}

I expected to see this happen: A capacity overflow panic, followed by 264 lines of dropped!.

Instead, this happened:

18446744073709551615 + 1 = 18446744073709551616
0 + 0 = 0

This is caused by VecDeque::append() using a wrapping addition for the length when T::IS_ZST:

pub fn append(&mut self, other: &mut Self) {
    if T::IS_ZST {
        self.len += other.len;
        other.len = 0;
        other.head = 0;
        return;
    }

    /* ... */
}

Meta

rustc --version --verbose:

rustc 1.69.0-nightly (c5c7d2b37 2023-02-24)
binary: rustc
commit-hash: c5c7d2b37780dac1092e75f12ab97dd56c30861d
commit-date: 2023-02-24
host: x86_64-unknown-linux-gnu
release: 1.69.0-nightly
LLVM version: 15.0.7

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions