diff --git a/Cargo.lock b/Cargo.lock index dda89e9e5f..955dc3885e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -239,6 +239,12 @@ version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +[[package]] +name = "bytecount" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" + [[package]] name = "byteorder" version = "1.4.3" @@ -2167,6 +2173,7 @@ dependencies = [ "backoff", "backtrace", "brotli2", + "bytecount", "chardet", "chrono", "clap", diff --git a/Cargo.toml b/Cargo.toml index d114f31ebe..8f4550cfd7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ anyhow = { version = "1.0.66", features = ["backtrace"] } backoff = "0.4.0" backtrace = "0.3.66" brotli2 = "0.3.2" +bytecount = "0.6.3" chardet = "0.2.4" chrono = { version = "0.4.22", features = ["serde"] } clap = { version = "3.2.22", default-features = false, features = [ diff --git a/src/commands/files/upload.rs b/src/commands/files/upload.rs index 30cf776f47..f5a3533472 100644 --- a/src/commands/files/upload.rs +++ b/src/commands/files/upload.rs @@ -10,6 +10,7 @@ use symbolic::debuginfo::sourcebundle::SourceFileType; use crate::api::{Api, ProgressBarMode}; use crate::config::Config; +use crate::utils::args::validate_distribution; use crate::utils::file_search::ReleaseFileSearch; use crate::utils::file_upload::{ReleaseFile, ReleaseFileUpload, UploadContext}; use crate::utils::fs::{decompress_gzip_content, is_gzip_compressed, path_as_url}; @@ -35,6 +36,7 @@ pub fn make_command(command: Command) -> Command { .long("dist") .short('d') .value_name("DISTRIBUTION") + .validator(validate_distribution) .help("Optional distribution identifier for this file."), ) .arg( diff --git a/src/commands/react_native/appcenter.rs b/src/commands/react_native/appcenter.rs index 5600ca381f..6a8d8a501e 100644 --- a/src/commands/react_native/appcenter.rs +++ b/src/commands/react_native/appcenter.rs @@ -11,7 +11,7 @@ use log::info; use crate::api::{Api, NewRelease}; use crate::config::Config; use crate::utils::appcenter::{get_appcenter_package, get_react_native_appcenter_release}; -use crate::utils::args::ArgExt; +use crate::utils::args::{validate_distribution, ArgExt}; use crate::utils::file_search::ReleaseFileSearch; use crate::utils::file_upload::UploadContext; use crate::utils::sourcemaps::SourceMapProcessor; @@ -50,6 +50,7 @@ pub fn make_command(command: Command) -> Command { .long("dist") .value_name("DISTRIBUTION") .multiple_occurrences(true) + .validator(validate_distribution) .help("The names of the distributions to publish. Can be supplied multiple times."), ) .arg( diff --git a/src/commands/react_native/gradle.rs b/src/commands/react_native/gradle.rs index 09c1d6c05e..d7a7b4caee 100644 --- a/src/commands/react_native/gradle.rs +++ b/src/commands/react_native/gradle.rs @@ -8,7 +8,7 @@ use sourcemap::ram_bundle::RamBundle; use crate::api::{Api, NewRelease}; use crate::config::Config; -use crate::utils::args::ArgExt; +use crate::utils::args::{validate_distribution, ArgExt}; use crate::utils::file_search::ReleaseFileSearch; use crate::utils::file_upload::UploadContext; use crate::utils::sourcemaps::SourceMapProcessor; @@ -45,6 +45,7 @@ pub fn make_command(command: Command) -> Command { .value_name("DISTRIBUTION") .required(true) .multiple_occurrences(true) + .validator(validate_distribution) .help("The names of the distributions to publish. Can be supplied multiple times."), ) .arg( diff --git a/src/commands/react_native/xcode.rs b/src/commands/react_native/xcode.rs index ac6a174f11..91d71e69c5 100644 --- a/src/commands/react_native/xcode.rs +++ b/src/commands/react_native/xcode.rs @@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize}; use crate::api::{Api, NewRelease}; use crate::config::Config; -use crate::utils::args::ArgExt; +use crate::utils::args::{validate_distribution, ArgExt}; use crate::utils::file_search::ReleaseFileSearch; use crate::utils::file_upload::UploadContext; use crate::utils::fs::TempFile; @@ -69,6 +69,7 @@ pub fn make_command(command: Command) -> Command { .long("dist") .value_name("DISTRIBUTION") .multiple_occurrences(true) + .validator(validate_distribution) .help("The names of the distributions to publish. Can be supplied multiple times."), ) .arg( diff --git a/src/commands/send_event.rs b/src/commands/send_event.rs index b989dfb6c7..fb9228a4e2 100644 --- a/src/commands/send_event.rs +++ b/src/commands/send_event.rs @@ -15,7 +15,7 @@ use serde_json::Value; use username::get_user_name; use crate::config::Config; -use crate::utils::args::{get_timestamp, validate_timestamp}; +use crate::utils::args::{get_timestamp, validate_distribution, validate_timestamp}; use crate::utils::event::{attach_logfile, get_sdk_info, with_sentry_client}; use crate::utils::releases::detect_release_name; @@ -58,6 +58,7 @@ pub fn make_command(command: Command) -> Command { .value_name("DISTRIBUTION") .long("dist") .short('d') + .validator(validate_distribution) .help("Set the distribution."), ) .arg( diff --git a/src/commands/sourcemaps/upload.rs b/src/commands/sourcemaps/upload.rs index c789946698..52f779fc65 100644 --- a/src/commands/sourcemaps/upload.rs +++ b/src/commands/sourcemaps/upload.rs @@ -9,6 +9,7 @@ use sha1_smol::Digest; use crate::api::{Api, NewRelease}; use crate::config::Config; +use crate::utils::args::validate_distribution; use crate::utils::file_search::ReleaseFileSearch; use crate::utils::file_upload::UploadContext; use crate::utils::fs::path_as_url; @@ -44,6 +45,7 @@ pub fn make_command(command: Command) -> Command { .long("dist") .short('d') .value_name("DISTRIBUTION") + .validator(validate_distribution) .help("Optional distribution identifier for the sourcemaps."), ) .arg( diff --git a/src/utils/args.rs b/src/utils/args.rs index ccee776de5..4d78787210 100644 --- a/src/utils/args.rs +++ b/src/utils/args.rs @@ -50,6 +50,22 @@ fn validate_release(v: &str) -> Result<(), String> { } } +pub fn validate_distribution(v: &str) -> Result<(), String> { + if v.trim() != v { + Err( + "Invalid distribution name. Distribution must not contain leading or trailing spaces." + .to_string(), + ) + } else if bytecount::num_chars(v.as_bytes()) > 64 { + Err( + "Invalid distribution name. Distribution name must not be longer than 64 characters." + .to_string(), + ) + } else { + Ok(()) + } +} + pub fn validate_int(v: &str) -> Result<(), String> { if v.parse::().is_ok() { Ok(()) diff --git a/tests/integration/_cases/send_event/send_event-raw-fail.trycmd b/tests/integration/_cases/send_event/send_event-raw-fail.trycmd new file mode 100644 index 0000000000..34c006fda8 --- /dev/null +++ b/tests/integration/_cases/send_event/send_event-raw-fail.trycmd @@ -0,0 +1,21 @@ +``` +$ sentry-cli send-event --log-level=debug +> --level debug +> --timestamp 1649335000929 +> --release my-release +> --dist 11111111111111111111111111111111111111111111111111111111111111111 +> --env production +> --message hello +> --platform prod +> --tag "hello:there" +> --extra "hello:there" +> --user "id:42" +> --fingerprint custom-fingerprint +> --no-environ +? 2 +error: Invalid value "11111111111111111111111111111111111111111111111111111111111111111" for '--dist ': Invalid distribution name. Distribution name must not be longer than 64 characters. + +For more information try --help + +``` + diff --git a/tests/integration/send_event.rs b/tests/integration/send_event.rs index cbaa6747b9..035d44f232 100644 --- a/tests/integration/send_event.rs +++ b/tests/integration/send_event.rs @@ -18,3 +18,8 @@ fn command_send_event_raw() { fn command_send_event_file() { register_test("send_event/send_event-file.trycmd"); } + +#[test] +fn command_send_event_raw_fail() { + register_test("send_event/send_event-raw-fail.trycmd"); +}