Skip to content

Commit

Permalink
opencv: Security fixes
Browse files Browse the repository at this point in the history
Added patches to fix below CVE's:

1. CVE-2019-14491, CVE-2019-14492
Link: opencv/opencv@ac425f6

2. CVE-2019-14493
Link: opencv/opencv@5691d99

3. CVE-2019-15939
Link: opencv/opencv@5a49707

4. CVE-2019-19624
Link: opencv/opencv@d1615ba

Signed-off-by: Neetika.Singh <[email protected]>
Signed-off-by: Armin Kuster <[email protected]>
  • Loading branch information
Neetika Singh authored and akuster committed Mar 16, 2021
1 parent 1ad4455 commit 389757a
Show file tree
Hide file tree
Showing 5 changed files with 619 additions and 0 deletions.
148 changes: 148 additions & 0 deletions meta-oe/recipes-support/opencv/opencv/CVE-2019-14491.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
From 321c74ccd6077bdea1d47450ca4fe955cb5b6330 Mon Sep 17 00:00:00 2001
From: Alexander Alekhin <[email protected]>
Date: Thu, 25 Jul 2019 17:15:59 +0300
Subject: [PATCH] objdetect: validate feature rectangle on reading

CVE: CVE-2019-14491
CVE: CVE-2019-14492
Upstream-Status: Backport [https://github.com/opencv/opencv/commit/ac425f67e4c1d0da9afb9203f0918d8d57c067ed.patch]
Comment: No changes in any hunk

Signed-off-by: Neetika Singh <[email protected]>
---
modules/objdetect/src/cascadedetect.cpp | 43 +++++++++++++++++++++----
modules/objdetect/src/cascadedetect.hpp | 6 ++--
2 files changed, 40 insertions(+), 9 deletions(-)

diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp
index 4b2078306fe..bd62cd21a1b 100644
--- a/modules/objdetect/src/cascadedetect.cpp
+++ b/modules/objdetect/src/cascadedetect.cpp
@@ -47,6 +47,10 @@
#include "opencv2/objdetect/objdetect_c.h"
#include "opencl_kernels_objdetect.hpp"

+#if defined(_MSC_VER)
+# pragma warning(disable:4458) // declaration of 'origWinSize' hides class member
+#endif
+
namespace cv
{

@@ -537,7 +541,7 @@ bool FeatureEvaluator::setImage( InputArray _image, const std::vector<float>& _s

//---------------------------------------------- HaarEvaluator ---------------------------------------

-bool HaarEvaluator::Feature :: read( const FileNode& node )
+bool HaarEvaluator::Feature::read(const FileNode& node, const Size& origWinSize)
{
FileNode rnode = node[CC_RECTS];
FileNodeIterator it = rnode.begin(), it_end = rnode.end();
@@ -549,11 +553,23 @@ bool HaarEvaluator::Feature :: read( const FileNode& node )
rect[ri].weight = 0.f;
}

+ const int W = origWinSize.width;
+ const int H = origWinSize.height;
+
for(ri = 0; it != it_end; ++it, ri++)
{
FileNodeIterator it2 = (*it).begin();
- it2 >> rect[ri].r.x >> rect[ri].r.y >>
- rect[ri].r.width >> rect[ri].r.height >> rect[ri].weight;
+ Feature::RectWeigth& rw = rect[ri];
+ it2 >> rw.r.x >> rw.r.y >> rw.r.width >> rw.r.height >> rw.weight;
+ // input validation
+ {
+ CV_CheckGE(rw.r.x, 0, "Invalid HAAR feature");
+ CV_CheckGE(rw.r.y, 0, "Invalid HAAR feature");
+ CV_CheckLT(rw.r.x, W, "Invalid HAAR feature"); // necessary for overflow checks
+ CV_CheckLT(rw.r.y, H, "Invalid HAAR feature"); // necessary for overflow checks
+ CV_CheckLE(rw.r.x + rw.r.width, W, "Invalid HAAR feature");
+ CV_CheckLE(rw.r.y + rw.r.height, H, "Invalid HAAR feature");
+ }
}

tilted = (int)node[CC_TILTED] != 0;
@@ -598,7 +614,7 @@ bool HaarEvaluator::read(const FileNode& node, Size _origWinSize)

for(i = 0; i < n; i++, ++it)
{
- if(!ff[i].read(*it))
+ if(!ff[i].read(*it, _origWinSize))
return false;
if( ff[i].tilted )
hasTiltedFeatures = true;
@@ -759,11 +775,24 @@ int HaarEvaluator::getSquaresOffset() const
}

//---------------------------------------------- LBPEvaluator -------------------------------------
-bool LBPEvaluator::Feature :: read(const FileNode& node )
+bool LBPEvaluator::Feature::read(const FileNode& node, const Size& origWinSize)
{
FileNode rnode = node[CC_RECT];
FileNodeIterator it = rnode.begin();
it >> rect.x >> rect.y >> rect.width >> rect.height;
+
+ const int W = origWinSize.width;
+ const int H = origWinSize.height;
+ // input validation
+ {
+ CV_CheckGE(rect.x, 0, "Invalid LBP feature");
+ CV_CheckGE(rect.y, 0, "Invalid LBP feature");
+ CV_CheckLT(rect.x, W, "Invalid LBP feature");
+ CV_CheckLT(rect.y, H, "Invalid LBP feature");
+ CV_CheckLE(rect.x + rect.width, W, "Invalid LBP feature");
+ CV_CheckLE(rect.y + rect.height, H, "Invalid LBP feature");
+ }
+
return true;
}

@@ -797,7 +826,7 @@ bool LBPEvaluator::read( const FileNode& node, Size _origWinSize )
std::vector<Feature>& ff = *features;
for(int i = 0; it != it_end; ++it, i++)
{
- if(!ff[i].read(*it))
+ if(!ff[i].read(*it, _origWinSize))
return false;
}
nchannels = 1;
@@ -1477,6 +1506,8 @@ bool CascadeClassifierImpl::Data::read(const FileNode &root)
origWinSize.width = (int)root[CC_WIDTH];
origWinSize.height = (int)root[CC_HEIGHT];
CV_Assert( origWinSize.height > 0 && origWinSize.width > 0 );
+ CV_CheckLE(origWinSize.width, 1000000, "Invalid window size (too large)");
+ CV_CheckLE(origWinSize.height, 1000000, "Invalid window size (too large)");

// load feature params
FileNode fn = root[CC_FEATURE_PARAMS];
diff --git a/modules/objdetect/src/cascadedetect.hpp b/modules/objdetect/src/cascadedetect.hpp
index f9910530b94..d9a288fcdda 100644
--- a/modules/objdetect/src/cascadedetect.hpp
+++ b/modules/objdetect/src/cascadedetect.hpp
@@ -317,12 +317,12 @@ class HaarEvaluator CV_FINAL : public FeatureEvaluator
struct Feature
{
Feature();
- bool read( const FileNode& node );
+ bool read(const FileNode& node, const Size& origWinSize);

bool tilted;

enum { RECT_NUM = 3 };
- struct
+ struct RectWeigth
{
Rect r;
float weight;
@@ -412,7 +412,7 @@ class LBPEvaluator CV_FINAL : public FeatureEvaluator
Feature( int x, int y, int _block_w, int _block_h ) :
rect(x, y, _block_w, _block_h) {}

- bool read(const FileNode& node );
+ bool read(const FileNode& node, const Size& origWinSize);

Rect rect; // weight and height for block
};

237 changes: 237 additions & 0 deletions meta-oe/recipes-support/opencv/opencv/CVE-2019-14493.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
From 5691d998ead1d9b0542bcfced36c2dceb3a59023 Mon Sep 17 00:00:00 2001
From: Alexander Alekhin <[email protected]>
Date: Thu, 25 Jul 2019 15:14:22 +0300
Subject: [PATCH] core(persistence): added null ptr checks

CVE: CVE-2019-14493
Upstream-Status: Backport [https://github.com/opencv/opencv/commit/5691d998ead1d9b0542bcfced36c2dceb3a59023.patch]
Comment: No changes in any hunk

Signed-off-by: Neetika Singh <[email protected]>
---
modules/core/src/persistence_json.cpp | 12 ++++++++++++
modules/core/src/persistence_xml.cpp | 21 +++++++++++++++++++++
modules/core/src/persistence_yml.cpp | 21 +++++++++++++++++++++
3 files changed, 54 insertions(+)

diff --git a/modules/core/src/persistence_json.cpp b/modules/core/src/persistence_json.cpp
index ae678e1b8b1..89914e6534f 100644
--- a/modules/core/src/persistence_json.cpp
+++ b/modules/core/src/persistence_json.cpp
@@ -296,6 +296,8 @@ class JSONParser : public FileStorageParser

while ( is_eof == false && is_completed == false )
{
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
switch ( *ptr )
{
/* comment */
@@ -381,6 +383,7 @@ class JSONParser : public FileStorageParser
if ( is_eof || !is_completed )
{
ptr = fs->bufferStart();
+ CV_Assert(ptr);
*ptr = '\0';
fs->setEof();
if( !is_completed )
@@ -392,6 +395,9 @@ class JSONParser : public FileStorageParser

char* parseKey( char* ptr, FileNode& collection, FileNode& value_placeholder )
{
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+
if( *ptr != '"' )
CV_PARSE_ERROR_CPP( "Key must start with \'\"\'" );

@@ -430,6 +436,9 @@ class JSONParser : public FileStorageParser

char* parseValue( char* ptr, FileNode& node )
{
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid value input");
+
ptr = skipSpaces( ptr );
if( !ptr || !*ptr )
CV_PARSE_ERROR_CPP( "Unexpected End-Of-File" );
@@ -817,6 +826,9 @@ class JSONParser : public FileStorageParser

bool parse( char* ptr )
{
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+
ptr = skipSpaces( ptr );
if ( !ptr || !*ptr )
return false;
diff --git a/modules/core/src/persistence_xml.cpp b/modules/core/src/persistence_xml.cpp
index fb30d90896e..89876dd3da8 100644
--- a/modules/core/src/persistence_xml.cpp
+++ b/modules/core/src/persistence_xml.cpp
@@ -360,6 +360,9 @@ class XMLParser : public FileStorageParser

char* skipSpaces( char* ptr, int mode )
{
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+
int level = 0;

for(;;)
@@ -441,6 +444,9 @@ class XMLParser : public FileStorageParser

char* parseValue( char* ptr, FileNode& node )
{
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+
FileNode new_elem;
bool have_space = true;
int value_type = node.type();
@@ -456,6 +462,8 @@ class XMLParser : public FileStorageParser
(c == '<' && ptr[1] == '!' && ptr[2] == '-') )
{
ptr = skipSpaces( ptr, 0 );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
have_space = true;
c = *ptr;
}
@@ -502,6 +510,8 @@ class XMLParser : public FileStorageParser
{
ptr = fs->parseBase64( ptr, 0, new_elem);
ptr = skipSpaces( ptr, 0 );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
}

ptr = parseTag( ptr, key2, type_name, tag_type );
@@ -645,6 +655,9 @@ class XMLParser : public FileStorageParser
char* parseTag( char* ptr, std::string& tag_name,
std::string& type_name, int& tag_type )
{
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid tag input");
+
if( *ptr == '\0' )
CV_PARSE_ERROR_CPP( "Unexpected end of the stream" );

@@ -702,6 +715,8 @@ class XMLParser : public FileStorageParser
if( *ptr != '=' )
{
ptr = skipSpaces( ptr, CV_XML_INSIDE_TAG );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid attribute");
if( *ptr != '=' )
CV_PARSE_ERROR_CPP( "Attribute name should be followed by \'=\'" );
}
@@ -740,6 +755,8 @@ class XMLParser : public FileStorageParser
if( c != '>' )
{
ptr = skipSpaces( ptr, CV_XML_INSIDE_TAG );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
c = *ptr;
}

@@ -781,6 +798,8 @@ class XMLParser : public FileStorageParser

// CV_XML_INSIDE_TAG is used to prohibit leading comments
ptr = skipSpaces( ptr, CV_XML_INSIDE_TAG );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");

if( memcmp( ptr, "<?xml", 5 ) != 0 ) // FIXIT ptr[1..] - out of bounds read without check
CV_PARSE_ERROR_CPP( "Valid XML should start with \'<?xml ...?>\'" );
@@ -791,6 +810,8 @@ class XMLParser : public FileStorageParser
while( ptr && *ptr != '\0' )
{
ptr = skipSpaces( ptr, 0 );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");

if( *ptr != '\0' )
{
diff --git a/modules/core/src/persistence_yml.cpp b/modules/core/src/persistence_yml.cpp
index 4129ca1dc57..7742e827701 100644
--- a/modules/core/src/persistence_yml.cpp
+++ b/modules/core/src/persistence_yml.cpp
@@ -330,6 +330,9 @@ class YAMLParser : public FileStorageParser

char* skipSpaces( char* ptr, int min_indent, int max_comment_indent )
{
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+
for(;;)
{
while( *ptr == ' ' )
@@ -374,6 +377,9 @@ class YAMLParser : public FileStorageParser

bool getBase64Row(char* ptr, int indent, char* &beg, char* &end)
{
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+
beg = end = ptr = skipSpaces(ptr, 0, INT_MAX);
if (!ptr || !*ptr)
return false; // end of file
@@ -394,6 +400,9 @@ class YAMLParser : public FileStorageParser

char* parseKey( char* ptr, FileNode& map_node, FileNode& value_placeholder )
{
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+
char c;
char *endptr = ptr - 1, *saveptr;

@@ -422,6 +431,9 @@ class YAMLParser : public FileStorageParser

char* parseValue( char* ptr, FileNode& node, int min_indent, bool is_parent_flow )
{
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+
char* endptr = 0;
char c = ptr[0], d = ptr[1];
int value_type = FileNode::NONE;
@@ -508,6 +520,8 @@ class YAMLParser : public FileStorageParser

*endptr = d;
ptr = skipSpaces( endptr, min_indent, INT_MAX );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");

c = *ptr;

@@ -634,6 +648,8 @@ class YAMLParser : public FileStorageParser
FileNode elem;

ptr = skipSpaces( ptr, new_min_indent, INT_MAX );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
if( *ptr == '}' || *ptr == ']' )
{
if( *ptr != d )
@@ -647,6 +663,8 @@ class YAMLParser : public FileStorageParser
if( *ptr != ',' )
CV_PARSE_ERROR_CPP( "Missing , between the elements" );
ptr = skipSpaces( ptr + 1, new_min_indent, INT_MAX );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
}

if( struct_type == FileNode::MAP )
@@ -746,6 +764,9 @@ class YAMLParser : public FileStorageParser

bool parse( char* ptr )
{
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+
bool first = true;
bool ok = true;
FileNode root_collection(fs->getFS(), 0, 0);

Loading

0 comments on commit 389757a

Please sign in to comment.