From e98e7731863ec049c4dc3cbf65eb87df1c949288 Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Thu, 3 Aug 2023 14:32:14 -0700 Subject: [PATCH 01/13] doc: fix typo (#1287) --- packages/html/src/events/mounted.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/html/src/events/mounted.rs b/packages/html/src/events/mounted.rs index 293b51b9e..bc561bf1b 100644 --- a/packages/html/src/events/mounted.rs +++ b/packages/html/src/events/mounted.rs @@ -1,4 +1,4 @@ -//! Handles quering data from the renderer +//! Handles querying data from the renderer use euclid::Rect; From ab1d64bc4a55fc6a555ba09cf6c2a150f19c3ca4 Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Fri, 4 Aug 2023 10:49:31 -0700 Subject: [PATCH 02/13] docs(cli): fix typo (#1294) "tripple" should be "triple". --- packages/cli/src/cli/create.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/cli/create.rs b/packages/cli/src/cli/create.rs index b2323d0a2..92b0334f5 100644 --- a/packages/cli/src/cli/create.rs +++ b/packages/cli/src/cli/create.rs @@ -46,15 +46,15 @@ impl Create { toml.as_table_mut().fmt(); let as_string = toml.to_string(); - let new_string = remove_tripple_newlines(&as_string); + let new_string = remove_triple_newlines(&as_string); let mut file = std::fs::File::create(toml_path)?; file.write_all(new_string.as_bytes())?; } - // remove any tripple newlines from the readme + // remove any triple newlines from the readme let readme_path = path.join("README.md"); let readme = std::fs::read_to_string(&readme_path)?; - let new_readme = remove_tripple_newlines(&readme); + let new_readme = remove_triple_newlines(&readme); let mut file = std::fs::File::create(readme_path)?; file.write_all(new_readme.as_bytes())?; @@ -64,7 +64,7 @@ impl Create { } } -fn remove_tripple_newlines(string: &str) -> String { +fn remove_triple_newlines(string: &str) -> String { let mut new_string = String::new(); for char in string.chars() { if char == '\n' && new_string.ends_with("\n\n") { From 50230b6f715ec354a346c9e2adbe6267584ac97d Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Fri, 4 Aug 2023 10:51:17 -0700 Subject: [PATCH 03/13] build(web): fix `default-features` warning (#1296) `cargo build` would print this warning: ``` warning: dioxus/packages/web/Cargo.toml: `default-features` is ignored for dioxus-html, since `default-features` was not specified for `workspace.dependencies.dioxus-html`, this could become a hard error in the future ``` Since it's being ignored anyway and that doesn't seem to be causing problems, I figured I'd remove it and get rid of the warning. --- packages/web/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/Cargo.toml b/packages/web/Cargo.toml index baa3c6fe5..8de282869 100644 --- a/packages/web/Cargo.toml +++ b/packages/web/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["dom", "ui", "gui", "react", "wasm"] [dependencies] dioxus-core = { workspace = true, features = ["serialize"] } -dioxus-html = { workspace = true, features = ["wasm-bind"], default-features = false } +dioxus-html = { workspace = true, features = ["wasm-bind"] } dioxus-interpreter-js = { workspace = true, features = [ "sledgehammer", "minimal_bindings", From 6d154b5072ed0b694aea8540914c9b68dc06371e Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Fri, 4 Aug 2023 11:44:56 -0700 Subject: [PATCH 04/13] Minor Proxy Improvements (#1289) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(serve): provide a clear error with pathless proxy URLs Without this, `dx serve` panics with this message: ``` Paths must start with a `/`. Use "/" for root routes ``` That's not very clear. Instead, we can detect this situation and provide a better error message: ``` Error: 🚫 Serving project failed: Failed to establish proxy: Proxy backend URL must have a non-empty path, e.g. http://localhost:8080/api instead of http://localhost:8080 ``` * docs(config): correct format for `web.proxy` --- packages/cli/docs/src/configure.md | 2 +- packages/cli/src/error.rs | 3 +++ packages/cli/src/server/web/proxy.rs | 31 ++++++++++++++++++++++++++-- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/cli/docs/src/configure.md b/packages/cli/docs/src/configure.md index 8da66d9ec..9d0cb0a9b 100644 --- a/packages/cli/docs/src/configure.md +++ b/packages/cli/docs/src/configure.md @@ -144,7 +144,7 @@ Configeration related to static resources your application uses in development: Configeration related to any proxies your application requires durring development. Proxies will forward requests to a new service ``` -[web.proxy] +[[web.proxy]] # configuration ``` diff --git a/packages/cli/src/error.rs b/packages/cli/src/error.rs index 7832ab326..84b9d4b71 100644 --- a/packages/cli/src/error.rs +++ b/packages/cli/src/error.rs @@ -35,6 +35,9 @@ pub enum Error { #[error("Invalid proxy URL: {0}")] InvalidProxy(#[from] hyper::http::uri::InvalidUri), + #[error("Failed to establish proxy: {0}")] + ProxySetupError(String), + #[error("Error proxying request: {0}")] ProxyRequestError(hyper::Error), diff --git a/packages/cli/src/server/web/proxy.rs b/packages/cli/src/server/web/proxy.rs index 8de65f4db..e35635b6b 100644 --- a/packages/cli/src/server/web/proxy.rs +++ b/packages/cli/src/server/web/proxy.rs @@ -48,6 +48,16 @@ impl ProxyClient { pub fn add_proxy(mut router: Router, proxy: &WebProxyConfig) -> Result { let url: Uri = proxy.backend.parse()?; let path = url.path().to_string(); + let trimmed_path = path.trim_end_matches('/'); + + if trimmed_path.is_empty() { + return Err(crate::Error::ProxySetupError(format!( + "Proxy backend URL must have a non-empty path, e.g. {}/api instead of {}", + proxy.backend.trim_end_matches('/'), + proxy.backend + ))); + } + let client = ProxyClient::new(url); // We also match everything after the path using a wildcard matcher. @@ -56,7 +66,7 @@ pub fn add_proxy(mut router: Router, proxy: &WebProxyConfig) -> Result { router = router.route( // Always remove trailing /'s so that the exact route // matches. - path.trim_end_matches('/'), + trimmed_path, any(move |req| async move { client .send(req) @@ -68,7 +78,7 @@ pub fn add_proxy(mut router: Router, proxy: &WebProxyConfig) -> Result { // Wildcard match anything else _after_ the backend URL's path. // Note that we know `path` ends with a trailing `/` in this branch, // so `wildcard` will look like `http://localhost/api/*proxywildcard`. - let wildcard = format!("{}/*proxywildcard", path.trim_end_matches('/')); + let wildcard = format!("{}/*proxywildcard", trimmed_path); router = router.route( &wildcard, any(move |req| async move { @@ -168,4 +178,21 @@ mod test { async fn add_proxy_trailing_slash() { test_proxy_requests("/api/".to_string()).await; } + + #[test] + fn add_proxy_empty_path() { + let config = WebProxyConfig { + backend: "http://localhost:8000".to_string(), + }; + let router = super::add_proxy(Router::new(), &config); + match router.unwrap_err() { + crate::Error::ProxySetupError(e) => { + assert_eq!( + e, + "Proxy backend URL must have a non-empty path, e.g. http://localhost:8000/api instead of http://localhost:8000" + ); + } + e => panic!("Unexpected error type: {}", e), + } + } } From 8f93ff37473358f5674f2cacf1f485401716269f Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Fri, 4 Aug 2023 13:13:02 -0700 Subject: [PATCH 05/13] docs(hooks): fix typos (#1299) I'm not totally sure how the sentence was supposed to read, but removing "state" from "It state" seemed to work. Also, "it's" is "it is" and not possessive, so I fixed that. --- packages/hooks/src/computed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/hooks/src/computed.rs b/packages/hooks/src/computed.rs index 248eb4f83..94011d37d 100644 --- a/packages/hooks/src/computed.rs +++ b/packages/hooks/src/computed.rs @@ -10,7 +10,7 @@ use std::{ /// Create a new tracked state. /// Tracked state is state that can drive Selector state /// -/// It state will efficiently update any Selector state that is reading from it, but it is not readable on it's own. +/// It will efficiently update any Selector state that is reading from it, but it is not readable on its own. /// /// ```rust /// use dioxus::prelude::*; From 63bb5cc7582b646da485be3a0a9c9321181e32e4 Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Fri, 4 Aug 2023 13:52:49 -0700 Subject: [PATCH 06/13] chore(cli): remove unused function I believe that technically this function is part of the public API via `dioxus_cli::cli::cfg::parse_public_url`. However, I don't see any evidence that this function is actually used inside or outside this crate. The last use within the crate was removed in January 2022 (9bb10c65a3cbabef127f6af5c0d1eadab1d01531). --- packages/cli/src/cli/cfg.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/cli/src/cli/cfg.rs b/packages/cli/src/cli/cfg.rs index 687780228..2a441a1c8 100644 --- a/packages/cli/src/cli/cfg.rs +++ b/packages/cli/src/cli/cfg.rs @@ -101,13 +101,6 @@ pub enum Platform { Desktop, } -/// Ensure the given value for `--public-url` is formatted correctly. -pub fn parse_public_url(val: &str) -> String { - let prefix = if !val.starts_with('/') { "/" } else { "" }; - let suffix = if !val.ends_with('/') { "/" } else { "" }; - format!("{}{}{}", prefix, val, suffix) -} - /// Config options for the bundling system. #[derive(Clone, Debug, Default, Deserialize, Parser)] pub struct ConfigOptsBundle { From 5c629478358b5ca7e056fac3a733834ee3b4e00e Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Fri, 4 Aug 2023 15:00:19 -0700 Subject: [PATCH 07/13] refactor(cli): move `check` module alongside others (#1304) There was no reason for `check` to be defined as `check/mod.rs` when all the others were at the top level e.g. `serve.rs`. --- packages/cli/src/cli/{check/mod.rs => check.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/cli/src/cli/{check/mod.rs => check.rs} (100%) diff --git a/packages/cli/src/cli/check/mod.rs b/packages/cli/src/cli/check.rs similarity index 100% rename from packages/cli/src/cli/check/mod.rs rename to packages/cli/src/cli/check.rs From a77ff1c820c7878eec6ba160ec2ebaf40f5f0cdc Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Fri, 4 Aug 2023 15:00:41 -0700 Subject: [PATCH 08/13] docs(cli): update subcommand comments (#1303) A bunch of these were copy-pasted from `build`. This commit updates them to be the same as what their `dx help` string is. --- packages/cli/docs/src/cmd/README.md | 1 + packages/cli/src/cli/autoformat.rs | 2 +- packages/cli/src/cli/bundle.rs | 2 +- packages/cli/src/cli/config.rs | 2 +- packages/cli/src/cli/mod.rs | 1 + packages/cli/src/cli/plugin.rs | 2 +- packages/cli/src/cli/translate.rs | 2 +- packages/cli/src/cli/version.rs | 2 +- 8 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/cli/docs/src/cmd/README.md b/packages/cli/docs/src/cmd/README.md index 93f6f5573..735794635 100644 --- a/packages/cli/docs/src/cmd/README.md +++ b/packages/cli/docs/src/cmd/README.md @@ -15,6 +15,7 @@ Commands: serve Build, watch & serve the Rust WASM app and all of its assets create Init a new project for Dioxus clean Clean output artifacts + bundle Bundle the Rust desktop app and all of its assets version Print the version of this extension fmt Format some rsx check Check the Rust files in the project for issues diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index a0c0a8066..f436ab4c4 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -6,7 +6,7 @@ use super::*; // For reference, the rustfmt main.rs file // https://github.com/rust-lang/rustfmt/blob/master/src/bin/main.rs -/// Build the Rust WASM app and all of its assets. +/// Format some rsx #[derive(Clone, Debug, Parser)] pub struct Autoformat { /// Run in 'check' mode. Exits with 0 if input is formatted correctly. Exits diff --git a/packages/cli/src/cli/bundle.rs b/packages/cli/src/cli/bundle.rs index 76c494056..0d4fb23da 100644 --- a/packages/cli/src/cli/bundle.rs +++ b/packages/cli/src/cli/bundle.rs @@ -6,7 +6,7 @@ use tauri_bundler::{BundleSettings, PackageSettings, SettingsBuilder}; use super::*; use crate::{build_desktop, cfg::ConfigOptsBundle}; -/// Build the Rust WASM app and all of its assets. +/// Bundle the Rust desktop app and all of its assets #[derive(Clone, Debug, Parser)] #[clap(name = "bundle")] pub struct Bundle { diff --git a/packages/cli/src/cli/config.rs b/packages/cli/src/cli/config.rs index cde29ef6a..45fcc2f23 100644 --- a/packages/cli/src/cli/config.rs +++ b/packages/cli/src/cli/config.rs @@ -1,6 +1,6 @@ use super::*; -/// Build the Rust WASM app and all of its assets. +/// Dioxus config file controls #[derive(Clone, Debug, Deserialize, Subcommand)] #[clap(name = "config")] pub enum Config { diff --git a/packages/cli/src/cli/mod.rs b/packages/cli/src/cli/mod.rs index 37d64d2f3..9b3be33bc 100644 --- a/packages/cli/src/cli/mod.rs +++ b/packages/cli/src/cli/mod.rs @@ -72,6 +72,7 @@ pub enum Commands { #[clap(name = "fmt")] Autoformat(autoformat::Autoformat), + /// Check the Rust files in the project for issues. #[clap(name = "check")] Check(check::Check), diff --git a/packages/cli/src/cli/plugin.rs b/packages/cli/src/cli/plugin.rs index 9f514edec..43375f700 100644 --- a/packages/cli/src/cli/plugin.rs +++ b/packages/cli/src/cli/plugin.rs @@ -2,7 +2,7 @@ use super::*; -/// Build the Rust WASM app and all of its assets. +/// Manage plugins for dioxus cli #[derive(Clone, Debug, Deserialize, Subcommand)] #[clap(name = "plugin")] pub enum Plugin { diff --git a/packages/cli/src/cli/translate.rs b/packages/cli/src/cli/translate.rs index a922d428d..d3901e651 100644 --- a/packages/cli/src/cli/translate.rs +++ b/packages/cli/src/cli/translate.rs @@ -4,7 +4,7 @@ use dioxus_rsx::{BodyNode, CallBody}; use super::*; -/// Build the Rust WASM app and all of its assets. +/// Translate some source file into Dioxus code #[derive(Clone, Debug, Parser)] #[clap(name = "translate")] pub struct Translate { diff --git a/packages/cli/src/cli/version.rs b/packages/cli/src/cli/version.rs index 3c77ba419..c015a73a2 100644 --- a/packages/cli/src/cli/version.rs +++ b/packages/cli/src/cli/version.rs @@ -1,6 +1,6 @@ use super::*; -/// Build the Rust WASM app and all of its assets. +/// Print the version of this extension #[derive(Clone, Debug, Parser)] #[clap(name = "version")] pub struct Version {} From 7a7397bbb487e66da1b38939575c1e354b8d89f8 Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Fri, 4 Aug 2023 15:01:04 -0700 Subject: [PATCH 09/13] chore(cli): remove unused module (#1302) It seems this was replaced by the `plugin.rs` module in 6cce4b9f4da055fb75fc555b1fae43be58ba3463. --- packages/cli/src/cli/tool.rs | 64 ------------------------------------ 1 file changed, 64 deletions(-) delete mode 100644 packages/cli/src/cli/tool.rs diff --git a/packages/cli/src/cli/tool.rs b/packages/cli/src/cli/tool.rs deleted file mode 100644 index 2edccf7ea..000000000 --- a/packages/cli/src/cli/tool.rs +++ /dev/null @@ -1,64 +0,0 @@ -use crate::tools; - -use super::*; - -/// Build the Rust WASM app and all of its assets. -#[derive(Clone, Debug, Deserialize, Subcommand)] -#[clap(name = "tool")] -pub enum Tool { - /// Return all dioxus-cli support tools. - List {}, - /// Get default app install path. - AppPath {}, - /// Install a new tool. - Add { name: String }, -} - -impl Tool { - pub async fn tool(self) -> Result<()> { - match self { - Tool::List {} => { - for item in tools::tool_list() { - if tools::Tool::from_str(item).unwrap().is_installed() { - println!("- {item} [installed]"); - } else { - println!("- {item}"); - } - } - } - Tool::AppPath {} => { - if let Some(v) = tools::tools_path().to_str() { - println!("{}", v); - } else { - return custom_error!("Tools path get failed."); - } - } - Tool::Add { name } => { - let tool_list = tools::tool_list(); - - if !tool_list.contains(&name.as_str()) { - return custom_error!("Tool {name} not found."); - } - let target_tool = tools::Tool::from_str(&name).unwrap(); - - if target_tool.is_installed() { - log::warn!("Tool {name} is installed."); - return Ok(()); - } - - log::info!("Start to download tool package..."); - if let Err(e) = target_tool.download_package().await { - return custom_error!("Tool download failed: {e}"); - } - - log::info!("Start to install tool package..."); - if let Err(e) = target_tool.install_package().await { - return custom_error!("Tool install failed: {e}"); - } - - log::info!("Tool {name} installed successfully!"); - } - } - Ok(()) - } -} From 14e7c50478942d00f76379671089159dc9382fe6 Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Fri, 4 Aug 2023 20:02:07 -0700 Subject: [PATCH 10/13] fix(cli): prevent "zip slip" vulnerability in tool extract Using the name directly from a zip archive's entry and writing to it is a potential security vulnerability. More information about the vulnerability can be found here: https://security.snyk.io/research/zip-slip-vulnerability and here https://docs.rs/zip/latest/zip/read/struct.ZipFile.html#warnings. It looks like the previous version maybe tried to remove `\` characters to prevent this, but only in directory paths? --- packages/cli/src/tools.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/packages/cli/src/tools.rs b/packages/cli/src/tools.rs index 98d4f9dbe..b1fcdc72d 100644 --- a/packages/cli/src/tools.rs +++ b/packages/cli/src/tools.rs @@ -328,20 +328,26 @@ pub fn extract_zip(file: &Path, target: &Path) -> anyhow::Result<()> { } for i in 0..zip.len() { - let mut file = zip.by_index(i)?; - if file.is_dir() { + let mut zip_entry = zip.by_index(i)?; + let Some(enclosed_name) = zip_entry.enclosed_name() else { + return Err(anyhow::anyhow!( + "Refusing to unpack zip entry with potentially dangerous path: zip={} entry={:?}", + file.display(), + zip_entry.name() + )); + }; + let output_path = target.join(enclosed_name); + if zip_entry.is_dir() { // dir - let target = target.join(Path::new(&file.name().replace('\\', ""))); - std::fs::create_dir_all(target)?; + std::fs::create_dir_all(output_path)?; } else { // file - let file_path = target.join(Path::new(file.name())); - let mut target_file = if !file_path.exists() { - std::fs::File::create(file_path)? + let mut target_file = if !output_path.exists() { + std::fs::File::create(output_path)? } else { - std::fs::File::open(file_path)? + std::fs::File::open(output_path)? }; - let _num = std::io::copy(&mut file, &mut target_file)?; + let _num = std::io::copy(&mut zip_entry, &mut target_file)?; } } From 03e02591ec99d14810334a07c5f5825e5c576507 Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Fri, 4 Aug 2023 21:28:09 -0700 Subject: [PATCH 11/13] fix(cli): allows extracting files without separate directory entries Some zip files do not list directories separately from files. For example, a zip might contain `dir/file.txt` without a corresponding entry for just `dir/`. This should be okay, so we just create the leading paths for the files we extract as necessary. Also adds tests for the expected and dangerous path cases of `extract_zip`. --- packages/cli/Cargo.toml | 3 ++ packages/cli/src/tools.rs | 55 +++++++++++++++++++++- packages/cli/tests/fixtures/dangerous.zip | Bin 0 -> 127 bytes packages/cli/tests/fixtures/test.zip | Bin 0 -> 315 bytes 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 packages/cli/tests/fixtures/dangerous.zip create mode 100644 packages/cli/tests/fixtures/test.zip diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index c5168a4db..892399a9d 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -97,3 +97,6 @@ plugin = ["mlua"] [[bin]] path = "src/main.rs" name = "dx" + +[dev-dependencies] +tempfile = "3.3" diff --git a/packages/cli/src/tools.rs b/packages/cli/src/tools.rs index b1fcdc72d..4045b236e 100644 --- a/packages/cli/src/tools.rs +++ b/packages/cli/src/tools.rs @@ -329,6 +329,9 @@ pub fn extract_zip(file: &Path, target: &Path) -> anyhow::Result<()> { for i in 0..zip.len() { let mut zip_entry = zip.by_index(i)?; + + // check for dangerous paths + // see https://docs.rs/zip/latest/zip/read/struct.ZipFile.html#warnings let Some(enclosed_name) = zip_entry.enclosed_name() else { return Err(anyhow::anyhow!( "Refusing to unpack zip entry with potentially dangerous path: zip={} entry={:?}", @@ -336,12 +339,17 @@ pub fn extract_zip(file: &Path, target: &Path) -> anyhow::Result<()> { zip_entry.name() )); }; + let output_path = target.join(enclosed_name); if zip_entry.is_dir() { - // dir std::fs::create_dir_all(output_path)?; } else { - // file + // create parent dirs if needed + if let Some(parent) = output_path.parent() { + std::fs::create_dir_all(parent)?; + } + + // extract file let mut target_file = if !output_path.exists() { std::fs::File::create(output_path)? } else { @@ -353,3 +361,46 @@ pub fn extract_zip(file: &Path, target: &Path) -> anyhow::Result<()> { Ok(()) } + +#[cfg(test)] +mod test { + use super::*; + use std::path::PathBuf; + use tempfile::tempdir; + + #[test] + fn test_extract_zip() -> anyhow::Result<()> { + let path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()) + .join("tests/fixtures/test.zip"); + let temp_dir = tempdir()?; + let temp_path = temp_dir.path(); + + extract_zip(path.as_path(), temp_path)?; + + let expected_files = vec!["file1.txt", "file2.txt", "dir/file3.txt"]; + for file in expected_files { + let path = temp_path.join(file); + assert!(path.exists(), "File not found: {:?}", path); + } + + Ok(()) + } + + #[test] + fn test_extract_zip_dangerous_path() -> anyhow::Result<()> { + let path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()) + .join("tests/fixtures/dangerous.zip"); + let temp_dir = tempdir()?; + let temp_path = temp_dir.path(); + + let result = extract_zip(path.as_path(), temp_path); + + let err = result.unwrap_err(); + assert!(err + .to_string() + .contains("Refusing to unpack zip entry with potentially dangerous path: zip=")); + assert!(err.to_string().contains("entry=\"/etc/passwd\"")); + + Ok(()) + } +} diff --git a/packages/cli/tests/fixtures/dangerous.zip b/packages/cli/tests/fixtures/dangerous.zip new file mode 100644 index 0000000000000000000000000000000000000000..09ff13d6357a4fc55c07488c5c5ed11c7d7bbc16 GIT binary patch literal 127 zcmWIWW@Zs#0D-cVEa43KoA$8-*&xgf#QLcv$@&F}#l__*DT#UMsYQwb-i%Bl%(!&` cHGx3`BZxxMAK=Z(1`=WfLQ5cR0OBwJ0N|Sx-~a#s literal 0 HcmV?d00001 diff --git a/packages/cli/tests/fixtures/test.zip b/packages/cli/tests/fixtures/test.zip new file mode 100644 index 0000000000000000000000000000000000000000..bb90b81addaf5ca48b42ee9f7cbdfae67fddbfcc GIT binary patch literal 315 zcmWIWW@Zs#0DUj5El|ol%1X5>& zP?ri+H@ojrE=(OS(7cq)B7KmV#vrxE0p5&EBFwmL2WkL=29Oa5w;*f7<`{@328ISk k4X8G-(~z}ca~nci0Fa5|(g1H(Hjp$k5UvE$H6RWH07iW_^Z)<= literal 0 HcmV?d00001 From 24df4e15d9943e024ff4180445c28f61d85285c2 Mon Sep 17 00:00:00 2001 From: Dylan Blokhuis Date: Sun, 6 Aug 2023 18:42:36 +0200 Subject: [PATCH 12/13] spelling (#1308) --- packages/hot-reload/src/file_watcher.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/hot-reload/src/file_watcher.rs b/packages/hot-reload/src/file_watcher.rs index 9bbfcb512..48d97dfa7 100644 --- a/packages/hot-reload/src/file_watcher.rs +++ b/packages/hot-reload/src/file_watcher.rs @@ -248,7 +248,7 @@ pub fn init(cfg: Config) { return shutdown; } else if log { println!( - "Rebuild needed... shutting down hot reloading.\nManually rebuild the application to view futher changes." + "Rebuild needed... shutting down hot reloading.\nManually rebuild the application to view further changes." ); } true From a025617db34ccb482710758b89f13e800dfe849a Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Mon, 7 Aug 2023 09:08:51 -0700 Subject: [PATCH 13/13] refactor(cli): use more semantic `Instant::elapsed` (#1307) Plus, one of these was incorrectly subtracting the end time from the start time. --- packages/cli/src/builder.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/builder.rs b/packages/cli/src/builder.rs index b25576120..3fa8e7818 100644 --- a/packages/cli/src/builder.rs +++ b/packages/cli/src/builder.rs @@ -236,10 +236,9 @@ pub fn build(config: &CrateConfig, quiet: bool) -> Result { } } - let t_end = std::time::Instant::now(); Ok(BuildResult { warnings: warning_messages, - elapsed_time: (t_end - t_start).as_millis(), + elapsed_time: t_start.elapsed().as_millis(), }) } @@ -360,7 +359,7 @@ pub fn build_desktop(config: &CrateConfig, _is_serve: bool) -> Result