git.delta.rocks / jrsonnet / refs/commits / 9c66309c9a3e

difftreelog

fix prevent --multi path escape

zqpzplzvYaroslav Bolyukin2026-07-28parent: #8e3aecf.patch.diff
in: master

1 file changed

modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
1use 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};
56
6use clap::{CommandFactory, Parser};7use clap::{CommandFactory, Parser};
160 true161 true
161}162}
163
164fn 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}
162181
163fn 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"))?;
224243
225 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();