Skip to content

ada_url::Url::parse seems to leak memory when parsing invalid urls #101

@irdassis

Description

@irdassis

It can be reproduced with:

fn main() {
    let invalid = "http://[invalid";

    // Leaks one heap allocation per call — ada_parse allocates but Err drops the pointer.
    for _ in 0..1_000_000 {
        let _ = ada_url::Url::parse(invalid, None);
    }
}

Valgrind output:

==725== Memcheck, a memory error detector
==725== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==725== Using Valgrind-3.24.0 and LibVEX; rerun with -h for copyright info
==725== Command: ./target/release/ada_url_leak
==725==
==725==
==725== HEAP SUMMARY:
==725==     in use at exit: 88,000,544 bytes in 1,000,001 blocks
==725==   total heap usage: 2,000,010 allocs, 1,000,009 frees, 119,076,348 bytes allocated
==725==
==725== 440 bytes in 5 blocks are possibly lost in loss record 1 of 3
==725==    at 0x4844F93: operator new(unsigned long) (vg_replace_malloc.c:487)
==725==    by 0x171BE7: ada_parse (in /app/target/release/ada_url_leak)
==725==    by 0x15B9EE: ada_url_leak::main (in /app/target/release/ada_url_leak)
==725==    by 0x15BA52: std::sys::backtrace::__rust_begin_short_backtrace (in /app/target/release/ada_url_leak)
==725==    by 0x15BA48: std::rt::lang_start::{{closure}} (in /app/target/release/ada_url_leak)
==725==    by 0x1976F3: std::rt::lang_start_internal (in /app/target/release/ada_url_leak)
==725==    by 0x15BA94: main (in /app/target/release/ada_url_leak)
==725==
==725== 87,999,560 bytes in 999,995 blocks are definitely lost in loss record 3 of 3
==725==    at 0x4844F93: operator new(unsigned long) (vg_replace_malloc.c:487)
==725==    by 0x171BE7: ada_parse (in /app/target/release/ada_url_leak)
==725==    by 0x15B9EE: ada_url_leak::main (in /app/target/release/ada_url_leak)
==725==    by 0x15BA52: std::sys::backtrace::__rust_begin_short_backtrace (in /app/target/release/ada_url_leak)
==725==    by 0x15BA48: std::rt::lang_start::{{closure}} (in /app/target/release/ada_url_leak)
==725==    by 0x1976F3: std::rt::lang_start_internal (in /app/target/release/ada_url_leak)
==725==    by 0x15BA94: main (in /app/target/release/ada_url_leak)
==725==
==725== LEAK SUMMARY:
==725==    definitely lost: 87,999,560 bytes in 999,995 blocks
==725==    indirectly lost: 0 bytes in 0 blocks
==725==      possibly lost: 440 bytes in 5 blocks
==725==    still reachable: 544 bytes in 1 blocks
==725==         suppressed: 0 bytes in 0 blocks
==725== Reachable blocks (those to which a pointer was found) are not shown.
==725== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==725==
==725== For lists of detected and suppressed errors, rerun with: -s
==725== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

Issue seems to be on the Err path here https://github.com/ada-url/rust/blob/main/src/lib.rs#L233

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions