Skip to content

Valgrind thinks the slice's memory is leaked since no real pointer remains to it #2

@federicomenaquintero

Description

@federicomenaquintero

In librsvg we got this issue about a leak reported by Valgrind:

==6237== 40 bytes in 1 blocks are definitely lost in loss record 1,053 of 1,774
==6237==    at 0x483A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==6237==    by 0x49F2BB6: alloc (alloc.rs:80)
==6237==    by 0x49F2BB6: alloc (alloc.rs:174)
==6237==    by 0x49F2BB6: allocate_in<selectors::parser::Component<rsvg_internals::css::Selector>,alloc::alloc::Global> (raw_vec.rs:152)
==6237==    by 0x49F2BB6: with_capacity_in<selectors::parser::Component<rsvg_internals::css::Selector>,alloc::alloc::Global> (raw_vec.rs:135)
==6237==    by 0x49F2BB6: with_capacity<selectors::parser::Component<rsvg_internals::css::Selector>> (raw_vec.rs:92)
==6237==    by 0x49F2BB6: with_capacity<selectors::parser::Component<rsvg_internals::css::Selector>> (vec.rs:358)
==6237==    by 0x49F2BB6: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T,I>>::from_iter (vec.rs:2073)
==6237==    by 0x4ADC6DF: from_iter<selectors::parser::Component<rsvg_internals::css::Selector>,smallvec::IntoIter<[selectors::parser::Component<rsvg_internals::css::Selector>; 2]>> (vec.rs:1981)
==6237==    by 0x4ADC6DF: collect<smallvec::IntoIter<[selectors::parser::Component<rsvg_internals::css::Selector>; 2]>,alloc::vec::Vec<selectors::parser::Component<rsvg_internals::css::Selector>>> (iterator.rs:1660)
==6237==    by 0x4ADC6DF: into_vec<[selectors::parser::Component<rsvg_internals::css::Selector>; 2]> (lib.rs:1073)
==6237==    by 0x4ADC6DF: parse_negation<rsvg_internals::css::RuleParser,rsvg_internals::css::Selector> (parser.rs:1987)
==6237==    by 0x4ADC6DF: selectors::parser::parse_functional_pseudo_class (parser.rs:2088)

Here, selectors is the selectors crate from Servo; it uses thin-slice for a few things.

From servo/components/selectors/parser.rs:

fn parse_negation<'i, 't, P, Impl>(
    parser: &P,
    input: &mut CssParser<'i, 't>,
) -> Result<Component<Impl>, ParseError<'i, P::Error>>
{
    ...
    Ok(Component::Negation(
        sequence.into_vec().into_boxed_slice().into(),
    ))
}

Component::Negation is a ThinBoxedSlice:

pub enum Component<Impl: SelectorImpl> {
    // ...
    Negation(ThinBoxedSlice<Component<Impl>>),
    // ...
}

I think Valgrind sees the malloc from the call to sequence.into_vec(), then it gets turned to a boxed slice, then to a ThinBoxedSlice. But since that erases the pointer from malloc, Valgrind thinks it's leaked.

So... this is not a real bug in thin-slice, just a bad interaction with Valgrind. I don't know if it's possible to have a suppression file for it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions