Skip to content

Avoid zero-sized leaf allocations in BTreeMap #28497

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 19, 2015
Merged

Avoid zero-sized leaf allocations in BTreeMap #28497

merged 1 commit into from
Sep 19, 2015

Conversation

apasel422
Copy link
Contributor

When both the key and value types were zero-sized, BTreeMap previously
called heap::allocate with size == 0 for leaf nodes, which is
undefined behavior, and jemalloc would attempt to read invalid memory,
crashing the process.

This avoids undefined behavior by allocating enough space to store one
edge in leaf nodes that would otherwise have size == 0. Although this
uses extra memory, maps with zero-sized key types that have sensible
implementations of the ordering traits can only contain a single
key-value pair (and therefore only a single leaf node), and maps with
key and value types that are both zero-sized have few uses, if any.

Furthermore, this is a temporary fix that will likely be unnecessary
once the BTreeMap implementation is rewritten to use parent pointers.

Closes #28493.

@rust-highfive
Copy link
Contributor

r? @nikomatsakis

(rust_highfive has picked a reviewer for you, use r? to override)

@nikomatsakis
Copy link
Contributor

cc @gankro -- who owns this code?

This change certainly seems safe to me, but I'm not familiar enough to know if there is a better way to go about it.

@apasel422
Copy link
Contributor Author

There's likely a better way to go about this, at least in terms of memory usage, but this is probably the least invasive way, and the usage of zero-sized keys in this collection is of questionable utility. Additionally, the fix is expected to be short-lived, given that @gereeter's parent pointer rewrite is almost complete.

When both the key and value types were zero-sized, `BTreeMap` previously
called `heap::allocate` with `size == 0` for leaf nodes, which is
undefined behavior, and jemalloc would attempt to read invalid memory,
crashing the process.

This avoids undefined behavior by allocating enough space to store one
edge in leaf nodes that would otherwise have `size == 0`. Although this
uses extra memory, maps with zero-sized key types that have sensible
implementations of the ordering traits can only contain a single
key-value pair (and therefore only a single leaf node), and maps with
key and value types that are both zero-sized have few uses, if any.

Furthermore, this is a temporary fix that will likely be unnecessary
once the `BTreeMap` implementation is rewritten to use parent pointers.

Closes #28493.
@Gankra
Copy link
Contributor

Gankra commented Sep 18, 2015

Yeah this is just a shim

@Gankra
Copy link
Contributor

Gankra commented Sep 18, 2015

I'm not a super fan of this, but honestly this is a stupid data structure to make anyway, and I'm just waiting for the rewrite.

@Gankra
Copy link
Contributor

Gankra commented Sep 18, 2015

@bors r+

@bors
Copy link
Collaborator

bors commented Sep 18, 2015

📌 Commit 9526813 has been approved by Gankro

@Gankra
Copy link
Contributor

Gankra commented Sep 18, 2015

@brson this is arguably a regression fix, but this bug has probably been around for ages. I know my originally merged impl didn't have this.

@bors
Copy link
Collaborator

bors commented Sep 19, 2015

⌛ Testing commit 9526813 with merge 6db1a0e...

bors added a commit that referenced this pull request Sep 19, 2015
When both the key and value types were zero-sized, `BTreeMap` previously
called `heap::allocate` with `size == 0` for leaf nodes, which is
undefined behavior, and jemalloc would attempt to read invalid memory,
crashing the process.

This avoids undefined behavior by allocating enough space to store one
edge in leaf nodes that would otherwise have `size == 0`. Although this
uses extra memory, maps with zero-sized key types that have sensible
implementations of the ordering traits can only contain a single
key-value pair (and therefore only a single leaf node), and maps with
key and value types that are both zero-sized have few uses, if any.

Furthermore, this is a temporary fix that will likely be unnecessary
once the `BTreeMap` implementation is rewritten to use parent pointers.

Closes #28493.
@bors bors merged commit 9526813 into rust-lang:master Sep 19, 2015
@apasel422 apasel422 deleted the issue-28493 branch September 19, 2015 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BTreeSet causes general protection fault with zero-sized key-value pairs and jemalloc
5 participants