Skip to content

Commit fee60dc

Browse files
Copilotjgarzik
andcommitted
Add defense-in-depth fixes for archive and file format parsing
Co-authored-by: jgarzik <494411+jgarzik@users.noreply.github.com>
1 parent dd2832c commit fee60dc

File tree

7 files changed

+38
-2
lines changed

7 files changed

+38
-2
lines changed

pax/formats/cpio.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,12 @@ fn parse_header<R: Read>(header: &[u8; HEADER_SIZE], reader: &mut R) -> PaxResul
272272
fn parse_octal_field(bytes: &[u8]) -> PaxResult<u64> {
273273
let s = std::str::from_utf8(bytes)
274274
.map_err(|_| PaxError::InvalidHeader("invalid octal field".to_string()))?;
275-
u64::from_str_radix(s.trim(), 8)
275+
let s = s.trim();
276+
// Reject if the octal string contains a sign
277+
if s.starts_with('+') || s.starts_with('-') {
278+
return Err(PaxError::InvalidHeader(format!("invalid octal: {}", s)));
279+
}
280+
u64::from_str_radix(s, 8)
276281
.map_err(|_| PaxError::InvalidHeader(format!("invalid octal: {}", s)))
277282
}
278283

pax/formats/pax.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,10 @@ fn parse_octal(bytes: &[u8]) -> PaxResult<u64> {
837837
if s.is_empty() {
838838
return Ok(0);
839839
}
840+
// Reject if the octal string contains a sign
841+
if s.starts_with('+') || s.starts_with('-') {
842+
return Err(PaxError::InvalidHeader(format!("invalid octal: {}", s)));
843+
}
840844
u64::from_str_radix(&s, 8).map_err(|_| PaxError::InvalidHeader(format!("invalid octal: {}", s)))
841845
}
842846

pax/formats/ustar.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ fn parse_octal(bytes: &[u8]) -> PaxResult<u64> {
273273
if s.is_empty() {
274274
return Ok(0);
275275
}
276+
// Reject if the octal string contains a sign
277+
if s.starts_with('+') || s.starts_with('-') {
278+
return Err(PaxError::InvalidHeader(format!("invalid octal: {}", s)));
279+
}
276280
u64::from_str_radix(&s, 8).map_err(|_| PaxError::InvalidHeader(format!("invalid octal: {}", s)))
277281
}
278282

pax/main.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,11 @@ fn is_valid_tar_checksum(buf: &[u8]) -> bool {
557557
return false;
558558
}
559559

560+
// Reject if checksum contains a sign
561+
if chksum_str.starts_with('+') || chksum_str.starts_with('-') {
562+
return false;
563+
}
564+
560565
let stored = match u32::from_str_radix(chksum_str, 8) {
561566
Ok(v) => v,
562567
Err(_) => return false,

pax/modes/append.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ fn is_valid_tar_checksum(header: &[u8]) -> bool {
124124
return false;
125125
}
126126

127+
// Reject if checksum contains a sign
128+
if chksum_str.starts_with('+') || chksum_str.starts_with('-') {
129+
return false;
130+
}
131+
127132
let stored = match u32::from_str_radix(chksum_str, 8) {
128133
Ok(v) => v,
129134
Err(_) => return false,
@@ -214,6 +219,10 @@ fn parse_octal(bytes: &[u8]) -> PaxResult<u64> {
214219
if s.is_empty() {
215220
return Ok(0);
216221
}
222+
// Reject if the octal string contains a sign
223+
if s.starts_with('+') || s.starts_with('-') {
224+
return Err(PaxError::InvalidHeader(format!("invalid octal: {}", s)));
225+
}
217226
u64::from_str_radix(s, 8).map_err(|_| PaxError::InvalidHeader(format!("invalid octal: {}", s)))
218227
}
219228

pax/multivolume.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,10 @@ fn parse_octal(bytes: &[u8]) -> PaxResult<u64> {
745745
if s.is_empty() {
746746
return Ok(0);
747747
}
748+
// Reject if the octal string contains a sign
749+
if s.starts_with('+') || s.starts_with('-') {
750+
return Err(PaxError::InvalidHeader(format!("invalid octal: {}", s)));
751+
}
748752
u64::from_str_radix(s, 8).map_err(|_| PaxError::InvalidHeader(format!("invalid octal: {}", s)))
749753
}
750754

xform/uudecode.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,12 @@ impl Header {
5959
panic!("Invalid encoding type");
6060
};
6161

62-
let lower_perm_bits = u32::from_str_radix(split[1], 8).expect("Invalid permission value");
62+
let mode_str = split[1];
63+
// Reject if mode contains a sign
64+
if mode_str.starts_with('+') || mode_str.starts_with('-') {
65+
panic!("Invalid permission value: unexpected sign");
66+
}
67+
let lower_perm_bits = u32::from_str_radix(mode_str, 8).expect("Invalid permission value");
6368
let out = PathBuf::from(split[2]);
6469

6570
Self {

0 commit comments

Comments
 (0)