Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/uu/env/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ path = "src/env.rs"
[dependencies]
clap = { workspace = true }
rust-ini = { workspace = true }
thiserror = { workspace = true }
uucore = { workspace = true, features = ["signals"] }

[target.'cfg(unix)'.dependencies]
Expand Down
129 changes: 118 additions & 11 deletions src/uu/env/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
// spell-checker:ignore (ToDO) chdir execvp progname subcommand subcommands unsets setenv putenv spawnp SIGSEGV SIGBUS sigaction

pub mod native_int_str;
pub mod parse_error;
pub mod split_iterator;
pub mod string_expander;
pub mod string_parser;
Expand Down Expand Up @@ -40,6 +39,42 @@ use uucore::line_ending::LineEnding;
use uucore::signals::signal_by_name_or_value;
use uucore::{format_usage, help_about, help_section, help_usage, show_warning};

use thiserror::Error;

#[derive(Debug, Error, PartialEq)]
pub enum EnvError {
#[error("no terminating quote in -S string")]
EnvMissingClosingQuote(usize, char),
#[error("invalid backslash at end of string in -S")]
EnvInvalidBackslashAtEndOfStringInMinusS(usize, String),
#[error("'\\c' must not appear in double-quoted -S string")]
EnvBackslashCNotAllowedInDoubleQuotes(usize),
#[error("invalid sequence '\\{}' in -S",.1)]
EnvInvalidSequenceBackslashXInMinusS(usize, char),
#[error("Missing closing brace")]
EnvParsingOfVariableMissingClosingBrace(usize),
#[error("Missing variable name")]
EnvParsingOfMissingVariable(usize),
#[error("Missing closing brace after default value at {}",.0)]
EnvParsingOfVariableMissingClosingBraceAfterValue(usize),
#[error("Unexpected character: '{}', expected variable name must not start with 0..9",.1)]
EnvParsingOfVariableUnexpectedNumber(usize, String),
#[error("Unexpected character: '{}', expected a closing brace ('}}') or colon (':')",.1)]
EnvParsingOfVariableExceptedBraceOrColon(usize, String),
#[error("")]
EnvReachedEnd,
#[error("")]
EnvContinueWithDelimiter,
#[error("{}{:?}",.0,.1)]
EnvInternalError(usize, string_parser::Error),
}

impl From<string_parser::Error> for EnvError {
fn from(value: string_parser::Error) -> Self {
EnvError::EnvInternalError(value.peek_position, value)
}
}

const ABOUT: &str = help_about!("env.md");
const USAGE: &str = help_usage!("env.md");
const AFTER_HELP: &str = help_section!("after help", "env.md");
Expand Down Expand Up @@ -273,20 +308,28 @@ pub fn uu_app() -> Command {

pub fn parse_args_from_str(text: &NativeIntStr) -> UResult<Vec<NativeIntString>> {
split_iterator::split(text).map_err(|e| match e {
parse_error::ParseError::BackslashCNotAllowedInDoubleQuotes { pos: _ } => {
USimpleError::new(125, "'\\c' must not appear in double-quoted -S string")
EnvError::EnvBackslashCNotAllowedInDoubleQuotes(_) => USimpleError::new(125, e.to_string()),
EnvError::EnvInvalidBackslashAtEndOfStringInMinusS(_, _) => {
USimpleError::new(125, e.to_string())
}
EnvError::EnvInvalidSequenceBackslashXInMinusS(_, _) => {
USimpleError::new(125, e.to_string())
}
EnvError::EnvMissingClosingQuote(_, _) => USimpleError::new(125, e.to_string()),
EnvError::EnvParsingOfVariableMissingClosingBrace(pos) => {
USimpleError::new(125, format!("variable name issue (at {pos}): {}", e))
}
parse_error::ParseError::InvalidBackslashAtEndOfStringInMinusS { pos: _, quoting: _ } => {
USimpleError::new(125, "invalid backslash at end of string in -S")
EnvError::EnvParsingOfMissingVariable(pos) => {
USimpleError::new(125, format!("variable name issue (at {pos}): {}", e))
}
parse_error::ParseError::InvalidSequenceBackslashXInMinusS { pos: _, c } => {
USimpleError::new(125, format!("invalid sequence '\\{c}' in -S"))
EnvError::EnvParsingOfVariableMissingClosingBraceAfterValue(pos) => {
USimpleError::new(125, format!("variable name issue (at {pos}): {}", e))
}
parse_error::ParseError::MissingClosingQuote { pos: _, c: _ } => {
USimpleError::new(125, "no terminating quote in -S string")
EnvError::EnvParsingOfVariableUnexpectedNumber(pos, _) => {
USimpleError::new(125, format!("variable name issue (at {pos}): {}", e))
}
parse_error::ParseError::ParsingOfVariableNameFailed { pos, msg } => {
USimpleError::new(125, format!("variable name issue (at {pos}): {msg}",))
EnvError::EnvParsingOfVariableExceptedBraceOrColon(pos, _) => {
USimpleError::new(125, format!("variable name issue (at {pos}): {}", e))
}
_ => USimpleError::new(125, format!("Error: {e:?}")),
})
Expand Down Expand Up @@ -771,4 +814,68 @@ mod tests {
parse_args_from_str(&NCvt::convert(r#"-i A='B \' C'"#)).unwrap()
);
}

#[test]
fn test_error_cases() {
// Test EnvBackslashCNotAllowedInDoubleQuotes
let result = parse_args_from_str(&NCvt::convert(r#"sh -c "echo \c""#));
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"'\\c' must not appear in double-quoted -S string"
);

// Test EnvInvalidBackslashAtEndOfStringInMinusS
let result = parse_args_from_str(&NCvt::convert(r#"sh -c "echo \"#));
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"no terminating quote in -S string"
);

// Test EnvInvalidSequenceBackslashXInMinusS
let result = parse_args_from_str(&NCvt::convert(r#"sh -c "echo \x""#));
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("invalid sequence '\\x' in -S")
);

// Test EnvMissingClosingQuote
let result = parse_args_from_str(&NCvt::convert(r#"sh -c "echo "#));
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"no terminating quote in -S string"
);

// Test variable-related errors
let result = parse_args_from_str(&NCvt::convert(r#"echo ${FOO"#));
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("variable name issue (at 10): Missing closing brace")
);

let result = parse_args_from_str(&NCvt::convert(r#"echo ${FOO:-value"#));
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("variable name issue (at 17): Missing closing brace after default value")
);

let result = parse_args_from_str(&NCvt::convert(r#"echo ${1FOO}"#));
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("variable name issue (at 7): Unexpected character: '1', expected variable name must not start with 0..9"));

let result = parse_args_from_str(&NCvt::convert(r#"echo ${FOO?}"#));
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("variable name issue (at 10): Unexpected character: '?', expected a closing brace ('}') or colon (':')"));
}
}
55 changes: 0 additions & 55 deletions src/uu/env/src/parse_error.rs

This file was deleted.

Loading
Loading