Skip to content

Commit e3b4bd7

Browse files
BREAKING(tar/unstable): fix handling of mode, uid, and gid (#6440)
Co-authored-by: Yohe-Am <[email protected]>
1 parent ae95786 commit e3b4bd7

File tree

4 files changed

+50
-71
lines changed

4 files changed

+50
-71
lines changed

tar/tar_stream.ts

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,17 @@ type TarStreamInputInternal =
6868
export interface TarStreamOptions {
6969
/**
7070
* An octal literal.
71-
* Defaults to 755 for directories and 644 for files.
71+
* Defaults to 0o755 for directories and 0o644 for files.
7272
*/
7373
mode?: number;
7474
/**
7575
* An octal literal.
76-
* @default {0}
76+
* @default {0o0}
7777
*/
7878
uid?: number;
7979
/**
8080
* An octal literal.
81-
* @default {0}
81+
* @default {0o0}
8282
*/
8383
gid?: number;
8484
/**
@@ -208,9 +208,9 @@ export class TarStream implements TransformStream<TarStreamInput, Uint8Array> {
208208
const header = new Uint8Array(512);
209209
const size = "size" in chunk ? chunk.size : 0;
210210
const options: Required<TarStreamOptions> = {
211-
mode: typeflag === "5" ? 755 : 644,
212-
uid: 0,
213-
gid: 0,
211+
mode: typeflag === "5" ? 0o755 : 0o644,
212+
uid: 0o0,
213+
gid: 0o0,
214214
mtime: Math.floor(Date.now() / 1000),
215215
uname: "",
216216
gname: "",
@@ -222,9 +222,9 @@ export class TarStream implements TransformStream<TarStreamInput, Uint8Array> {
222222
header.set(name); // name
223223
header.set(
224224
encoder.encode(
225-
options.mode.toString().padStart(6, "0") + " \0" + // mode
226-
options.uid.toString().padStart(6, "0") + " \0" + //uid
227-
options.gid.toString().padStart(6, "0") + " \0" + // gid
225+
options.mode.toString(8).padStart(6, "0") + " \0" + // mode
226+
options.uid.toString(8).padStart(6, "0") + " \0" + //uid
227+
options.gid.toString(8).padStart(6, "0") + " \0" + // gid
228228
size.toString(8).padStart(size < 8 ** 11 ? 11 : 12, "0") +
229229
(size < 8 ** 11 ? " " : "") + // size
230230
options.mtime.toString(8).padStart(11, "0") + " " + // mtime
@@ -508,21 +508,15 @@ export function assertValidPath(path: string) {
508508
* ```
509509
*/
510510
export function assertValidTarStreamOptions(options: TarStreamOptions) {
511-
if (
512-
options.mode &&
513-
(options.mode.toString().length > 6 ||
514-
!/^[0-7]*$/.test(options.mode.toString()))
515-
) throw new TypeError("Cannot add to the tar archive: Invalid Mode provided");
516-
if (
517-
options.uid &&
518-
(options.uid.toString().length > 6 ||
519-
!/^[0-7]*$/.test(options.uid.toString()))
520-
) throw new TypeError("Cannot add to the tar archive: Invalid UID provided");
521-
if (
522-
options.gid &&
523-
(options.gid.toString().length > 6 ||
524-
!/^[0-7]*$/.test(options.gid.toString()))
525-
) throw new TypeError("Cannot add to the tar archive: Invalid GID provided");
511+
if (options.mode && (options.mode.toString(8).length > 6)) {
512+
throw new TypeError("Cannot add to the tar archive: Invalid Mode provided");
513+
}
514+
if (options.uid && (options.uid.toString(8).length > 6)) {
515+
throw new TypeError("Cannot add to the tar archive: Invalid UID provided");
516+
}
517+
if (options.gid && (options.gid.toString(8).length > 6)) {
518+
throw new TypeError("Cannot add to the tar archive: Invalid GID provided");
519+
}
526520
if (
527521
options.mtime != undefined &&
528522
(options.mtime.toString(8).length > 11 ||

tar/tar_stream_test.ts

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -204,109 +204,94 @@ Deno.test("parsePath()", async () => {
204204
Deno.test("validTarStreamOptions()", () => {
205205
assertValidTarStreamOptions({});
206206

207-
assertValidTarStreamOptions({ mode: 0 });
207+
assertValidTarStreamOptions({ mode: 0o0 });
208208
assertThrows(
209-
() => assertValidTarStreamOptions({ mode: 8 }),
209+
() => assertValidTarStreamOptions({ mode: 0o1111111 }),
210210
TypeError,
211-
"Invalid Mode provided",
212-
);
213-
assertThrows(
214-
() => assertValidTarStreamOptions({ mode: 1111111 }),
215-
TypeError,
216-
"Invalid Mode provided",
211+
"Cannot add to the tar archive: Invalid Mode provided",
217212
);
218213

219-
assertValidTarStreamOptions({ uid: 0 });
214+
assertValidTarStreamOptions({ uid: 0o0 });
220215
assertThrows(
221-
() => assertValidTarStreamOptions({ uid: 8 }),
216+
() => assertValidTarStreamOptions({ uid: 0o1111111 }),
222217
TypeError,
223-
"Invalid UID provided",
224-
);
225-
assertThrows(
226-
() => assertValidTarStreamOptions({ uid: 1111111 }),
227-
TypeError,
228-
"Invalid UID provided",
218+
"Cannot add to the tar archive: Invalid UID provided",
229219
);
230220

231-
assertValidTarStreamOptions({ gid: 0 });
232-
assertThrows(
233-
() => assertValidTarStreamOptions({ gid: 8 }),
234-
TypeError,
235-
"Invalid GID provided",
236-
);
221+
assertValidTarStreamOptions({ gid: 0o0 });
237222
assertThrows(
238-
() => assertValidTarStreamOptions({ gid: 1111111 }),
223+
() => assertValidTarStreamOptions({ gid: 0o1111111 }),
239224
TypeError,
240-
"Invalid GID provided",
225+
"Cannot add to the tar archive: Invalid GID provided",
241226
);
242227

243-
assertValidTarStreamOptions({ mtime: 0 });
228+
assertValidTarStreamOptions({ mtime: 0o0 });
244229
assertThrows(
245230
() => assertValidTarStreamOptions({ mtime: NaN }),
246231
TypeError,
247-
"Invalid MTime provided",
232+
"Cannot add to the tar archive: Invalid MTime provided",
248233
);
249234
assertValidTarStreamOptions({
250235
mtime: Math.floor(new Date().getTime() / 1000),
251236
});
252237
assertThrows(
253238
() => assertValidTarStreamOptions({ mtime: new Date().getTime() }),
254239
TypeError,
255-
"Invalid MTime provided",
240+
"Cannot add to the tar archive: Invalid MTime provided",
256241
);
257242

258243
assertValidTarStreamOptions({ uname: "" });
259244
assertValidTarStreamOptions({ uname: "abcdef" });
260245
assertThrows(
261246
() => assertValidTarStreamOptions({ uname: "å-abcdef" }),
262247
TypeError,
263-
"Invalid UName provided",
248+
"Cannot add to the tar archive: Invalid UName provided",
264249
);
265250
assertThrows(
266251
() => assertValidTarStreamOptions({ uname: "a".repeat(100) }),
267252
TypeError,
268-
"Invalid UName provided",
253+
"Cannot add to the tar archive: Invalid UName provided",
269254
);
270255

271256
assertValidTarStreamOptions({ gname: "" });
272257
assertValidTarStreamOptions({ gname: "abcdef" });
273258
assertThrows(
274259
() => assertValidTarStreamOptions({ gname: "å-abcdef" }),
275260
TypeError,
276-
"Invalid GName provided",
261+
"Cannot add to the tar archive: Invalid GName provided",
277262
);
278263
assertThrows(
279264
() => assertValidTarStreamOptions({ gname: "a".repeat(100) }),
280265
TypeError,
281-
"Invalid GName provided",
266+
"Cannot add to the tar archive: Invalid GName provided",
282267
);
283268

284269
assertValidTarStreamOptions({ devmajor: "" });
285270
assertValidTarStreamOptions({ devmajor: "1234" });
286271
assertThrows(
287272
() => assertValidTarStreamOptions({ devmajor: "123456789" }),
288273
TypeError,
289-
"Invalid DevMajor provided",
274+
"Cannot add to the tar archive: Invalid DevMajor provided",
290275
);
291276

292277
assertValidTarStreamOptions({ devminor: "" });
293278
assertValidTarStreamOptions({ devminor: "1234" });
294279
assertThrows(
295280
() => assertValidTarStreamOptions({ devminor: "123456789" }),
296281
TypeError,
297-
"Invalid DevMinor provided",
282+
"Cannot add to the tar archive: Invalid DevMinor provided",
298283
);
299284
});
300285

301286
Deno.test("TarStream() with invalid options", async () => {
302287
const readable = ReadableStream.from<TarStreamInput>([
303-
{ type: "directory", path: "potato", options: { mode: 9 } },
288+
{ type: "directory", path: "potato", options: { mode: 0o1111111 } },
304289
]).pipeThrough(new TarStream());
305290

306291
await assertRejects(
307292
() => Array.fromAsync(readable),
308293
TypeError,
309-
"Invalid Mode provided",
294+
"Cannot add to the tar archive: Invalid Mode provided",
310295
);
311296
});
312297

tar/untar_stream.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,9 @@ export class UntarStream
246246
// Decode Header
247247
let header: OldStyleFormat | PosixUstarFormat = {
248248
name: decoder.decode(value.subarray(0, 100)).split("\0")[0]!,
249-
mode: parseInt(decoder.decode(value.subarray(100, 108 - 2))),
250-
uid: parseInt(decoder.decode(value.subarray(108, 116 - 2))),
251-
gid: parseInt(decoder.decode(value.subarray(116, 124 - 2))),
249+
mode: parseInt(decoder.decode(value.subarray(100, 108)), 8),
250+
uid: parseInt(decoder.decode(value.subarray(108, 116)), 8),
251+
gid: parseInt(decoder.decode(value.subarray(116, 124)), 8),
252252
size: parseInt(decoder.decode(value.subarray(124, 136)).trimEnd(), 8),
253253
mtime: parseInt(decoder.decode(value.subarray(136, 148 - 1)), 8),
254254
typeflag: decoder.decode(value.subarray(156, 157)),

tar/untar_stream_test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ Deno.test("expandTarArchiveCheckingHeaders", async () => {
1818
type: "directory",
1919
path: "./potato",
2020
options: {
21-
mode: 111111,
22-
uid: 12,
23-
gid: 21,
21+
mode: 0o111111,
22+
uid: 0o12,
23+
gid: 0o21,
2424
mtime: seconds,
2525
uname: "potato",
2626
gname: "cake",
@@ -46,9 +46,9 @@ Deno.test("expandTarArchiveCheckingHeaders", async () => {
4646
}
4747
assertEquals(headers, [{
4848
name: "./potato",
49-
mode: 111111,
50-
uid: 12,
51-
gid: 21,
49+
mode: 0o111111,
50+
uid: 0o12,
51+
gid: 0o21,
5252
mtime: seconds,
5353
uname: "potato",
5454
gname: "cake",
@@ -62,9 +62,9 @@ Deno.test("expandTarArchiveCheckingHeaders", async () => {
6262
prefix: "",
6363
}, {
6464
name: "./text.txt",
65-
mode: 644,
66-
uid: 0,
67-
gid: 0,
65+
mode: 0o644,
66+
uid: 0o0,
67+
gid: 0o0,
6868
mtime: seconds,
6969
uname: "",
7070
gname: "",

0 commit comments

Comments
 (0)