Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't crash on truncated tar archives #2364

Merged
merged 1 commit into from
Oct 11, 2024

Conversation

kientzle
Copy link
Contributor

@kientzle kientzle commented Oct 6, 2024

The tar header parsing overhaul in #2127 introduced a systematic mishandling of truncated files: the code incorrectly checks for whether a given read operation failed, and ends up dereferencing a NULL pointer in this case. I've gone back and double-checked how __archive_read_ahead actually works (it returns NULL precisely when it was unable to satisfy the read request) and reworked the error handling for each call to this function in archive_read_support_format_tar.c

Resolves #2353
Resolves https://issues.oss-fuzz.com/issues/42537231

The tar header parsing overhaul in libarchive#2127 introduced a systematic
mishandling of truncated files:  the code incorrectly checks for
whether a given read operation failed, and ends up dereferencing
a NULL pointer in this case.  I've gone back and double-checked
how `__archive_read_ahead` actually works (it returns NULL precisely
when it was unable to satisfy the read request) and reworked the
error handling for each call to this function in archive_read_support_format_tar.c

Resolves libarchive#2353
Resolves https://issues.oss-fuzz.com/issues/42537231
@@ -631,8 +631,6 @@ archive_read_format_tar_read_data(struct archive_read *a,
}

*buff = __archive_read_ahead(a, 1, &bytes_read);
if (bytes_read < 0)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whenever __archive_read_ahead puts an error value into bytes_read it also returns NULL, so the bytes_read < 0 checks throughout are redundant and have been removed.

@@ -763,7 +759,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
return (ARCHIVE_EOF);
}
}
if (bytes < 512) { /* Short block at EOF; this is bad. */
if (h == NULL) { /* Short block at EOF; this is bad. */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change has no effect but makes this part more consistent with the pattern now used throughout this source file.

@@ -1630,6 +1626,9 @@ read_mac_metadata_blob(struct archive_read *a,
tar_flush_unconsumed(a, unconsumed);
data = __archive_read_ahead(a, msize, NULL);
if (data == NULL) {
archive_set_error(&a->archive, EINVAL,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added appropriate error messages for every failed read.

err = ARCHIVE_WARN;
}
} else {
if (p == NULL) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've swapped this and a few other instances around so that we consistently check for p == NULL as the first thing after __archive_read_ahead.

@@ -3395,7 +3405,7 @@ readline(struct archive_read *a, struct tar *tar, const char **start,
tar_flush_unconsumed(a, unconsumed);

t = __archive_read_ahead(a, 1, &bytes_read);
if (bytes_read <= 0)
if (bytes_read <= 0 || t == NULL)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bytes_read <= 0 clause here is technically redundant, but I've left it for now since it does no harm.

@kientzle
Copy link
Contributor Author

kientzle commented Oct 6, 2024

CC: @88Sanghy88

@mmatuska mmatuska merged commit 565b5ae into libarchive:master Oct 11, 2024
20 checks passed
mmatuska pushed a commit that referenced this pull request Oct 12, 2024
The tar header parsing overhaul in #2127 introduced a systematic
mishandling of truncated files: the code incorrectly checks for whether
a given read operation failed, and ends up dereferencing a NULL pointer
in this case. I've gone back and double-checked how
`__archive_read_ahead` actually works (it returns NULL precisely when it
was unable to satisfy the read request) and reworked the error handling
for each call to this function in archive_read_support_format_tar.c

Resolves #2353
Resolves https://issues.oss-fuzz.com/issues/42537231

(cherry picked from commit 565b5ae)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants