Skip to content

Commit 1ab2268

Browse files
authored
fix(fs): improve file stat checks (#30876)
1 parent 992e998 commit 1ab2268

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed

ext/fs/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ deno_core::extension!(deno_fs,
166166
op_fs_file_sync_data_async,
167167
op_fs_file_sync_sync,
168168
op_fs_file_sync_async,
169-
op_fs_file_stat_sync,
170-
op_fs_file_stat_async,
169+
op_fs_file_stat_sync<P>,
170+
op_fs_file_stat_async<P>,
171171
op_fs_fchmod_async,
172172
op_fs_fchmod_sync,
173173
op_fs_fchown_async,

ext/fs/ops.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,13 +1772,20 @@ pub async fn op_fs_file_sync_async(
17721772
}
17731773

17741774
#[op2(fast)]
1775-
pub fn op_fs_file_stat_sync(
1775+
pub fn op_fs_file_stat_sync<P: FsPermissions + 'static>(
17761776
state: &mut OpState,
17771777
#[smi] rid: ResourceId,
17781778
#[buffer] stat_out_buf: &mut [u32],
17791779
) -> Result<(), FsOpsError> {
17801780
let file =
17811781
FileResource::get_file(state, rid).map_err(FsOpsErrorKind::Resource)?;
1782+
if let Some(path) = file.maybe_path() {
1783+
_ = state.borrow::<P>().check_open(
1784+
Cow::Borrowed(path),
1785+
OpenAccessKind::Read,
1786+
"Deno.FsFile.prototype.statSync()",
1787+
)?;
1788+
}
17821789
let stat = file.stat_sync()?;
17831790
let serializable_stat = SerializableStat::from(stat);
17841791
serializable_stat.write(stat_out_buf);
@@ -1787,12 +1794,19 @@ pub fn op_fs_file_stat_sync(
17871794

17881795
#[op2(async)]
17891796
#[serde]
1790-
pub async fn op_fs_file_stat_async(
1797+
pub async fn op_fs_file_stat_async<P: FsPermissions + 'static>(
17911798
state: Rc<RefCell<OpState>>,
17921799
#[smi] rid: ResourceId,
17931800
) -> Result<SerializableStat, FsOpsError> {
17941801
let file = FileResource::get_file(&state.borrow(), rid)
17951802
.map_err(FsOpsErrorKind::Resource)?;
1803+
if let Some(path) = file.maybe_path() {
1804+
_ = state.borrow().borrow::<P>().check_open(
1805+
Cow::Borrowed(path),
1806+
OpenAccessKind::Read,
1807+
"Deno.FsFile.prototype.stat()",
1808+
)?;
1809+
}
17961810
let stat = file.stat_async().await?;
17971811
Ok(stat.into())
17981812
}

tests/unit/stat_test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,3 +329,27 @@ Deno.test(
329329
assert(!s.isSocket);
330330
},
331331
);
332+
333+
Deno.test(
334+
{ permissions: { read: false, write: true } },
335+
async function fsFileStatFailPermissions() {
336+
const testDir = Deno.makeTempDirSync();
337+
const filename = testDir + "/file.txt";
338+
using file = await Deno.open(filename, {
339+
read: false,
340+
write: true,
341+
create: true,
342+
});
343+
344+
await assertRejects(
345+
() => file.stat(),
346+
Deno.errors.NotCapable,
347+
"Requires read access to",
348+
);
349+
assertThrows(
350+
() => file.statSync(),
351+
Deno.errors.NotCapable,
352+
"Requires read access to",
353+
);
354+
},
355+
);

0 commit comments

Comments
 (0)