Commit 22b69cc8 authored by Nick Terrell's avatar Nick Terrell Committed by Facebook Github Bot

Fix UB in small_vector

Summary:
`moveObjectsRightAndCreate()` did pointer arithmetic outside of the object,
because it had a one before the beginning pointer. Instead, decrement the
pointers before use.

Reviewed By: ot

Differential Revision: D14887926

fbshipit-source-id: 198151d1eaef17e86cda800367480e0a8f7b2f49
parent 21c6ab58
...@@ -118,9 +118,8 @@ moveObjectsRightAndCreate( ...@@ -118,9 +118,8 @@ moveObjectsRightAndCreate(
return; return;
} }
T* const end = first - 1; // Past the end going backwards. T* out = realLast;
T* out = realLast - 1; T* in = lastConstructed;
T* in = lastConstructed - 1;
{ {
auto rollback = makeGuard([&] { auto rollback = makeGuard([&] {
// We want to make sure the same stuff is uninitialized memory // We want to make sure the same stuff is uninitialized memory
...@@ -133,16 +132,26 @@ moveObjectsRightAndCreate( ...@@ -133,16 +132,26 @@ moveObjectsRightAndCreate(
it->~T(); it->~T();
} }
}); });
for (; in != end && out >= lastConstructed; --in, --out) { // Decrement the pointers only when it is known that the resulting pointer
new (out) T(std::move(*in)); // is within the boundaries of the object. Decrementing past the beginning
// of the object is UB. Note that this is asymmetric wrt forward iteration,
// as past-the-end pointers are explicitly allowed.
for (; in != first && out > lastConstructed;) {
// Out must be decremented before an exception can be thrown so that
// the rollback guard knows where to start.
--out;
new (out) T(std::move(*(--in)));
} }
for (; in != end; --in, --out) { for (; in != first;) {
*out = std::move(*in); --out;
*out = std::move(*(--in));
} }
for (; out >= lastConstructed; --out) { for (; out > lastConstructed;) {
--out;
new (out) T(create(out - first)); new (out) T(create(out - first));
} }
for (; out != end; --out) { for (; out != first;) {
--out;
*out = create(out - first); *out = create(out - first);
} }
rollback.dismiss(); rollback.dismiss();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment