From 7deeafc02b29cc51d51079e66f4f43f986ff9cc5 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Mon, 12 Feb 2018 22:10:14 +0100 Subject: [PATCH] Fix a crash condition due invalid ZIP data --- HISTORY | 3 ++- doc/history.1 | 4 +++- doc/history.d | 3 ++- doc/history.txt | 3 ++- zip.cc | 20 +++++++++++++++----- zip.h | 4 ++-- 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/HISTORY b/HISTORY index 382f421..5868bc6 100644 --- a/HISTORY +++ b/HISTORY @@ -3,10 +3,11 @@ ======================= -ADVANCECOMP VERSION 2.1 2018/01 +ADVANCECOMP VERSION 2.1 2018/02 =============================== * Support ZIPs with data descriptor signature. +* Fixed a crash condition with invalid ZIP data. ADVANCECOMP VERSION 2.0 2017/06 diff --git a/doc/history.1 b/doc/history.1 index e684d4b..adbafc1 100644 --- a/doc/history.1 +++ b/doc/history.1 @@ -1,10 +1,12 @@ .TH "History For AdvanceCOMP" 1 .SH NAME advcomp \- History For AdvanceCOMP -.SH ADVANCECOMP VERSION 2.1 2018/01 +.SH ADVANCECOMP VERSION 2.1 2018/02 .PD 0 .IP \(bu Support ZIPs with data descriptor signature. +.IP \(bu +Fixed a crash condition with invalid ZIP data. .PD .SH ADVANCECOMP VERSION 2.0 2017/06 .PD 0 diff --git a/doc/history.d b/doc/history.d index 2b1623a..245ec4c 100644 --- a/doc/history.d +++ b/doc/history.d @@ -1,8 +1,9 @@ Name advcomp - History For AdvanceCOMP -AdvanceCOMP Version 2.1 2018/01 +AdvanceCOMP Version 2.1 2018/02 ) Support ZIPs with data descriptor signature. + ) Fixed a crash condition with invalid ZIP data. AdvanceCOMP Version 2.0 2017/06 ) Added support for reading MNG files with depth of 1, 2, and 4 bits. diff --git a/doc/history.txt b/doc/history.txt index fcfd9af..bda6383 100644 --- a/doc/history.txt +++ b/doc/history.txt @@ -3,10 +3,11 @@ ======================= -ADVANCECOMP VERSION 2.1 2018/01 +ADVANCECOMP VERSION 2.1 2018/02 =============================== * Support ZIPs with data descriptor signature. +* Fixed a crash condition with invalid ZIP data. ADVANCECOMP VERSION 2.0 2017/06 diff --git a/zip.cc b/zip.cc index b4608f7..18882ed 100644 --- a/zip.cc +++ b/zip.cc @@ -456,13 +456,15 @@ string zip_entry::name_get() const } /** Check central directory entry. */ -void zip_entry::check_cent(const unsigned char* buf) const +void zip_entry::check_cent(const unsigned char* buf, unsigned buf_size) const { + if (buf_size < ZIP_CO_FIXED) { + throw error_invalid() << "Invalid central directory data"; + } // check signature if (le_uint32_read(buf+ZIP_CO_central_file_header_signature) != ZIP_C_signature) { throw error_invalid() << "Invalid central directory signature"; } - // check filename_length > 0, can't exist a file without a name if (le_uint16_read(buf+ZIP_CO_filename_length) == 0) { throw error_invalid() << "Empty filename in central directory"; @@ -679,11 +681,11 @@ void zip_entry::save_local(FILE* f) * \param buf Fixed size cent dir. * \param f File seeked after the fixed size cent dir. */ -void zip_entry::load_cent(const unsigned char* buf, unsigned& skip) +void zip_entry::load_cent(const unsigned char* buf, unsigned buf_size, unsigned& skip) { const unsigned char* o_buf = buf; - check_cent(buf); + check_cent(buf, buf_size); // read header info.version_made_by = le_uint8_read(buf+ZIP_CO_version_made_by); @@ -705,6 +707,14 @@ void zip_entry::load_cent(const unsigned char* buf, unsigned& skip) info.relative_offset_of_local_header = le_uint32_read(buf+ZIP_CO_relative_offset_of_local_header); buf += ZIP_CO_FIXED; + if (buf_size < info.filename_length + || buf_size < info.central_extra_field_length + || buf_size < info.file_comment_length + || buf_size < ZIP_CO_FIXED + info.filename_length + info.central_extra_field_length + info.file_comment_length + ) { + throw error_invalid() << "Invalid central directory data"; + } + // read filename data_free(file_name); file_name = data_alloc(info.filename_length); @@ -853,7 +863,7 @@ void zip::open() unsigned skip = 0; try { - i->load_cent(data + data_pos, skip); + i->load_cent(data + data_pos, data_size - data_pos, skip); } catch (...) { map.erase(i); throw; diff --git a/zip.h b/zip.h index 45fdf2a..abd10c1 100644 --- a/zip.h +++ b/zip.h @@ -192,7 +192,7 @@ class zip_entry { unsigned char* central_extra_field; unsigned char* data; - void check_cent(const unsigned char* buf) const; + void check_cent(const unsigned char* buf, unsigned buf_size) const; void check_local(const unsigned char* buf) const; void check_descriptor(const unsigned char* buf) const; @@ -208,7 +208,7 @@ class zip_entry { void load_local(const unsigned char* buf, FILE* f, unsigned size); void save_local(FILE* f); - void load_cent(const unsigned char* buf, unsigned& skip); + void load_cent(const unsigned char* buf, unsigned size, unsigned& skip); void save_cent(FILE* f); void unload();