@@ -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 {
151154pub 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
156161impl 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