react-native-mmkv 3.0.0-beta.7 → 3.0.0-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -131,7 +131,7 @@ uint32_t KeyValueHolderCrypt::realValueSize() const {
131
131
 
132
132
  // get decrypt data with [position, -1)
133
133
  static MMBuffer decryptBuffer(AESCrypt &crypter, const MMBuffer &inputBuffer, size_t position) {
134
- static size_t smallBuffer[16 / sizeof(size_t)];
134
+ size_t smallBuffer[16 / sizeof(size_t)];
135
135
  auto basePtr = (uint8_t *) inputBuffer.getPtr();
136
136
  auto ptr = basePtr;
137
137
  for (size_t index = sizeof(smallBuffer); index < position; index += sizeof(smallBuffer)) {
@@ -78,7 +78,11 @@ struct KeyValueHolderCrypt {
78
78
  return sizeof(KeyValueHolderCrypt) - offsetof(KeyValueHolderCrypt, paddedValue);
79
79
  }
80
80
 
81
- static bool isValueStoredAsOffset(size_t valueSize) { return valueSize >= 256; }
81
+ static constexpr size_t MediumBufferSize() {
82
+ return 256;
83
+ }
84
+
85
+ static bool isValueStoredAsOffset(size_t valueSize) { return valueSize > MediumBufferSize(); }
82
86
 
83
87
  KeyValueHolderCrypt() = default;
84
88
  KeyValueHolderCrypt(const void *valuePtr, size_t valueLength);
@@ -34,7 +34,7 @@
34
34
  #include <vector>
35
35
  #include <unordered_map>
36
36
 
37
- constexpr auto MMKV_VERSION = "v1.3.7";
37
+ constexpr auto MMKV_VERSION = "v1.3.9";
38
38
 
39
39
  #ifdef DEBUG
40
40
  # define MMKV_DEBUG
@@ -338,7 +338,6 @@ void MMKV::checkLoadData() {
338
338
  }
339
339
  }
340
340
 
341
- constexpr uint32_t ItemSizeHolder = 0x00ffffff;
342
341
  constexpr uint32_t ItemSizeHolderSize = 4;
343
342
 
344
343
  static pair<MMBuffer, size_t> prepareEncode(const MMKVMap &dic) {
@@ -911,17 +910,22 @@ KVHolderRet_t MMKV::doOverrideDataWithKey(const MMBuffer &data,
911
910
  } else {
912
911
  m_crypter->resetIV();
913
912
  }
914
- if (KeyValueHolderCrypt::isValueStoredAsOffset(valueLength)) {
915
- m_crypter->getCurStatus(t_status);
916
- }
917
913
  }
918
914
  #endif
919
915
  try {
920
916
  // write ItemSizeHolder
921
917
  m_output->setPosition(0);
922
- m_output->writeRawVarint32(ItemSizeHolder);
918
+ m_output->writeUInt32(AESCrypt::randomItemSizeHolder(ItemSizeHolderSize));
923
919
  m_actualSize = ItemSizeHolderSize;
924
-
920
+ #ifndef MMKV_DISABLE_CRYPT
921
+ if (m_crypter) {
922
+ auto ptr = (uint8_t *) m_file->getMemory() + Fixed32Size;
923
+ m_crypter->encrypt(ptr, ptr, m_actualSize);
924
+ if (KeyValueHolderCrypt::isValueStoredAsOffset(valueLength)) {
925
+ m_crypter->getCurStatus(t_status);
926
+ }
927
+ }
928
+ #endif
925
929
  if (isKeyEncoded) {
926
930
  m_output->writeRawData(keyData);
927
931
  } else {
@@ -941,10 +945,10 @@ KVHolderRet_t MMKV::doOverrideDataWithKey(const MMBuffer &data,
941
945
 
942
946
  auto offset = static_cast<uint32_t>(m_actualSize);
943
947
  m_actualSize += size;
944
- auto ptr = (uint8_t *) m_file->getMemory() + Fixed32Size;
945
948
  #ifndef MMKV_DISABLE_CRYPT
946
949
  if (m_crypter) {
947
- m_crypter->encrypt(ptr, ptr, m_actualSize);
950
+ auto ptr = (uint8_t *) m_file->getMemory() + Fixed32Size + offset;
951
+ m_crypter->encrypt(ptr, ptr, size);
948
952
  }
949
953
  #endif
950
954
  recalculateCRCDigestOnly();
@@ -1128,7 +1132,7 @@ memmoveDictionary(MMKVMap &dic, CodedOutputData *output, uint8_t *ptr, AESCrypt
1128
1132
  }
1129
1133
  }
1130
1134
  // hold the fake size of dictionary's serialization result
1131
- output->writeRawVarint32(ItemSizeHolder);
1135
+ output->writeUInt32(AESCrypt::randomItemSizeHolder(ItemSizeHolderSize));
1132
1136
  auto writtenSize = static_cast<size_t>(writePtr - originOutputPtr);
1133
1137
  #ifndef MMKV_DISABLE_CRYPT
1134
1138
  if (encrypter) {
@@ -1159,14 +1163,16 @@ static void memmoveDictionary(MMKVMapCrypt &dic,
1159
1163
  }
1160
1164
  sort(vec.begin(), vec.end(), [](auto left, auto right) { return left->offset < right->offset; });
1161
1165
  }
1162
- auto sizeHolder = ItemSizeHolder, sizeHolderSize = ItemSizeHolderSize;
1166
+ auto sizeHolderSize = ItemSizeHolderSize;
1167
+ auto sizeHolder = AESCrypt::randomItemSizeHolder(sizeHolderSize);
1163
1168
  if (!vec.empty()) {
1164
1169
  auto smallestOffset = vec.front()->offset;
1165
1170
  if (smallestOffset != ItemSizeHolderSize && smallestOffset <= 5) {
1166
1171
  sizeHolderSize = smallestOffset;
1167
1172
  assert(sizeHolderSize != 0);
1168
1173
  static const uint32_t ItemSizeHolders[] = {0, 0x0f, 0xff, 0xffff, 0xffffff, 0xffffffff};
1169
- sizeHolder = ItemSizeHolders[sizeHolderSize];
1174
+ sizeHolder = AESCrypt::randomItemSizeHolder(sizeHolderSize);
1175
+ assert(sizeHolder >= ItemSizeHolders[sizeHolderSize] && sizeHolder <= ItemSizeHolders[sizeHolderSize]);
1170
1176
  }
1171
1177
  }
1172
1178
  output->writeRawVarint32(static_cast<int32_t>(sizeHolder));
@@ -1230,7 +1236,7 @@ static void memmoveDictionary(MMKVMapCrypt &dic,
1230
1236
 
1231
1237
  static void fullWriteBackWholeData(MMBuffer allData, size_t totalSize, CodedOutputData *output) {
1232
1238
  auto originOutputPtr = output->curWritePointer();
1233
- output->writeRawVarint32(ItemSizeHolder);
1239
+ output->writeUInt32(AESCrypt::randomItemSizeHolder(ItemSizeHolderSize));
1234
1240
  if (allData.length() > 0) {
1235
1241
  auto dataSize = CodedInputData(allData.getPtr(), allData.length()).readUInt32();
1236
1242
  if (dataSize > 0) {
@@ -260,35 +260,21 @@ MMKV::appendDataWithKey(const MMBuffer &data, MMKVKey_t key, const KeyValueHolde
260
260
 
261
261
  pair<bool, KeyValueHolder>
262
262
  MMKV::overrideDataWithKey(const MMBuffer &data, MMKVKey_t key, const KeyValueHolderCrypt &kvHolder, bool isDataHolder) {
263
- size_t old_actualSize = m_actualSize;
264
- size_t old_position = m_output->getPosition();
265
- // only one key in dict, do not append, just rewrite from beginning
266
- m_actualSize = 0;
267
- m_output->setPosition(0);
268
-
269
- auto m_tmpDic = m_dic;
270
- auto m_tmpDicCrypt = m_dicCrypt;
271
- if (m_crypter) {
272
- m_dicCrypt = new MMKVMapCrypt();
273
- } else {
274
- m_dic = new MMKVMap();
263
+ if (kvHolder.type != KeyValueHolderType_Offset) {
264
+ return overrideDataWithKey(data, key, isDataHolder);
275
265
  }
266
+ SCOPED_LOCK(m_exclusiveProcessLock);
276
267
 
277
- auto ret = appendDataWithKey(data, key, kvHolder, isDataHolder);
278
- if (!ret.first) {
279
- // rollback
280
- m_actualSize = old_actualSize;
281
- m_output->setPosition(old_position);
282
- }
268
+ uint32_t keyLength = kvHolder.keySize;
269
+ // size needed to encode the key
270
+ size_t rawKeySize = keyLength + pbRawVarint32Size(keyLength);
283
271
 
284
- if (m_crypter) {
285
- delete m_dicCrypt;
286
- m_dicCrypt = m_tmpDicCrypt;
287
- } else {
288
- delete m_dic;
289
- m_dic = m_tmpDic;
290
- }
291
- return ret;
272
+ auto basePtr = (uint8_t *) m_file->getMemory() + Fixed32Size;
273
+ MMBuffer keyData(rawKeySize);
274
+ AESCrypt decrypter = m_crypter->cloneWithStatus(kvHolder.cryptStatus);
275
+ decrypter.decrypt(basePtr + kvHolder.offset, keyData.getPtr(), rawKeySize);
276
+
277
+ return doOverrideDataWithKey(data, keyData, isDataHolder, keyLength);
292
278
  }
293
279
  # endif
294
280
 
@@ -38,10 +38,8 @@ ThreadLock::ThreadLock() : m_lock({}) {
38
38
  }
39
39
 
40
40
  ThreadLock::~ThreadLock() {
41
- #ifdef MMKV_OHOS
42
- // OHOS's pthread is buggy, check for POC: https://gist.github.com/lingol/622af352e090e0490ebacfe3a38b9221
43
41
  pthread_mutex_unlock(&m_lock);
44
- #endif
42
+
45
43
  pthread_mutex_destroy(&m_lock);
46
44
  }
47
45
 
@@ -25,12 +25,25 @@
25
25
  #include <cstring>
26
26
  #include <ctime>
27
27
 
28
+ namespace mmkv {
29
+
30
+ // assuming size in [1, 5]
31
+ uint32_t AESCrypt::randomItemSizeHolder(uint32_t size) {
32
+ constexpr uint32_t ItemSizeHolders[] = {0, 0x80, 0x4000, 0x200000, 0x10000000, 0};
33
+ auto ItemSizeHolderMin = ItemSizeHolders[size - 1];
34
+ auto ItemSizeHolderMax = ItemSizeHolders[size] - 1;
35
+
36
+ srand((unsigned) time(nullptr));
37
+ auto result = static_cast<uint32_t>(rand());
38
+ result = result % (ItemSizeHolderMax - ItemSizeHolderMin + 1);
39
+ result += ItemSizeHolderMin;
40
+ return result;
41
+ }
42
+
28
43
  #ifndef MMKV_DISABLE_CRYPT
29
44
 
30
45
  using namespace openssl;
31
46
 
32
- namespace mmkv {
33
-
34
47
  AESCrypt::AESCrypt(const void *key, size_t keyLength, const void *iv, size_t ivLength) {
35
48
  if (key && keyLength > 0) {
36
49
  memcpy(m_key, key, (keyLength > AES_KEY_LEN) ? AES_KEY_LEN : keyLength);
@@ -161,8 +174,6 @@ AESCrypt AESCrypt::cloneWithStatus(const AESCryptStatus &status) const {
161
174
  return AESCrypt(*this, status);
162
175
  }
163
176
 
164
- } // namespace mmkv
165
-
166
177
  # ifdef MMKV_DEBUG
167
178
 
168
179
  # include "../MMKVLog.h"
@@ -170,8 +181,17 @@ AESCrypt AESCrypt::cloneWithStatus(const AESCryptStatus &status) const {
170
181
 
171
182
  namespace mmkv {
172
183
 
184
+ void testRandomPlaceHolder() {
185
+ for (uint32_t size = 1; size < 6; size++) {
186
+ auto holder = AESCrypt::randomItemSizeHolder(size);
187
+ MMKVInfo("holder 0x%x for size %u", holder, size);
188
+ }
189
+ }
190
+
173
191
  // check if AESCrypt is encrypt-decrypt full-duplex
174
192
  void AESCrypt::testAESCrypt() {
193
+ testRandomPlaceHolder();
194
+
175
195
  const uint8_t plainText[] = "Hello, OpenSSL-mmkv::AESCrypt::testAESCrypt() with AES CFB 128.";
176
196
  constexpr size_t textLength = sizeof(plainText) - 1;
177
197
 
@@ -250,7 +270,7 @@ void AESCrypt::testAESCrypt() {
250
270
  delete[] decryptText;
251
271
  }
252
272
 
253
- } // namespace mmkv
254
-
255
273
  # endif // MMKV_DEBUG
256
274
  #endif // MMKV_DISABLE_CRYPT
275
+
276
+ } // namespace mmkv
@@ -29,7 +29,10 @@
29
29
  #ifdef MMKV_DISABLE_CRYPT
30
30
 
31
31
  namespace mmkv {
32
- class AESCrypt;
32
+ class AESCrypt {
33
+ public:
34
+ static uint32_t randomItemSizeHolder(uint32_t size);
35
+ };
33
36
  }
34
37
 
35
38
  #else
@@ -88,6 +91,7 @@ public:
88
91
  void getKey(void *output) const;
89
92
 
90
93
  static void fillRandomIV(void *vector);
94
+ static uint32_t randomItemSizeHolder(uint32_t size);
91
95
 
92
96
  // just forbid it for possibly misuse
93
97
  explicit AESCrypt(const AESCrypt &other) = delete;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-mmkv",
3
- "version": "3.0.0-beta.7",
3
+ "version": "3.0.0-beta.8",
4
4
  "description": "The fastest key/value storage for React Native. ~30x faster than AsyncStorage! Works on Android, iOS and Web.",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",