Support unsigned protobuf value lengths

This commit is contained in:
guoling
2026-09-03 17:06:41 +08:00
parent 0f688fd15f
commit 998c51baca
6 changed files with 65 additions and 77 deletions
+10 -29
View File
@@ -85,11 +85,7 @@ bool CodedInputData::readBool() {
}
string CodedInputData::readString() {
int32_t size = readRawVarint32();
if (size < 0) {
throw length_error("InvalidProtocolBuffer negativeSize");
}
uint32_t size = readUInt32();
auto s_size = static_cast<size_t>(size);
if (s_size <= m_size - m_position) {
string result((char *) (m_ptr + m_position), s_size);
@@ -101,11 +97,7 @@ string CodedInputData::readString() {
}
void CodedInputData::readString(string &s) {
int32_t size = readRawVarint32();
if (size < 0) {
throw length_error("InvalidProtocolBuffer negativeSize");
}
uint32_t size = readUInt32();
auto s_size = static_cast<size_t>(size);
if (s_size <= m_size - m_position) {
s.resize(s_size);
@@ -119,11 +111,7 @@ void CodedInputData::readString(string &s) {
string CodedInputData::readString(KeyValueHolder &kvHolder) {
kvHolder.offset = static_cast<uint32_t>(m_position);
int32_t size = this->readRawVarint32();
if (size < 0) {
throw length_error("InvalidProtocolBuffer negativeSize");
}
uint32_t size = readUInt32();
auto s_size = static_cast<size_t>(size);
if (s_size <= m_size - m_position) {
if (s_size > mmkv::KeySizeLimit) {
@@ -146,11 +134,7 @@ MMBuffer CodedInputData::readRealData(mmkv::MMBuffer & data) {
}
MMBuffer CodedInputData::readData(bool copy, bool exactly) {
int32_t size = this->readRawVarint32();
if (size < 0) {
throw length_error("InvalidProtocolBuffer negativeSize");
}
uint32_t size = readUInt32();
auto s_size = static_cast<size_t>(size);
bool isSizeValid = exactly ? (s_size == m_size - m_position) : (s_size <= m_size - m_position);
if (isSizeValid) {
@@ -164,11 +148,7 @@ MMBuffer CodedInputData::readData(bool copy, bool exactly) {
}
void CodedInputData::readData(KeyValueHolder &kvHolder) {
int32_t size = this->readRawVarint32();
if (size < 0) {
throw length_error("InvalidProtocolBuffer negativeSize");
}
uint32_t size = readUInt32();
auto s_size = static_cast<size_t>(size);
if (s_size <= m_size - m_position) {
auto kvSize = m_position - kvHolder.offset;
@@ -189,7 +169,7 @@ int32_t CodedInputData::readRawVarint32() {
if (tmp >= 0) {
return tmp;
}
int32_t result = tmp & 0x7f;
uint32_t result = tmp & 0x7f;
if ((tmp = this->readRawByte()) >= 0) {
result |= tmp << 7;
} else {
@@ -202,12 +182,13 @@ int32_t CodedInputData::readRawVarint32() {
result |= tmp << 21;
} else {
result |= (tmp & 0x7f) << 21;
result |= (tmp = this->readRawByte()) << 28;
tmp = this->readRawByte();
result |= static_cast<uint32_t>(static_cast<uint8_t>(tmp)) << 28;
if (tmp < 0) {
// discard upper 32 bits
for (int i = 0; i < 5; i++) {
if (this->readRawByte() >= 0) {
return result;
return UInt32ToInt32(result);
}
}
throw invalid_argument("InvalidProtocolBuffer malformed varint32");
@@ -215,7 +196,7 @@ int32_t CodedInputData::readRawVarint32() {
}
}
}
return result;
return UInt32ToInt32(result);
}
int32_t CodedInputData::readRawLittleEndian32() {
+7 -14
View File
@@ -185,7 +185,7 @@ int32_t CodedInputDataCrypt::readRawVarint32(bool discardPreData) {
if (tmp >= 0) {
return tmp;
}
int32_t result = tmp & 0x7f;
uint32_t result = tmp & 0x7f;
if ((tmp = this->readRawByte()) >= 0) {
result |= tmp << 7;
} else {
@@ -198,12 +198,13 @@ int32_t CodedInputDataCrypt::readRawVarint32(bool discardPreData) {
result |= tmp << 21;
} else {
result |= (tmp & 0x7f) << 21;
result |= (tmp = this->readRawByte()) << 28;
tmp = this->readRawByte();
result |= static_cast<uint32_t>(static_cast<uint8_t>(tmp)) << 28;
if (tmp < 0) {
// discard upper 32 bits
for (int i = 0; i < 5; i++) {
if (this->readRawByte() >= 0) {
return result;
return UInt32ToInt32(result);
}
}
throw invalid_argument("InvalidProtocolBuffer malformed varint32");
@@ -211,7 +212,7 @@ int32_t CodedInputDataCrypt::readRawVarint32(bool discardPreData) {
}
}
}
return result;
return UInt32ToInt32(result);
}
int32_t CodedInputDataCrypt::readInt32() {
@@ -221,11 +222,7 @@ int32_t CodedInputDataCrypt::readInt32() {
string CodedInputDataCrypt::readString(KeyValueHolderCrypt &kvHolder) {
kvHolder.offset = static_cast<uint32_t>(m_position);
int32_t size = this->readRawVarint32(true);
if (size < 0) {
throw length_error("InvalidProtocolBuffer negativeSize");
}
uint32_t size = static_cast<uint32_t>(readRawVarint32(true));
auto s_size = static_cast<size_t>(size);
if (s_size <= m_size - m_position) {
consumeBytes(s_size);
@@ -245,11 +242,7 @@ string CodedInputDataCrypt::readString(KeyValueHolderCrypt &kvHolder) {
}
void CodedInputDataCrypt::readData(KeyValueHolderCrypt &kvHolder) {
int32_t size = this->readRawVarint32();
if (size < 0) {
throw length_error("InvalidProtocolBuffer negativeSize");
}
uint32_t size = static_cast<uint32_t>(readRawVarint32());
auto s_size = static_cast<size_t>(size);
if (s_size <= m_size - m_position) {
if (KeyValueHolderCrypt::isValueStoredAsOffset(s_size)) {
+1 -5
View File
@@ -36,11 +36,7 @@ namespace mmkv {
NSString *CodedInputDataCrypt::readNSString(KeyValueHolderCrypt &kvHolder) {
kvHolder.offset = static_cast<uint32_t>(m_position);
int32_t size = this->readRawVarint32(true);
if (size < 0) {
throw length_error("InvalidProtocolBuffer negativeSize");
}
uint32_t size = static_cast<uint32_t>(readRawVarint32(true));
auto s_size = static_cast<size_t>(size);
if (s_size <= m_size - m_position) {
if (s_size > mmkv::KeySizeLimit) {
+3 -15
View File
@@ -34,11 +34,7 @@ using namespace std;
namespace mmkv {
NSString *CodedInputData::readNSString() {
int32_t size = this->readRawVarint32();
if (size < 0) {
throw length_error("InvalidProtocolBuffer negativeSize");
}
uint32_t size = readUInt32();
auto s_size = static_cast<size_t>(size);
if (s_size <= m_size - m_position) {
auto ptr = m_ptr + m_position;
@@ -53,11 +49,7 @@ NSString *CodedInputData::readNSString() {
NSString *CodedInputData::readNSString(KeyValueHolder &kvHolder) {
kvHolder.offset = static_cast<uint32_t>(m_position);
int32_t size = this->readRawVarint32();
if (size < 0) {
throw length_error("InvalidProtocolBuffer negativeSize");
}
uint32_t size = readUInt32();
auto s_size = static_cast<size_t>(size);
if (s_size <= m_size - m_position) {
if (s_size > mmkv::KeySizeLimit) {
@@ -75,11 +67,7 @@ NSString *CodedInputData::readNSString(KeyValueHolder &kvHolder) {
}
NSData *CodedInputData::readNSData() {
int32_t size = this->readRawVarint32();
if (size < 0) {
throw length_error("InvalidProtocolBuffer negativeSize");
}
uint32_t size = readUInt32();
auto s_size = static_cast<size_t>(size);
if (s_size <= m_size - m_position) {
NSData *result = [NSData dataWithBytes:(m_ptr + m_position) length:s_size];
+4 -6
View File
@@ -1039,12 +1039,10 @@ size_t MMKV::getValueSize(MMKVKey_t key, bool actualSize) {
if (actualSize) {
try {
CodedInputData input(data.getPtr(), data.length());
auto length = input.readInt32();
if (length >= 0) {
auto s_length = static_cast<size_t>(length);
if (pbRawVarint32Size(length) + s_length == data.length()) {
return s_length;
}
auto length = input.readUInt32();
auto s_length = static_cast<size_t>(length);
if (pbRawVarint32Size(length) + s_length == data.length()) {
return s_length;
}
} catch (std::exception &exception) {
MMKVError("%s", exception.what());
+40 -8
View File
@@ -19,6 +19,7 @@
*/
#include <MMKV/MMKV.h>
#include "CodedInputData.h"
#include "CodedOutputData.h"
#include "PBUtility.h"
#include "aes/AESCrypt.h"
@@ -289,16 +290,19 @@ void testOversizedValue(MMKV *mmkv) {
assert(mmkv->getString("value", value) && value == "before");
assert(mmkv->set("after", "value"));
assert(mmkv->getString("value", value) && value == "after");
auto expiring = MMKV::mmkvWithID("oversized_expiring_value_test");
expiring->clearAll();
assert(expiring->enableAutoKeyExpire());
assert(!expiring->set(oversized, "value", 60));
assert(expiring->set("after", "value", 60));
assert(expiring->getString("value", value) && value == "after");
expiring->clearAll();
}
auto expiring = MMKV::mmkvWithID("oversized_expiring_value_test");
expiring->clearAll();
assert(expiring->enableAutoKeyExpire());
if (numeric_limits<size_t>::max() > numeric_limits<uint32_t>::max()) {
MMBuffer oversized(&sentinel, static_cast<size_t>(numeric_limits<uint32_t>::max()) + 1, MMBufferNoCopy);
assert(!expiring->set(oversized, "value", 60));
}
assert(expiring->set("after", "value", 60));
assert(expiring->getString("value", value) && value == "after");
expiring->clearAll();
printf("test oversized value: passed\n");
}
@@ -420,6 +424,22 @@ void testCodedOutputBounds() {
assert(equal(expected32[index].begin(), expected32[index].end(), storage.begin()));
}
constexpr array<uint8_t, 5> wideLength = {0x80, 0x80, 0x80, 0x80, 0x08};
CodedInputData wideInput(wideLength.data(), wideLength.size());
rejected = false;
try {
wideInput.readData(false);
} catch (const out_of_range &) {
rejected = true;
}
assert(rejected);
storage.fill(0);
CodedOutputData signedOutput(storage.data(), storage.size());
signedOutput.writeInt32(-1);
CodedInputData signedInput(storage.data(), signedOutput.getPosition());
assert(signedInput.readInt32() == -1);
constexpr array<uint64_t, 6> values64 = {0, 127, 128, 16383, 16384, numeric_limits<uint64_t>::max()};
const vector<vector<uint8_t>> expected64 = {
{0x00},
@@ -485,6 +505,18 @@ void testCodedOutputBounds() {
}
assert(rejected && positionOutput.getPosition() == 2);
if (numeric_limits<size_t>::max() > numeric_limits<int32_t>::max()) {
storage.fill(0xA5);
MMBuffer wideValue(storage.data(), static_cast<size_t>(numeric_limits<int32_t>::max()) + 1, MMBufferNoCopy);
CodedOutputData output(storage.data(), storage.size());
rejected = false;
try {
output.writeData(wideValue);
} catch (const out_of_range &) {
rejected = true;
}
assert(rejected && output.getPosition() == 0 && storage[0] == 0xA5);
}
if (numeric_limits<size_t>::max() > numeric_limits<uint32_t>::max()) {
storage.fill(0xA5);
MMBuffer oversized(storage.data(), static_cast<size_t>(numeric_limits<uint32_t>::max()) + 1,