Skip to content

Escape Pattern before being passed to glob #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 29, 2024
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
69 changes: 38 additions & 31 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ use std::env;
use std::path::PathBuf;
use std::process::Command;

use glob::glob;
use glob::{glob, Pattern};
use lazy_static::lazy_static;

pub mod errors;
Expand Down Expand Up @@ -162,13 +162,9 @@ pub fn get_jvm_dyn_lib_file_name() -> &'static str {
/// If `JAVA_HOME` is not defined, the function tries to locate it using the `java` executable.
pub fn locate_java_home() -> errors::Result<String> {
match &env::var("JAVA_HOME") {
Ok(s) if s.is_empty() => {
do_locate_java_home()
}
Ok(s) if s.is_empty() => do_locate_java_home(),
Ok(java_home_env_var) => Ok(java_home_env_var.clone()),
Err(_) => {
do_locate_java_home()
}
Err(_) => do_locate_java_home(),
}
}

Expand All @@ -189,25 +185,31 @@ fn do_locate_java_home() -> errors::Result<String> {
}

let output = command.output().map_err(|error| {
let message = format!("Command '{}' is not found in the system PATH ({})", command_str, error);
let message = format!(
"Command '{}' is not found in the system PATH ({})",
command_str, error
);
errors::JavaLocatorError::new(&message)
})?;
let java_exec_path = String::from_utf8(output.stdout)
.map(|jp| {
let mut lines: Vec<&str> = jp.lines().collect();
if lines.len() > 1 {
println!("WARNING: java_locator found {} possible java locations: {}. Using the last one.",
lines.len(),
lines.join(", "));
lines.remove(lines.len() - 1).to_string()
} else {
jp
}
})?;
let java_exec_path = String::from_utf8(output.stdout).map(|jp| {
let mut lines: Vec<&str> = jp.lines().collect();
if lines.len() > 1 {
println!(
"WARNING: java_locator found {} possible java locations: {}. Using the last one.",
lines.len(),
lines.join(", ")
);
lines.remove(lines.len() - 1).to_string()
} else {
jp
}
})?;

// Return early in case that the java executable is not found
if java_exec_path.is_empty() {
Err(errors::JavaLocatorError::new("Java is not installed or not added in the system PATH"))?
Err(errors::JavaLocatorError::new(
"Java is not installed or not added in the system PATH",
))?
}

let mut test_path = PathBuf::from(java_exec_path.trim());
Expand All @@ -230,17 +232,16 @@ fn do_locate_java_home() -> errors::Result<String> {

match test_path.to_str() {
Some(s) => Ok(String::from(s)),
None => Err(errors::JavaLocatorError::new(&format!("Could not convert path {:?} to String", test_path))),
None => Err(errors::JavaLocatorError::new(&format!(
"Could not convert path {:?} to String",
test_path
))),
}
}

/// Returns the path that contains the `libjvm.so` (or `jvm.dll` in windows).
pub fn locate_jvm_dyn_library() -> errors::Result<String> {
let jvm_dyn_lib_file_name = if is_windows() {
"jvm.dll"
} else {
"libjvm.*"
};
let jvm_dyn_lib_file_name = if is_windows() { "jvm.dll" } else { "libjvm.*" };

locate_file(jvm_dyn_lib_file_name)
}
Expand All @@ -252,7 +253,7 @@ pub fn locate_file(file_name: &str) -> errors::Result<String> {
// Find the JAVA_HOME
let java_home = locate_java_home()?;

let query = format!("{}/**/{}", java_home, file_name);
let query = format!("{}/**/{}", Pattern::escape(&java_home), file_name);

let paths_vec: Vec<String> = glob(&query)?
.filter_map(Result::ok)
Expand All @@ -265,7 +266,10 @@ pub fn locate_file(file_name: &str) -> errors::Result<String> {
.collect();

if paths_vec.is_empty() {
Err(errors::JavaLocatorError::new(&format!("Could not find the {} library in any subdirectory of {}", file_name, java_home)))
Err(errors::JavaLocatorError::new(&format!(
"Could not find the {} library in any subdirectory of {}",
file_name, java_home
)))
} else {
Ok(paths_vec[0].clone())
}
Expand All @@ -278,11 +282,14 @@ mod unit_tests {
#[test]
fn locate_java_home_test() {
println!("locate_java_home: {}", locate_java_home().unwrap());
println!("locate_jvm_dyn_library: {}", locate_jvm_dyn_library().unwrap());
println!(
"locate_jvm_dyn_library: {}",
locate_jvm_dyn_library().unwrap()
);
}

#[test]
fn locate_java_from_exec_test() {
println!("do_locate_java_home: {}", do_locate_java_home().unwrap());
}
}
}
27 changes: 27 additions & 0 deletions tests/ensure-escaped.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use java_locator::locate_jvm_dyn_library;

// Windows does not support `[`, `]`, or `*` in paths so this test does not apply
#[cfg(not(target_os = "windows"))]
#[test]
fn test_javahome_can_be_escaped() {
use std::env::temp_dir;

let test_path = temp_dir()
.join("[funky-javahome]")
.join("nested")
.join("*dir*");

std::fs::create_dir_all(&test_path).expect("failed to create directory");
std::fs::write(test_path.join("libjvm.so"), "stub-file").unwrap();
std::env::set_var(
"JAVA_HOME",
test_path.to_str().expect("no invalid characters"),
);
assert_eq!(
locate_jvm_dyn_library().expect("failed to located jvm library"),
format!(
"{}",
temp_dir().join("[funky-javahome]/nested/*dir*").display()
)
);
}
Loading