diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc index a64b3b155..efe10966e 100644 --- a/libziparchive/zip_archive.cc +++ b/libziparchive/zip_archive.cc @@ -62,68 +62,6 @@ static const bool kCrcChecksEnabled = false; // The maximum number of bytes to scan backwards for the EOCD start. static const uint32_t kMaxEOCDSearch = kMaxCommentLen + sizeof(EocdRecord); -static const char* kErrorMessages[] = { - "Unknown return code.", - "Iteration ended", - "Zlib error", - "Invalid file", - "Invalid handle", - "Duplicate entries in archive", - "Empty archive", - "Entry not found", - "Invalid offset", - "Inconsistent information", - "Invalid entry name", - "I/O Error", - "File mapping failed" -}; - -static const int32_t kErrorMessageUpperBound = 0; - -static const int32_t kIterationEnd = -1; - -// We encountered a Zlib error when inflating a stream from this file. -// Usually indicates file corruption. -static const int32_t kZlibError = -2; - -// The input file cannot be processed as a zip archive. Usually because -// it's too small, too large or does not have a valid signature. -static const int32_t kInvalidFile = -3; - -// An invalid iteration / ziparchive handle was passed in as an input -// argument. -static const int32_t kInvalidHandle = -4; - -// The zip archive contained two (or possibly more) entries with the same -// name. -static const int32_t kDuplicateEntry = -5; - -// The zip archive contains no entries. -static const int32_t kEmptyArchive = -6; - -// The specified entry was not found in the archive. -static const int32_t kEntryNotFound = -7; - -// The zip archive contained an invalid local file header pointer. -static const int32_t kInvalidOffset = -8; - -// The zip archive contained inconsistent entry information. This could -// be because the central directory & local file header did not agree, or -// if the actual uncompressed length or crc32 do not match their declared -// values. -static const int32_t kInconsistentInformation = -9; - -// An invalid entry name was encountered. -static const int32_t kInvalidEntryName = -10; - -// An I/O related system call (read, lseek, ftruncate, map) failed. -static const int32_t kIoError = -11; - -// We were not able to mmap the central directory or entry contents. -static const int32_t kMmapFailed = -12; - -static const int32_t kErrorMessageLowerBound = -13; - /* * A Read-only Zip archive. * @@ -1106,11 +1044,17 @@ int32_t ExtractEntryToFile(ZipArchiveHandle handle, } const char* ErrorCodeString(int32_t error_code) { - if (error_code > kErrorMessageLowerBound && error_code < kErrorMessageUpperBound) { - return kErrorMessages[error_code * -1]; + // Make sure that the number of entries in kErrorMessages and ErrorCodes + // match. + static_assert((-kLastErrorCode + 1) == arraysize(kErrorMessages), + "(-kLastErrorCode + 1) != arraysize(kErrorMessages)"); + + const uint32_t idx = -error_code; + if (idx < arraysize(kErrorMessages)) { + return kErrorMessages[idx]; } - return kErrorMessages[0]; + return "Unknown return code"; } int GetFileDescriptor(const ZipArchiveHandle handle) { diff --git a/libziparchive/zip_archive_private.h b/libziparchive/zip_archive_private.h index 971db4f12..de93ecdd1 100644 --- a/libziparchive/zip_archive_private.h +++ b/libziparchive/zip_archive_private.h @@ -26,6 +26,69 @@ #include #include +#include "android-base/macros.h" + +static const char* kErrorMessages[] = { + "Success", + "Iteration ended", + "Zlib error", + "Invalid file", + "Invalid handle", + "Duplicate entries in archive", + "Empty archive", + "Entry not found", + "Invalid offset", + "Inconsistent information", + "Invalid entry name", + "I/O error", + "File mapping failed", +}; + +enum ErrorCodes : int32_t { + kIterationEnd = -1, + + // We encountered a Zlib error when inflating a stream from this file. + // Usually indicates file corruption. + kZlibError = -2, + + // The input file cannot be processed as a zip archive. Usually because + // it's too small, too large or does not have a valid signature. + kInvalidFile = -3, + + // An invalid iteration / ziparchive handle was passed in as an input + // argument. + kInvalidHandle = -4, + + // The zip archive contained two (or possibly more) entries with the same + // name. + kDuplicateEntry = -5, + + // The zip archive contains no entries. + kEmptyArchive = -6, + + // The specified entry was not found in the archive. + kEntryNotFound = -7, + + // The zip archive contained an invalid local file header pointer. + kInvalidOffset = -8, + + // The zip archive contained inconsistent entry information. This could + // be because the central directory & local file header did not agree, or + // if the actual uncompressed length or crc32 do not match their declared + // values. + kInconsistentInformation = -9, + + // An invalid entry name was encountered. + kInvalidEntryName = -10, + + // An I/O related system call (read, lseek, ftruncate, map) failed. + kIoError = -11, + + // We were not able to mmap the central directory or entry contents. + kMmapFailed = -12, + + kLastErrorCode = kMmapFailed, +}; class MappedZipFile { public: diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc index 42167ddec..52099c3b5 100644 --- a/libziparchive/zip_archive_test.cc +++ b/libziparchive/zip_archive_test.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "zip_archive_private.h" + #include #include #include @@ -708,8 +710,7 @@ TEST(ziparchive, InvalidDataDescriptors) { int32_t error_code = 0; ExtractEntryToMemory(invalid_csize, &entry, &error_code); - ASSERT_GT(0, error_code); - ASSERT_STREQ("Inconsistent information", ErrorCodeString(error_code)); + ASSERT_EQ(kInconsistentInformation, error_code); std::vector invalid_size = kDataDescriptorZipFile; invalid_csize[kSizeOffset] = 0xfe; @@ -718,8 +719,17 @@ TEST(ziparchive, InvalidDataDescriptors) { entry.clear(); ExtractEntryToMemory(invalid_csize, &entry, &error_code); - ASSERT_GT(0, error_code); - ASSERT_STREQ("Inconsistent information", ErrorCodeString(error_code)); + ASSERT_EQ(kInconsistentInformation, error_code); +} + +TEST(ziparchive, ErrorCodeString) { + ASSERT_STREQ("Success", ErrorCodeString(0)); + + // Out of bounds. + ASSERT_STREQ("Unknown return code", ErrorCodeString(1)); + ASSERT_STREQ("Unknown return code", ErrorCodeString(-13)); + + ASSERT_STREQ("I/O error", ErrorCodeString(kIoError)); } int main(int argc, char** argv) {