Skip to content

Commit b111c0e

Browse files
meta-yaohwaymeta-codesync[bot]
authored andcommitted
MapBufferBuilder: fix size_t→int32 partial-write in putString/putMapBuffer length encoding (#56525)
Summary: Pull Request resolved: #56525 The MapBuffer wire format encodes lengths and offsets as `int32_t` (`MapBuffer::getString` / `getMapBuffer` read them as `*reinterpret_cast<const int32_t*>(...)`). But in `putString` and `putMapBuffer`: ```cpp auto strSize = value.size(); // size_t — 8 bytes on 64-bit memcpy(dynamicData_.data() + offset, &strSize, INT_SIZE); // copies first 4 of 8 bytes ``` `auto` deduces `size_t` from `.size()`, and `memcpy(&size_t_var, ..., 4)` writes only the **first 4 bytes** of an 8-byte object: - **little-endian:** writes the low 4 bytes — silent truncation if size > UINT32_MAX - **big-endian:** writes the high 4 bytes — encodes **zero** for normal sizes, producing a corrupt buffer the reader then trusts `putMapBufferList` already had the correct pattern: `auto offset = static_cast<int32_t>(dynamicData_.size())`. This diff applies that same explicit `static_cast<int32_t>` to `putString` (`strSize`, `offset`) and `putMapBuffer` (`mapBufferSize`, `offset`) so the value being `memcpy`'d is exactly `INT_SIZE` bytes wide. Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D100376322 fbshipit-source-id: ad0d505555e057240bf376795e867c52125590d8
1 parent 2902df0 commit b111c0e

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,16 @@ void MapBufferBuilder::putLong(MapBuffer::Key key, int64_t value) {
8484
}
8585

8686
void MapBufferBuilder::putString(MapBuffer::Key key, const std::string& value) {
87-
auto strSize = value.size();
87+
// The wire format encodes lengths and offsets as int32_t (see
88+
// MapBuffer::getString). Without an explicit narrowing cast, `auto` deduces
89+
// size_t (8 bytes on 64-bit) and `memcpy(&x, ..., INT_SIZE)` then copies only
90+
// the first 4 bytes of an 8-byte value: silent truncation on little-endian,
91+
// wrong (high) bytes on big-endian.
92+
auto strSize = static_cast<int32_t>(value.size());
8893
const char* strData = value.data();
8994

9095
// format [length of string (int)] + [Array of Characters in the string]
91-
auto offset = dynamicData_.size();
96+
auto offset = static_cast<int32_t>(dynamicData_.size());
9297
dynamicData_.resize(offset + INT_SIZE + strSize, 0);
9398
memcpy(dynamicData_.data() + offset, &strSize, INT_SIZE);
9499
memcpy(dynamicData_.data() + offset + INT_SIZE, strData, strSize);
@@ -102,9 +107,12 @@ void MapBufferBuilder::putString(MapBuffer::Key key, const std::string& value) {
102107
}
103108

104109
void MapBufferBuilder::putMapBuffer(MapBuffer::Key key, const MapBuffer& map) {
105-
auto mapBufferSize = map.size();
110+
// Wire format encodes lengths and offsets as int32_t (see
111+
// MapBuffer::getMapBuffer). Cast explicitly so memcpy(&x, ..., INT_SIZE)
112+
// copies the full value, not the first 4 bytes of an 8-byte size_t.
113+
auto mapBufferSize = static_cast<int32_t>(map.size());
106114

107-
auto offset = dynamicData_.size();
115+
auto offset = static_cast<int32_t>(dynamicData_.size());
108116

109117
// format [length of buffer (int)] + [bytes of MapBuffer]
110118
dynamicData_.resize(offset + INT_SIZE + mapBufferSize, 0);

0 commit comments

Comments
 (0)