summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author David Anekstein <anekstein@google.com> 2022-05-05 17:18:48 +0000
committer David Anekstein <anekstein@google.com> 2022-07-08 13:02:33 -0400
commitae78558b2b76ea241e0aaba09c22dd2d8c24210c (patch)
tree4bbe912c56472b5874572d6d9f72203c11854118
parentec0d68e94557ade17f1729aedfb0b5cad97c8427 (diff)
libbinder: Allow vector construction from unaligned data.
std::vector::insert(const_iterator pos, ...) requires that `pos` be aligned to the size of the type it points to, e.g. 8 byte aligned for an int64_t iterator, to avoid undefined behavior. In cases where the type is trivially copyable, it is safe to memcpy the contents of the buffer directly into the vector. This change does not cover non-trivially-copyable types that are not aligned to their size within `data`. Bug: None Test: run AIDL client / server tests Change-Id: Ie1a44659e79f7a07cf6c3b318870d0279e1516ce
-rw-r--r--libs/binder/include/binder/Parcel.h16
1 files changed, 13 insertions, 3 deletions
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 32b0ded55c..91febbd7bb 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -1184,10 +1184,20 @@ private:
c->clear(); // must clear before resizing/reserving otherwise move ctors may be called.
if constexpr (is_pointer_equivalent_array_v<T>) {
// could consider POD without gaps and alignment of 4.
- auto data = reinterpret_cast<const T*>(
- readInplace(static_cast<size_t>(size) * sizeof(T)));
+ size_t dataLen;
+ if (__builtin_mul_overflow(size, sizeof(T), &dataLen)) {
+ return -EOVERFLOW;
+ }
+ auto data = reinterpret_cast<const T*>(readInplace(dataLen));
if (data == nullptr) return BAD_VALUE;
- c->insert(c->begin(), data, data + size); // insert should do a reserve().
+ // std::vector::insert and similar methods will require type-dependent
+ // byte alignment when inserting from a const iterator such as `data`,
+ // e.g. 8 byte alignment for int64_t, and so will not work if `data`
+ // is 4 byte aligned (which is all Parcel guarantees). Copying
+ // the contents into the vector directly, where possible, circumvents
+ // this.
+ c->resize(size);
+ memcpy(c->data(), data, dataLen);
} else if constexpr (std::is_same_v<T, bool>
|| std::is_same_v<T, char16_t>) {
c->reserve(size); // avoids default initialization