mirror of
https://github.com/status-im/react-native.git
synced 2025-01-29 10:45:04 +00:00
Protect against SQLiteFullExceptions
Reviewed By: @kmagiera Differential Revision: D2512317 fb-gh-sync-id: 93fd65ebd88e42b5afc4e06c0612576101f15c97
This commit is contained in:
parent
b7b83e4f12
commit
ea8d0b6c1f
@ -23,6 +23,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.SetBuilder;
|
||||
import com.facebook.react.modules.common.ModuleDataCleaner;
|
||||
@ -137,8 +138,9 @@ public final class AsyncStorageModule
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FLog.w(ReactConstants.TAG, "Exception in database multiGet ", e);
|
||||
FLog.w(ReactConstants.TAG, e.getMessage(), e);
|
||||
callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()), null);
|
||||
return;
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
@ -179,19 +181,20 @@ public final class AsyncStorageModule
|
||||
|
||||
String sql = "INSERT OR REPLACE INTO " + TABLE_CATALYST + " VALUES (?, ?);";
|
||||
SQLiteStatement statement = mReactDatabaseSupplier.get().compileStatement(sql);
|
||||
mReactDatabaseSupplier.get().beginTransaction();
|
||||
WritableMap error = null;
|
||||
try {
|
||||
mReactDatabaseSupplier.get().beginTransaction();
|
||||
for (int idx=0; idx < keyValueArray.size(); idx++) {
|
||||
if (keyValueArray.getArray(idx).size() != 2) {
|
||||
callback.invoke(AsyncStorageErrorUtil.getInvalidValueError(null));
|
||||
error = AsyncStorageErrorUtil.getInvalidValueError(null);
|
||||
return;
|
||||
}
|
||||
if (keyValueArray.getArray(idx).getString(0) == null) {
|
||||
callback.invoke(AsyncStorageErrorUtil.getInvalidKeyError(null));
|
||||
error = AsyncStorageErrorUtil.getInvalidKeyError(null);
|
||||
return;
|
||||
}
|
||||
if (keyValueArray.getArray(idx).getString(1) == null) {
|
||||
callback.invoke(AsyncStorageErrorUtil.getInvalidValueError(null));
|
||||
error = AsyncStorageErrorUtil.getInvalidValueError(null);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -202,12 +205,23 @@ public final class AsyncStorageModule
|
||||
}
|
||||
mReactDatabaseSupplier.get().setTransactionSuccessful();
|
||||
} catch (Exception e) {
|
||||
FLog.w(ReactConstants.TAG, "Exception in database multiSet ", e);
|
||||
callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()));
|
||||
FLog.w(ReactConstants.TAG, e.getMessage(), e);
|
||||
error = AsyncStorageErrorUtil.getError(null, e.getMessage());
|
||||
} finally {
|
||||
mReactDatabaseSupplier.get().endTransaction();
|
||||
try {
|
||||
mReactDatabaseSupplier.get().endTransaction();
|
||||
} catch (Exception e) {
|
||||
FLog.w(ReactConstants.TAG, e.getMessage(), e);
|
||||
if (error == null) {
|
||||
error = AsyncStorageErrorUtil.getError(null, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error != null) {
|
||||
callback.invoke(error);
|
||||
} else {
|
||||
callback.invoke();
|
||||
}
|
||||
callback.invoke();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
@ -230,8 +244,9 @@ public final class AsyncStorageModule
|
||||
return;
|
||||
}
|
||||
|
||||
mReactDatabaseSupplier.get().beginTransaction();
|
||||
WritableMap error = null;
|
||||
try {
|
||||
mReactDatabaseSupplier.get().beginTransaction();
|
||||
for (int keyStart = 0; keyStart < keys.size(); keyStart += MAX_SQL_KEYS) {
|
||||
int keyCount = Math.min(keys.size() - keyStart, MAX_SQL_KEYS);
|
||||
mReactDatabaseSupplier.get().delete(
|
||||
@ -241,12 +256,23 @@ public final class AsyncStorageModule
|
||||
}
|
||||
mReactDatabaseSupplier.get().setTransactionSuccessful();
|
||||
} catch (Exception e) {
|
||||
FLog.w(ReactConstants.TAG, "Exception in database multiRemove ", e);
|
||||
callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()));
|
||||
FLog.w(ReactConstants.TAG, e.getMessage(), e);
|
||||
error = AsyncStorageErrorUtil.getError(null, e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
mReactDatabaseSupplier.get().endTransaction();
|
||||
} catch (Exception e) {
|
||||
FLog.w(ReactConstants.TAG, e.getMessage(), e);
|
||||
if (error == null) {
|
||||
error = AsyncStorageErrorUtil.getError(null, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error != null) {
|
||||
callback.invoke(error);
|
||||
} else {
|
||||
callback.invoke();
|
||||
}
|
||||
callback.invoke();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
@ -264,21 +290,22 @@ public final class AsyncStorageModule
|
||||
callback.invoke(AsyncStorageErrorUtil.getDBError(null));
|
||||
return;
|
||||
}
|
||||
mReactDatabaseSupplier.get().beginTransaction();
|
||||
WritableMap error = null;
|
||||
try {
|
||||
mReactDatabaseSupplier.get().beginTransaction();
|
||||
for (int idx = 0; idx < keyValueArray.size(); idx++) {
|
||||
if (keyValueArray.getArray(idx).size() != 2) {
|
||||
callback.invoke(AsyncStorageErrorUtil.getInvalidValueError(null));
|
||||
error = AsyncStorageErrorUtil.getInvalidValueError(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (keyValueArray.getArray(idx).getString(0) == null) {
|
||||
callback.invoke(AsyncStorageErrorUtil.getInvalidKeyError(null));
|
||||
error = AsyncStorageErrorUtil.getInvalidKeyError(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (keyValueArray.getArray(idx).getString(1) == null) {
|
||||
callback.invoke(AsyncStorageErrorUtil.getInvalidValueError(null));
|
||||
error = AsyncStorageErrorUtil.getInvalidValueError(null);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -286,18 +313,29 @@ public final class AsyncStorageModule
|
||||
mReactDatabaseSupplier.get(),
|
||||
keyValueArray.getArray(idx).getString(0),
|
||||
keyValueArray.getArray(idx).getString(1))) {
|
||||
callback.invoke(AsyncStorageErrorUtil.getDBError(null));
|
||||
error = AsyncStorageErrorUtil.getDBError(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mReactDatabaseSupplier.get().setTransactionSuccessful();
|
||||
} catch (Exception e) {
|
||||
FLog.w(ReactConstants.TAG, e.getMessage(), e);
|
||||
callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()));
|
||||
error = AsyncStorageErrorUtil.getError(null, e.getMessage());
|
||||
} finally {
|
||||
mReactDatabaseSupplier.get().endTransaction();
|
||||
try {
|
||||
mReactDatabaseSupplier.get().endTransaction();
|
||||
} catch (Exception e) {
|
||||
FLog.w(ReactConstants.TAG, e.getMessage(), e);
|
||||
if (error == null) {
|
||||
error = AsyncStorageErrorUtil.getError(null, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error != null) {
|
||||
callback.invoke(error);
|
||||
} else {
|
||||
callback.invoke();
|
||||
}
|
||||
callback.invoke();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
@ -316,11 +354,11 @@ public final class AsyncStorageModule
|
||||
}
|
||||
try {
|
||||
mReactDatabaseSupplier.get().delete(TABLE_CATALYST, null, null);
|
||||
callback.invoke();
|
||||
} catch (Exception e) {
|
||||
FLog.w(ReactConstants.TAG, "Exception in database clear ", e);
|
||||
FLog.w(ReactConstants.TAG, e.getMessage(), e);
|
||||
callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()));
|
||||
}
|
||||
callback.invoke();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
@ -348,8 +386,9 @@ public final class AsyncStorageModule
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FLog.w(ReactConstants.TAG, "Exception in database getAllKeys ", e);
|
||||
FLog.w(ReactConstants.TAG, e.getMessage(), e);
|
||||
callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()), null);
|
||||
return;
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
|
@ -21,8 +21,10 @@ public class ReactDatabaseSupplier extends SQLiteOpenHelper {
|
||||
|
||||
// VisibleForTesting
|
||||
public static final String DATABASE_NAME = "RKStorage";
|
||||
static final int DATABASE_VERSION = 1;
|
||||
|
||||
private static final int DATABASE_VERSION = 1;
|
||||
private static final int SLEEP_TIME_MS = 30;
|
||||
private static final long DEFAULT_MAX_DB_SIZE = 6L * 1024L * 1024L; // 6 MB in bytes
|
||||
|
||||
static final String TABLE_CATALYST = "catalystLocalStorage";
|
||||
static final String KEY_COLUMN = "key";
|
||||
@ -85,6 +87,10 @@ public class ReactDatabaseSupplier extends SQLiteOpenHelper {
|
||||
if (mDb == null) {
|
||||
throw lastSQLiteException;
|
||||
}
|
||||
// This is a sane limit to protect the user from the app storing too much data in the database.
|
||||
// This also protects the database from filling up the disk cache and becoming malformed
|
||||
// (endTransaction() calls will throw an exception, not rollback, and leave the db malformed).
|
||||
mDb.setMaximumSize(DEFAULT_MAX_DB_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user