Skip to content

Commit f4a9140

Browse files
committed
Fix writing large blobs through opfs-locks
1 parent 36590b3 commit f4a9140

File tree

6 files changed

+53
-4
lines changed

6 files changed

+53
-4
lines changed

sqlite3/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 2.6.1
2+
3+
- Fix out-of-bound reads in the `xWrite` implementation of the OPFS-locks based
4+
file-system implementation when writing more than 64 KiB in one operation.
5+
16
## 2.6.0
27

38
- Add `SimpleOpfsFileSystem.deleteFromStorage` to delete OPFS-based file

sqlite3/lib/src/wasm/vfs/async_opfs/client.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,11 @@ class WasmFile extends BaseVfsFile {
202202
// buffer would otherwise overflow.
203203
final bytesToWrite = min(MessageSerializer.dataSize, remainingBytes);
204204

205-
final subBuffer = bytesToWrite == remainingBytes
206-
? buffer
207-
: buffer.buffer.asUint8List(buffer.offsetInBytes, bytesToWrite);
205+
final subBuffer =
206+
(bytesToWrite == remainingBytes && totalBytesWritten == 0)
207+
? buffer
208+
: buffer.buffer.asUint8List(
209+
buffer.offsetInBytes + totalBytesWritten, bytesToWrite);
208210
vfs.serializer.byteView.set(subBuffer, 0);
209211

210212
vfs._runInWorker(WorkerOperation.xWrite,

sqlite3/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: sqlite3
22
description: Provides lightweight yet convenient bindings to SQLite by using dart:ffi
3-
version: 2.6.0
3+
version: 2.6.1
44
homepage: https://github.com/simolus3/sqlite3.dart/tree/main/sqlite3
55
issue_tracker: https://github.com/simolus3/sqlite3.dart/issues
66

sqlite3_web/test/integration_test.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,16 @@ void main() {
181181
await driver.assertFile(false);
182182
}
183183
});
184+
185+
test('check large write and read', () async {
186+
await driver.openDatabase(
187+
implementation: (storage, access),
188+
onlyOpenVfs: true,
189+
);
190+
await driver.assertFile(false);
191+
192+
await driver.checkReadWrite();
193+
});
184194
}
185195
});
186196
}

sqlite3_web/tool/server.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,14 @@ class TestWebDriver {
209209
}
210210
}
211211

212+
Future<void> checkReadWrite() async {
213+
final result =
214+
await driver.executeAsync('check_read_write("", arguments[0])', []);
215+
if (result != null) {
216+
throw 'check_read_write() failed: $result';
217+
}
218+
}
219+
212220
Future<void> delete(StorageMode mode) async {
213221
await driver
214222
.executeAsync('delete_db(arguments[0], arguments[1])', [mode.name]);

sqlite3_web/web/main.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:convert';
22
import 'dart:html';
33
import 'dart:js_interop';
44
import 'dart:js_interop_unsafe';
5+
import 'dart:typed_data';
56

67
import 'package:sqlite3_web/sqlite3_web.dart';
78

@@ -64,6 +65,29 @@ void main() {
6465
.deleteDatabase(name: databaseName, storage: storage);
6566
return true.toJS;
6667
});
68+
_addCallbackForWebDriver('check_read_write', (arg) async {
69+
final vfs = database!.fileSystem;
70+
71+
final bytes = Uint8List(1024 * 128);
72+
for (var i = 0; i < 128; i++) {
73+
bytes[i * 1024] = i;
74+
}
75+
76+
await vfs.writeFile(FileType.database, bytes);
77+
await vfs.flush();
78+
final result = await vfs.readFile(FileType.database);
79+
if (result.length != bytes.length) {
80+
return 'length mismatch'.toJS;
81+
}
82+
83+
for (var i = 0; i < 128; i++) {
84+
if (result[i * 1024] != i) {
85+
return 'mismatch, i=$i, byte ${result[i * 1024]}'.toJS;
86+
}
87+
}
88+
89+
return null;
90+
});
6791

6892
document.getElementById('selfcheck')?.onClick.listen((event) async {
6993
print('starting');

0 commit comments

Comments
 (0)