-
Notifications
You must be signed in to change notification settings - Fork 778
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
Conversation
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) |
There was a problem hiding this comment.
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. */ |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
CC: @88Sanghy88 |
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)
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.cResolves #2353
Resolves https://issues.oss-fuzz.com/issues/42537231