Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 707263e4 authored by Yurii Zubrytskyi's avatar Yurii Zubrytskyi
Browse files

[res] Zero big buffer memory on backing up

When a memory chunk gets returned into BigBuffer, it may have
some data written already. BigBuffer is supposed to give out
zeroed memory, so BackUp() needs to zero it as well

Bug: 336758568
Bug: 342579978
Test: unit test + bundletool on the attached aab
Flag: EXEMPT bugfix
Change-Id: I8ecd60e84dbe16570a92d82370d1633af72599c8
parent ac310d16
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -17,8 +17,8 @@
#include <androidfw/BigBuffer.h>

#include <algorithm>
#include <iterator>
#include <memory>
#include <vector>

#include "android-base/logging.h"

@@ -78,10 +78,27 @@ void* BigBuffer::NextBlock(size_t* out_size) {

std::string BigBuffer::to_string() const {
  std::string result;
  result.reserve(size_);
  for (const Block& block : blocks_) {
    result.append(block.buffer.get(), block.buffer.get() + block.size);
  }
  return result;
}

void BigBuffer::AppendBuffer(BigBuffer&& buffer) {
  std::move(buffer.blocks_.begin(), buffer.blocks_.end(), std::back_inserter(blocks_));
  size_ += buffer.size_;
  buffer.blocks_.clear();
  buffer.size_ = 0;
}

void BigBuffer::BackUp(size_t count) {
  Block& block = blocks_.back();
  block.size -= count;
  size_ -= count;
  // BigBuffer is supposed to always give zeroed memory, but backing up usually means
  // something has been already written into the block. Erase it.
  std::fill_n(block.buffer.get() + block.size, count, 0);
}

}  // namespace android
+3 −19
Original line number Diff line number Diff line
@@ -14,13 +14,12 @@
 * limitations under the License.
 */

#ifndef _ANDROID_BIG_BUFFER_H
#define _ANDROID_BIG_BUFFER_H
#pragma once

#include <cstring>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

#include "android-base/logging.h"
@@ -150,24 +149,11 @@ inline size_t BigBuffer::block_size() const {

template <typename T>
inline T* BigBuffer::NextBlock(size_t count) {
  static_assert(std::is_standard_layout<T>::value, "T must be standard_layout type");
  static_assert(std::is_standard_layout_v<T>, "T must be standard_layout type");
  CHECK(count != 0);
  return reinterpret_cast<T*>(NextBlockImpl(sizeof(T) * count));
}

inline void BigBuffer::BackUp(size_t count) {
  Block& block = blocks_.back();
  block.size -= count;
  size_ -= count;
}

inline void BigBuffer::AppendBuffer(BigBuffer&& buffer) {
  std::move(buffer.blocks_.begin(), buffer.blocks_.end(), std::back_inserter(blocks_));
  size_ += buffer.size_;
  buffer.blocks_.clear();
  buffer.size_ = 0;
}

inline void BigBuffer::Pad(size_t bytes) {
  NextBlock<char>(bytes);
}
@@ -188,5 +174,3 @@ inline BigBuffer::const_iterator BigBuffer::end() const {
}

}  // namespace android

#endif  // _ANDROID_BIG_BUFFER_H
+16 −0
Original line number Diff line number Diff line
@@ -98,4 +98,20 @@ TEST(BigBufferTest, PadAndAlignProperly) {
  ASSERT_EQ(8u, buffer.size());
}

TEST(BigBufferTest, BackUpZeroed) {
  BigBuffer buffer(16);

  auto block = buffer.NextBlock<char>(2);
  ASSERT_TRUE(block != nullptr);
  ASSERT_EQ(2u, buffer.size());
  block[0] = 0x01;
  block[1] = 0x02;
  buffer.BackUp(1);
  ASSERT_EQ(1u, buffer.size());
  auto new_block = buffer.NextBlock<char>(1);
  ASSERT_TRUE(new_block != nullptr);
  ASSERT_EQ(2u, buffer.size());
  ASSERT_EQ(0, *new_block);
}

}  // namespace android