summaryrefslogtreecommitdiff
path: root/ext/kv/sqlite.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-09-16 21:39:37 +0100
committerGitHub <noreply@github.com>2024-09-16 21:39:37 +0100
commit62e952559f600e72d7498c9b12f906cb0b1ba150 (patch)
tree6dbcce6592973358ef4bf6341888b0bbbdb98cc5 /ext/kv/sqlite.rs
parente0b9c745c15720914f14996bf357d5b375e2dbd8 (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.rs74
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>;