@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.
@@ -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
- this.mount();
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
  }