Skip to content

Commit

Permalink
Check archive filenames
Browse files Browse the repository at this point in the history
commit-id:1b4d23da
  • Loading branch information
mkaput committed Oct 3, 2023
1 parent 0098b47 commit 4d7fe8e
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 4 deletions.
12 changes: 11 additions & 1 deletion scarb/src/internal/restricted_names.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Helpers for validating and checking names.
use std::path::Path;

use crate::DEFAULT_TESTS_PATH;
use cairo_lang_filesystem::db::CORELIB_CRATE_NAME;

Expand Down Expand Up @@ -56,7 +58,7 @@ pub fn is_keyword(name: &str) -> bool {
.contains(&name)
}

/// Checks if name is restricted on Windows platforms
/// Checks if name is restricted on Windows platforms.
pub fn is_windows_restricted(name: &str) -> bool {
[
"con", "prn", "aux", "nul", "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8",
Expand All @@ -65,6 +67,14 @@ pub fn is_windows_restricted(name: &str) -> bool {
.contains(&name)
}

/// Checks the entire path for names restricted on Windows platforms.
pub fn is_windows_restricted_path(path: &Path) -> bool {
path.iter()
.filter_map(|c| c.to_str())
.filter_map(|s| s.split('.').next())
.any(is_windows_restricted)
}

/// Checks if name equals `core` or `starknet`
pub fn is_internal(name: &str) -> bool {
[
Expand Down
22 changes: 20 additions & 2 deletions scarb/src/ops/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::BTreeMap;
use std::fs::File;
use std::io::{Seek, SeekFrom, Write};

use anyhow::{ensure, Context, Result};
use anyhow::{bail, ensure, Context, Result};
use camino::Utf8PathBuf;
use indoc::writedoc;

Expand All @@ -13,7 +13,7 @@ use crate::core::publishing::manifest_normalization::prepare_manifest_for_publis
use crate::core::publishing::source::list_source_files;
use crate::core::{Package, PackageId, PackageName, Workspace};
use crate::flock::FileLockGuard;
use crate::internal::fsx;
use crate::internal::{fsx, restricted_names};
use crate::{ops, MANIFEST_FILE_NAME};

const VERSION: u8 = 1;
Expand Down Expand Up @@ -147,6 +147,7 @@ fn list_one_impl(
fn prepare_archive_recipe(pkg: &Package) -> Result<ArchiveRecipe> {
let mut recipe = source_files(pkg)?;

check_filenames(&recipe)?;
check_no_reserved_files(&recipe)?;

// Add normalized manifest file.
Expand Down Expand Up @@ -219,6 +220,23 @@ fn check_no_reserved_files(recipe: &ArchiveRecipe) -> Result<()> {
Ok(())
}

fn check_filenames(recipe: &ArchiveRecipe) -> Result<()> {
for ArchiveFile { path, .. } in recipe {
const BAD_CHARS: &[char] = &['/', '\\', '<', '>', ':', '"', '|', '?', '*'];
for component in path.components() {
let name = component.as_str();
if let Some(c) = BAD_CHARS.iter().find(|&&c| name.contains(c)) {
bail!("cannot package a filename with a special character `{c}`: {path}");
}
}

if restricted_names::is_windows_restricted_path(path.as_std_path()) {
bail!("cannot package file `{path}`, it is a Windows reserved filename");
}
}
Ok(())
}

fn normalize_manifest(pkg: Package) -> Result<Vec<u8>> {
let mut buf = Vec::new();

Expand Down
44 changes: 43 additions & 1 deletion scarb/tests/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,49 @@ fn list_ignore_nested() {
}

// TODO(mkaput): Invalid readme/license path
// TODO(mkaput): Restricted Windows files

#[test]
#[cfg_attr(
target_family = "windows",
ignore = "Windows doesn't allow these characters in filenames."
)]
fn weird_characters_in_filenames() {
let t = TempDir::new().unwrap();
ProjectBuilder::start().src("src/:foo", "").build(&t);

Scarb::quick_snapbox()
.arg("package")
.current_dir(&t)
.assert()
.failure()
.stdout_matches(indoc! {r#"
[..] Packaging [..]
error: cannot package a filename with a special character `:`: src/:foo
"#});
}

#[test]
#[cfg_attr(
target_family = "windows",
ignore = "We do not want to create invalid files on Windows."
)]
fn windows_restricted_filenames() {
let t = TempDir::new().unwrap();
ProjectBuilder::start()
.lib_cairo("mod aux;")
.src("src/aux.cairo", "")
.build(&t);

Scarb::quick_snapbox()
.arg("package")
.current_dir(&t)
.assert()
.failure()
.stdout_matches(indoc! {r#"
[..] Packaging [..]
error: cannot package file `src/aux.cairo`, it is a Windows reserved filename
"#});
}

#[test]
fn package_symlink() {
Expand Down

0 comments on commit 4d7fe8e

Please sign in to comment.