diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2024-09-16 21:39:37 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-16 21:39:37 +0100 |
commit | 62e952559f600e72d7498c9b12f906cb0b1ba150 (patch) | |
tree | 6dbcce6592973358ef4bf6341888b0bbbdb98cc5 /ext/kv/sqlite.rs | |
parent | e0b9c745c15720914f14996bf357d5b375e2dbd8 (diff) |
refactor(permissions): split up Descriptor into Allow, Deny, and Query (#25508)
This makes the permission system more versatile.
Diffstat (limited to 'ext/kv/sqlite.rs')
-rw-r--r-- | ext/kv/sqlite.rs | 74 |
1 files changed, 50 insertions, 24 deletions
diff --git a/ext/kv/sqlite.rs b/ext/kv/sqlite.rs index b31fd1736..8027ff03d 100644 --- a/ext/kv/sqlite.rs +++ b/ext/kv/sqlite.rs @@ -1,5 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use std::borrow::Cow; use std::cell::RefCell; use std::collections::HashMap; use std::env::current_dir; @@ -36,19 +37,37 @@ pub struct SqliteDbHandler<P: SqliteDbHandlerPermissions + 'static> { } pub trait SqliteDbHandlerPermissions { - fn check_read(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError>; - fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError>; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_read( + &mut self, + p: &str, + api_name: &str, + ) -> Result<PathBuf, AnyError>; + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn check_write<'a>( + &mut self, + p: &'a Path, + api_name: &str, + ) -> Result<Cow<'a, Path>, AnyError>; } impl SqliteDbHandlerPermissions for deno_permissions::PermissionsContainer { #[inline(always)] - fn check_read(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> { + fn check_read( + &mut self, + p: &str, + api_name: &str, + ) -> Result<PathBuf, AnyError> { deno_permissions::PermissionsContainer::check_read(self, p, api_name) } #[inline(always)] - fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> { - deno_permissions::PermissionsContainer::check_write(self, p, api_name) + fn check_write<'a>( + &mut self, + p: &'a Path, + api_name: &str, + ) -> Result<Cow<'a, Path>, AnyError> { + deno_permissions::PermissionsContainer::check_write_path(self, p, api_name) } } @@ -74,28 +93,35 @@ impl<P: SqliteDbHandlerPermissions> DatabaseHandler for SqliteDbHandler<P> { state: Rc<RefCell<OpState>>, path: Option<String>, ) -> Result<Self::DB, AnyError> { - // Validate path - if let Some(path) = &path { - if path != ":memory:" { - if path.is_empty() { - return Err(type_error("Filename cannot be empty")); - } - if path.starts_with(':') { - return Err(type_error( - "Filename cannot start with ':' unless prefixed with './'", - )); - } - let path = Path::new(path); - { - let mut state = state.borrow_mut(); - let permissions = state.borrow_mut::<P>(); - permissions.check_read(path, "Deno.openKv")?; - permissions.check_write(path, "Deno.openKv")?; - } + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + fn validate_path<P: SqliteDbHandlerPermissions + 'static>( + state: &RefCell<OpState>, + path: Option<String>, + ) -> Result<Option<String>, AnyError> { + let Some(path) = path else { + return Ok(None); + }; + if path == ":memory:" { + return Ok(Some(path)); + } + if path.is_empty() { + return Err(type_error("Filename cannot be empty")); + } + if path.starts_with(':') { + return Err(type_error( + "Filename cannot start with ':' unless prefixed with './'", + )); + } + { + let mut state = state.borrow_mut(); + let permissions = state.borrow_mut::<P>(); + let path = permissions.check_read(&path, "Deno.openKv")?; + let path = permissions.check_write(&path, "Deno.openKv")?; + Ok(Some(path.to_string_lossy().to_string())) } } - let path = path.clone(); + let path = validate_path::<P>(&state, path)?; let default_storage_dir = self.default_storage_dir.clone(); type ConnGen = Arc<dyn Fn() -> rusqlite::Result<rusqlite::Connection> + Send + Sync>; |