@landstrip/landstrip-api 0.18.40 → 0.18.41

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.
Files changed (2) hide show
  1. package/lib/shared.js +56 -10
  2. package/package.json +7 -7
package/lib/shared.js CHANGED
@@ -230,7 +230,7 @@ function canonicalizePath(filePath, baseDirectory, seen = new Set()) {
230
230
 
231
231
  function canonicalizeGlobPattern(pattern, baseDirectory) {
232
232
  const expanded = expandPath(pattern, baseDirectory);
233
- const wildcard = expanded.indexOf('*');
233
+ const wildcard = expanded.search(/[*?[\]]/);
234
234
  if (wildcard < 0) return canonicalizePath(expanded, baseDirectory);
235
235
 
236
236
  const prefix = expanded.slice(0, wildcard);
@@ -249,19 +249,65 @@ function normalizePathSeparators(path) {
249
249
 
250
250
  const globRegExpCache = new Map();
251
251
 
252
- // Translates an absolute glob pattern to a regular expression using standard
253
- // path semantics: `**` crosses directory boundaries (and `**/` may match zero
254
- // segments), while a single `*` is confined to one path segment.
252
+ class ByteGlobRegExp extends RegExp {
253
+ exec(value) {
254
+ return super.exec(Buffer.from(String(value)).toString('latin1'));
255
+ }
256
+ }
257
+
258
+ // Translates an absolute glob pattern using the same UTF-8 byte semantics as
259
+ // the Rust policy matcher: `**` crosses directories, `*` stays within one
260
+ // segment, `?` matches one non-separator byte, and classes support byte ranges.
255
261
  function globToRegExp(globPattern) {
256
262
  const cached = globRegExpCache.get(globPattern);
257
263
  if (cached) return cached;
258
264
 
259
- const escaped = globPattern
260
- .replace(/[.+^${}()|[\]\\]/g, '\\$&')
261
- .replace(/\*\*\/|\*\*|\*/g, (token) =>
262
- token === '**/' ? '(?:.*/)?' : token === '**' ? '.*' : '[^/]*',
263
- );
264
- const result = new RegExp(`^${escaped}$`);
265
+ const pattern = Buffer.from(globPattern).toString('latin1');
266
+ let escaped = '';
267
+ for (let at = 0; at < pattern.length;) {
268
+ if (pattern.startsWith('**/', at)) {
269
+ escaped += '(?:[\\s\\S]*/)?';
270
+ at += 3;
271
+ } else if (pattern.startsWith('**', at)) {
272
+ escaped += '[\\s\\S]*';
273
+ at += 2;
274
+ } else if (pattern[at] === '*') {
275
+ escaped += '[^/]*';
276
+ at += 1;
277
+ } else if (pattern[at] === '?') {
278
+ escaped += '[^/]';
279
+ at += 1;
280
+ } else if (pattern[at] === '[') {
281
+ const end = pattern.indexOf(']', at + 1);
282
+ if (end < 0) {
283
+ escaped += '\\[';
284
+ at += 1;
285
+ continue;
286
+ }
287
+
288
+ const content = pattern.slice(at + 1, end);
289
+ const hex = (code) => `\\x${code.toString(16).padStart(2, '0')}`;
290
+ let characterClass = '';
291
+ for (let offset = 0; offset < content.length;) {
292
+ if (offset + 2 < content.length && content[offset + 1] === '-') {
293
+ const start = content.charCodeAt(offset);
294
+ const finish = content.charCodeAt(offset + 2);
295
+ if (start <= finish) characterClass += `${hex(start)}-${hex(finish)}`;
296
+ offset += 3;
297
+ } else {
298
+ characterClass += hex(content.charCodeAt(offset));
299
+ offset += 1;
300
+ }
301
+ }
302
+ escaped += characterClass ? `(?=[^/])[${characterClass}]` : '(?!)';
303
+ at = end + 1;
304
+ } else {
305
+ escaped += pattern[at].replace(/[\\^$.*+?()[\]{}|]/g, '\\$&');
306
+ at += 1;
307
+ }
308
+ }
309
+
310
+ const result = new ByteGlobRegExp(`^${escaped}(?![\\s\\S])`);
265
311
  globRegExpCache.set(globPattern, result);
266
312
  return result;
267
313
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@landstrip/landstrip-api",
3
- "version": "0.18.40",
3
+ "version": "0.18.41",
4
4
  "description": "Sandbox runner using Landlock, Seatbelt, and AppContainer",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/landstrip/landstrip#readme",
@@ -37,12 +37,12 @@
37
37
  "LICENSE"
38
38
  ],
39
39
  "optionalDependencies": {
40
- "@landstrip/landstrip-darwin-arm64": "0.18.40",
41
- "@landstrip/landstrip-darwin-x64": "0.18.40",
42
- "@landstrip/landstrip-linux-x64": "0.18.40",
43
- "@landstrip/landstrip-linux-arm64": "0.18.40",
44
- "@landstrip/landstrip-win32-x64": "0.18.40",
45
- "@landstrip/landstrip-win32-arm64": "0.18.40"
40
+ "@landstrip/landstrip-darwin-arm64": "0.18.41",
41
+ "@landstrip/landstrip-darwin-x64": "0.18.41",
42
+ "@landstrip/landstrip-linux-x64": "0.18.41",
43
+ "@landstrip/landstrip-linux-arm64": "0.18.41",
44
+ "@landstrip/landstrip-win32-x64": "0.18.41",
45
+ "@landstrip/landstrip-win32-arm64": "0.18.41"
46
46
  },
47
47
  "publishConfig": {
48
48
  "access": "public"