@componentor/fs 3.0.17 → 3.0.18
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.
- package/README.md +20 -1
- package/dist/index.d.mts +16 -1
- package/dist/index.js +46 -3
- package/dist/index.js.map +1 -1
- package/dist/workers/repair.worker.js +38 -1
- package/dist/workers/repair.worker.js.map +1 -1
- package/dist/workers/server.worker.js +38 -1
- package/dist/workers/server.worker.js.map +1 -1
- package/dist/workers/sync-relay.worker.js +109 -3
- package/dist/workers/sync-relay.worker.js.map +1 -1
- package/package.json +1 -1
|
@@ -154,6 +154,13 @@ var VFSEngine = class {
|
|
|
154
154
|
superblockDirty = false;
|
|
155
155
|
// Free inode hint — skip O(n) scan
|
|
156
156
|
freeInodeHint = 0;
|
|
157
|
+
// Configurable upper bounds
|
|
158
|
+
maxInodes = 4e6;
|
|
159
|
+
maxBlocks = 4e6;
|
|
160
|
+
maxPathTable = 256 * 1024 * 1024;
|
|
161
|
+
// 256MB
|
|
162
|
+
maxVFSSize = 100 * 1024 * 1024 * 1024;
|
|
163
|
+
// 100GB
|
|
157
164
|
init(handle, opts) {
|
|
158
165
|
this.handle = handle;
|
|
159
166
|
this.processUid = opts?.uid ?? 0;
|
|
@@ -161,11 +168,23 @@ var VFSEngine = class {
|
|
|
161
168
|
this.umask = opts?.umask ?? DEFAULT_UMASK;
|
|
162
169
|
this.strictPermissions = opts?.strictPermissions ?? false;
|
|
163
170
|
this.debug = opts?.debug ?? false;
|
|
171
|
+
if (opts?.limits) {
|
|
172
|
+
if (opts.limits.maxInodes != null) this.maxInodes = opts.limits.maxInodes;
|
|
173
|
+
if (opts.limits.maxBlocks != null) this.maxBlocks = opts.limits.maxBlocks;
|
|
174
|
+
if (opts.limits.maxPathTable != null) this.maxPathTable = opts.limits.maxPathTable;
|
|
175
|
+
if (opts.limits.maxVFSSize != null) this.maxVFSSize = opts.limits.maxVFSSize;
|
|
176
|
+
}
|
|
164
177
|
const size = handle.getSize();
|
|
165
178
|
if (size === 0) {
|
|
166
179
|
this.format();
|
|
167
180
|
} else {
|
|
168
|
-
|
|
181
|
+
try {
|
|
182
|
+
this.mount();
|
|
183
|
+
} catch (err) {
|
|
184
|
+
const msg = err.message ?? String(err);
|
|
185
|
+
if (msg.startsWith("Corrupt VFS:")) throw err;
|
|
186
|
+
throw new Error(`Corrupt VFS: ${msg}`);
|
|
187
|
+
}
|
|
169
188
|
}
|
|
170
189
|
}
|
|
171
190
|
/** Release the sync access handle (call on fatal error or shutdown) */
|
|
@@ -232,6 +251,18 @@ var VFSEngine = class {
|
|
|
232
251
|
if (freeBlocks > totalBlocks) {
|
|
233
252
|
throw new Error(`Corrupt VFS: free blocks (${freeBlocks}) exceeds total blocks (${totalBlocks})`);
|
|
234
253
|
}
|
|
254
|
+
if (inodeCount > this.maxInodes) {
|
|
255
|
+
throw new Error(`Corrupt VFS: inode count ${inodeCount} exceeds maximum ${this.maxInodes}`);
|
|
256
|
+
}
|
|
257
|
+
if (totalBlocks > this.maxBlocks) {
|
|
258
|
+
throw new Error(`Corrupt VFS: total blocks ${totalBlocks} exceeds maximum ${this.maxBlocks}`);
|
|
259
|
+
}
|
|
260
|
+
if (fileSize > this.maxVFSSize) {
|
|
261
|
+
throw new Error(`Corrupt VFS: file size ${fileSize} exceeds maximum ${this.maxVFSSize}`);
|
|
262
|
+
}
|
|
263
|
+
if (!Number.isFinite(inodeTableOffset) || inodeTableOffset < 0 || !Number.isFinite(pathTableOffset) || pathTableOffset < 0 || !Number.isFinite(bitmapOffset) || bitmapOffset < 0 || !Number.isFinite(dataOffset) || dataOffset < 0) {
|
|
264
|
+
throw new Error(`Corrupt VFS: non-finite or negative section offset`);
|
|
265
|
+
}
|
|
235
266
|
if (inodeTableOffset !== SUPERBLOCK.SIZE) {
|
|
236
267
|
throw new Error(`Corrupt VFS: inode table offset ${inodeTableOffset} (expected ${SUPERBLOCK.SIZE})`);
|
|
237
268
|
}
|
|
@@ -249,7 +280,13 @@ var VFSEngine = class {
|
|
|
249
280
|
if (pathUsed > pathTableSize) {
|
|
250
281
|
throw new Error(`Corrupt VFS: path used (${pathUsed}) exceeds path table size (${pathTableSize})`);
|
|
251
282
|
}
|
|
283
|
+
if (pathTableSize > this.maxPathTable) {
|
|
284
|
+
throw new Error(`Corrupt VFS: path table size ${pathTableSize} exceeds maximum ${this.maxPathTable}`);
|
|
285
|
+
}
|
|
252
286
|
const expectedMinSize = dataOffset + totalBlocks * blockSize;
|
|
287
|
+
if (expectedMinSize > this.maxVFSSize) {
|
|
288
|
+
throw new Error(`Corrupt VFS: computed layout size ${expectedMinSize} exceeds maximum ${this.maxVFSSize}`);
|
|
289
|
+
}
|
|
253
290
|
if (fileSize < expectedMinSize) {
|
|
254
291
|
throw new Error(`Corrupt VFS: file size ${fileSize} too small for layout (need ${expectedMinSize})`);
|
|
255
292
|
}
|