代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/exiv2 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From 35b3e596edacd2437c2c5d3dd2b5c9502626163d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= <dan.cermak@cgc-instruments.com>
Date: Fri, 17 Aug 2018 16:41:05 +0200
Subject: [PATCH] Add overflow & overread checks to PngChunk::parseTXTChunk()
This function was creating a lot of new pointers and strings without
properly checking the array bounds. This commit adds several calls
to enforce(), making sure that the pointers stay within bounds.
Strings are now created using the helper function
string_from_unterminated() to prevent overreads in the constructor of
std::string.
This fixes #400
---
src/pngchunk_int.cpp | 63 ++++++++++++++++++++++++++------------------
1 file changed, 37 insertions(+), 26 deletions(-)
diff --git a/src/pngchunk.cpp b/src/pngchunk.cpp
index e087e47cb..f13594bd8 100644
--- a/src/pngchunk.cpp
+++ b/src/pngchunk.cpp
@@ -34,6 +34,7 @@
#include "image.hpp"
#include "error.hpp"
#include "enforce.hpp"
+#include "safe_op.hpp"
// + standard includes
#include <sstream>
@@ -55,6 +54,13 @@ EXIV2_RCSID("@(#) $Id: pngchunk.cpp 3777 2015-05-02 11:55:40Z ahuggel $")
#include <zlib.h> // To uncompress or compress text chunk
+/* Added as support of CVE-2018-16336 */
+std::string string_from_unterminated(const char* data, size_t data_length)
+{
+ const size_t StringLength = strnlen(data, data_length);
+
+ return std::string(data, StringLength);
+}
/*
URLs to find informations about PNG chunks :
@@ -133,6 +135,8 @@ namespace Exiv2 {
if(type == zTXt_Chunk)
{
+ enforce(data.size_ >= Safe::add(keysize, 2), Exiv2::kerCorruptedMetadata);
+
// Extract a deflate compressed Latin-1 text chunk
// we get the compression method after the key
@@ -149,11 +153,13 @@ namespace Exiv2 {
// compressed string after the compression technique spec
const byte* compressedText = data.pData_ + keysize + 2;
unsigned int compressedTextSize = data.size_ - keysize - 2;
+ enforce(compressedTextSize < data.size_, kerCorruptedMetadata);
zlibUncompress(compressedText, compressedTextSize, arr);
}
else if(type == tEXt_Chunk)
{
+ enforce(data.size_ >= Safe::add(keysize, 1), Exiv2::kerCorruptedMetadata);
// Extract a non-compressed Latin-1 text chunk
// the text comes after the key, but isn't null terminated
@@ -164,7 +170,8 @@ namespace Exiv2 {
}
else if(type == iTXt_Chunk)
{
+ enforce(data.size_ >= Safe::add(keysize, 3), Exiv2::kerCorruptedMetadata);
const int nullSeparators = std::count(&data.pData_[keysize+3], &data.pData_[data.size_], '\0');
enforce(nullSeparators >= 2, Exiv2::kerCorruptedMetadata);
@@ -178,40 +185,44 @@ namespace Exiv2 {
enforce(compressionMethod == 0x00, Exiv2::kerCorruptedMetadata);
// language description string after the compression technique spec
- std::string languageText((const char*)(data.pData_ + keysize + 3));
- unsigned int languageTextSize = static_cast<unsigned int>(languageText.size());
+ const size_t languageTextMaxSize = data.size_ - keysize - 3;
+ std::string languageText =
+ string_from_unterminated((const char*)(data.pData_ + Safe::add(keysize, 3)), languageTextMaxSize);
+ const unsigned int languageTextSize = static_cast<unsigned int>(languageText.size());
+
+ enforce(data.size_ >= Safe::add(static_cast<unsigned int>(Safe::add(keysize, 4)), languageTextSize),
+ Exiv2::kerCorruptedMetadata);
// translated keyword string after the language description
- std::string translatedKeyText((const char*)(data.pData_ + keysize + 3 + languageTextSize +1));
- unsigned int translatedKeyTextSize = static_cast<unsigned int>(translatedKeyText.size());
+ std::string translatedKeyText =
+ string_from_unterminated((const char*)(data.pData_ + keysize + 3 + languageTextSize + 1),
+ data.size_ - (keysize + 3 + languageTextSize + 1));
+ const unsigned int translatedKeyTextSize = static_cast<unsigned int>(translatedKeyText.size());
- if ( compressionFlag == 0x00 )
- {
- // then it's an uncompressed iTXt chunk
-#ifdef DEBUG
- std::cout << "Exiv2::PngChunk::parseTXTChunk: We found an uncompressed iTXt field\n";
-#endif
+ if ((compressionFlag == 0x00) || (compressionFlag == 0x01 && compressionMethod == 0x00)) {
+ enforce(Safe::add(static_cast<unsigned int>(keysize + 3 + languageTextSize + 1),
+ Safe::add(translatedKeyTextSize, 1u)) <= data.size_,
+ Exiv2::kerCorruptedMetadata);
- // the text comes after the translated keyword, but isn't null terminated
const byte* text = data.pData_ + keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1;
- long textsize = data.size_ - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1);
+ const long textsize = data.size_ - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1);
- arr.alloc(textsize);
- arr = DataBuf(text, textsize);
- }
- else if ( compressionFlag == 0x01 && compressionMethod == 0x00 )
- {
- // then it's a zlib compressed iTXt chunk
+ if (compressionFlag == 0x00) {
+ // then it's an uncompressed iTXt chunk
#ifdef DEBUG
- std::cout << "Exiv2::PngChunk::parseTXTChunk: We found a zlib compressed iTXt field\n";
+ std::cout << "Exiv2::PngChunk::parseTXTChunk: We found an uncompressed iTXt field\n";
#endif
- // the compressed text comes after the translated keyword, but isn't null terminated
- const byte* compressedText = data.pData_ + keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1;
- long compressedTextSize = data.size_ - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1);
+ arr.alloc(textsize);
+ arr = DataBuf(text, textsize);
+ } else if (compressionFlag == 0x01 && compressionMethod == 0x00) {
+ // then it's a zlib compressed iTXt chunk
+#ifdef DEBUG
+ std::cout << "Exiv2::PngChunk::parseTXTChunk: We found a zlib compressed iTXt field\n";
+#endif
- zlibUncompress(compressedText, compressedTextSize, arr);
- }
- else
- {
+ // the compressed text comes after the translated keyword, but isn't null terminated
+ zlibUncompress(text, textsize, arr);
+ }
+ } else {
// then it isn't zlib compressed and we are sunk
#ifdef DEBUG
std::cerr << "Exiv2::PngChunk::parseTXTChunk: Non-standard iTXt compression method.\n";
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。