Skip to content

Commit 5d06a08

Browse files
committed
Make the allow_escapes opt-in at the lib level
1 parent 128a9f2 commit 5d06a08

2 files changed

Lines changed: 19 additions & 0 deletions

File tree

cli/src/commands/extract.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub async fn run(args: ExtractArgs) -> Result<()> {
3838

3939
let options = ExtractOptions {
4040
verify_checksums: !args.no_checksum,
41+
allow_escapes: args.allow_escapes,
4142
};
4243

4344
let stats: ExtractStats = if args.files.is_empty() {

src/file/reader.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ pub enum ExtractError {
103103

104104
#[error("Verification failed. Path: '{}'", .1.display())]
105105
VerificationFailed(#[source] std::io::Error, PathBuf),
106+
107+
#[error("Archive has escaped paths but allow_escapes was not set in ExtractOptions")]
108+
AllowEscapesRequired,
106109
}
107110

108111
/// Timing breakdown for extraction phases.
@@ -151,12 +154,15 @@ impl AddAssign for ExtractStats {
151154
pub struct ExtractOptions {
152155
/// Verify blake3 checksums during extraction.
153156
pub verify_checksums: bool,
157+
/// Allow extracting archives with `\xNN` escape sequences in paths.
158+
pub allow_escapes: bool,
154159
}
155160

156161
impl Default for ExtractOptions {
157162
fn default() -> Self {
158163
Self {
159164
verify_checksums: true,
165+
allow_escapes: false,
160166
}
161167
}
162168
}
@@ -383,6 +389,9 @@ impl BoxFileReader {
383389
path: &BoxPath<'_>,
384390
output_path: P,
385391
) -> Result<(), ExtractError> {
392+
if self.header.allow_escapes {
393+
return Err(ExtractError::AllowEscapesRequired);
394+
}
386395
let output_path = output_path.as_ref();
387396
let record = self
388397
.meta
@@ -414,6 +423,9 @@ impl BoxFileReader {
414423
output_path: P,
415424
options: ExtractOptions,
416425
) -> Result<ExtractStats, ExtractError> {
426+
if self.header.allow_escapes && !options.allow_escapes {
427+
return Err(ExtractError::AllowEscapesRequired);
428+
}
417429
let output_path = output_path.as_ref();
418430
let mut stats = ExtractStats::default();
419431
let start = Instant::now();
@@ -439,6 +451,9 @@ impl BoxFileReader {
439451
output_path: P,
440452
options: ExtractOptions,
441453
) -> Result<ExtractStats, ExtractError> {
454+
if self.header.allow_escapes && !options.allow_escapes {
455+
return Err(ExtractError::AllowEscapesRequired);
456+
}
442457
let output_path = output_path.as_ref();
443458
let mut stats = ExtractStats::default();
444459

@@ -484,6 +499,9 @@ impl BoxFileReader {
484499
concurrency: usize,
485500
progress: Option<tokio::sync::mpsc::UnboundedSender<ExtractProgress>>,
486501
) -> Result<ExtractStats, ExtractError> {
502+
if self.header.allow_escapes && !options.allow_escapes {
503+
return Err(ExtractError::AllowEscapesRequired);
504+
}
487505
let output_path = output_path.as_ref();
488506
let mut timing = ExtractTiming::default();
489507

0 commit comments

Comments
 (0)