difftreelog
fix prevent --multi path escape
in: master
1 file changed
cmds/jrsonnet/src/main.rsdiffbeforeafterboth1use std::{1use std::{2 fs::{File, create_dir_all},2 fs::{File, create_dir_all},3 io::{Read, Write},3 io::{Read, Write},4 path::{Component, Path, PathBuf},4};5};566use clap::{CommandFactory, Parser};7use clap::{CommandFactory, Parser};160 true161 true161}162}163164fn multi_output_path(base: &Path, field: &str) -> Result<PathBuf, Error> {165 let mut normalized = PathBuf::new();166 for component in Path::new(field).components() {167 match component {168 Component::Normal(name) => normalized.push(name),169 Component::CurDir => {}170 Component::ParentDir if normalized.pop() => {}171 Component::ParentDir | Component::RootDir | Component::Prefix(_) => {172 bail!("field {field} escapes --multi output directory")173 }174 }175 }176 if normalized.as_os_str().is_empty() {177 bail!("field {field} is not a valid output path")178 }179 Ok(base.join(normalized))180}162181163fn main_real(opts: Opts) -> Result<(), Error> {182fn main_real(opts: Opts) -> Result<(), Error> {164 let _gc_leak_guard = opts.gc.leak_on_exit();183 let _gc_leak_guard = opts.gc.leak_on_exit();222 ) {241 ) {223 let data = data.with_description(|| format!("getting field {field} for manifest"))?;242 let data = data.with_description(|| format!("getting field {field} for manifest"))?;224243225 let mut path = multi.clone();244 let path = multi_output_path(&multi, &field)?;226 path.push(&field as &str);227 if opts.output.create_output_dirs {245 if opts.output.create_output_dirs {228 let mut dir = path.clone();246 let mut dir = path.clone();229 dir.pop();247 dir.pop();