Sophie

Sophie

distrib > Mageia > 6 > i586 > by-pkgid > 6473b75a49392b9e3df36b9ae3c1e07d > files > 4

advancecomp-1.20-3.3.mga6.src.rpm

Ed. note: documentation portions of the patch were removed.

From 7deeafc02b29cc51d51079e66f4f43f986ff9cc5 Mon Sep 17 00:00:00 2001
From: Andrea Mazzoleni <amadvance@gmail.com>
Date: Mon, 12 Feb 2018 22:10:14 +0100
Subject: [PATCH] Fix a crash condition due invalid ZIP data

---
 zip.cc          | 20 +++++++++++++++-----
 zip.h           |  4 ++--

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();