Skip to content

Commit fec0c53

Browse files
authored
Merge pull request #1 from elbe0046/fix-contents-added-after-header-creation
Fix handling contents added after header creation
2 parents dc78ebe + c07f6c0 commit fec0c53

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

src/builder.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,9 @@ impl<W: Write> Builder<W> {
120120
/// header will be modified.
121121
///
122122
/// Then it will append the header, followed by contents of the stream
123-
/// specified by `data`. To produce a valid archive the `size` field of
124-
/// `header` must be the same as the length of the stream that's being
123+
/// specified by `data`, with the `size` field of `header` enforced as an
124+
/// upper limit. To produce a valid archive the `size` field of `header`
125+
/// must be less than or equal to the length of the stream that's being
125126
/// written.
126127
///
127128
/// Note that this will not attempt to seek the archive to a valid position,
@@ -406,9 +407,13 @@ impl<W: Write> Builder<W> {
406407
}
407408
}
408409

409-
fn append(mut dst: &mut dyn Write, header: &Header, mut data: &mut dyn Read) -> io::Result<()> {
410+
fn append(mut dst: &mut dyn Write, header: &Header, data: &mut dyn Read) -> io::Result<()> {
410411
dst.write_all(header.as_bytes())?;
411-
let len = io::copy(&mut data, &mut dst)?;
412+
// Guards against there being more data than the header indicates in the case where contents
413+
// have been appended to the file since the header was created.
414+
let size = header.size()?;
415+
let mut limited = data.take(size);
416+
let len = io::copy(&mut limited, &mut dst)?;
412417

413418
// Pad with zeros if necessary.
414419
let buf = [0; 512];

tests/all.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -1279,10 +1279,12 @@ fn append_long_multibyte() {
12791279
let mut x = tar::Builder::new(Vec::new());
12801280
let mut name = String::new();
12811281
let data: &[u8] = &[];
1282+
let mut header = Header::new_gnu();
1283+
header.set_size(data.len() as u64);
12821284
for _ in 0..512 {
12831285
name.push('a');
12841286
name.push('𑢮');
1285-
x.append_data(&mut Header::new_gnu(), &name, data).unwrap();
1287+
x.append_data(&mut header, &name, data).unwrap();
12861288
name.pop();
12871289
}
12881290
}
@@ -1385,3 +1387,31 @@ fn header_size_overflow() {
13851387
err
13861388
);
13871389
}
1390+
1391+
#[test]
1392+
fn file_contents_appended_after_header_creation() {
1393+
let mut data = String::from("Hello");
1394+
1395+
let mut header = Header::new_gnu();
1396+
header.set_size(data.len() as u64);
1397+
header.set_cksum();
1398+
1399+
// Additional data is appended after header creation
1400+
data.push_str(", World!");
1401+
1402+
let mut ar = Builder::new(Vec::new());
1403+
t!(ar.append_data(&mut header, "test2", data.as_bytes()));
1404+
1405+
let raw = t!(ar.into_inner());
1406+
let mut ar = Archive::new(Cursor::new(raw));
1407+
let mut entries = t!(ar.entries());
1408+
let entry = t!(entries.next().unwrap());
1409+
let offset = entry.raw_file_position();
1410+
let mut raw = ar.into_inner();
1411+
1412+
let mut s = String::new();
1413+
raw.set_position(offset);
1414+
t!(raw.read_to_string(&mut s));
1415+
let s = s.trim_end_matches(char::from(0));
1416+
assert_eq!(s, "Hello");
1417+
}

0 commit comments

Comments
 (0)