mirror of
https://github.com/Tencent/MMKV.git
synced 2026-10-16 20:21:12 +08:00
Support unsigned protobuf value lengths
This commit is contained in:
+10
-29
@@ -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() {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user