From 44a6d9f4d4762bcda54bffea8a49005342e96ca3 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sun, 24 Mar 2019 17:27:43 +0100 Subject: [PATCH] intmatcher: Catch more out of bounds reads Credit to OSS-Fuzz which reported this issue: intmatcher.cpp:1121:17: runtime error: index 24 out of bounds for type 'uint8_t [24]' #0 0x61034b in ScratchEvidence::UpdateSumOfProtoEvidences(INT_CLASS_STRUCT*, unsigned int*, short) tesseract/src/classify/intmatcher.cpp:1121:17 #1 0x60f560 in IntegerMatcher::Match(INT_CLASS_STRUCT*, unsigned int*, unsigned int*, short, INT_FEATURE_STRUCT const*, tesseract::UnicharRating*, int, int, bool) tesseract/src/classify/intmatcher.cpp:514:11 #2 0x5f3a25 in tesseract::Classify::AdaptToChar(TBLOB*, int, int, float, ADAPT_TEMPLATES_STRUCT*) tesseract/src/classify/adaptmatch.cpp:894:9 #3 0x5f2ccd in tesseract::Classify::LearnPieces(char const*, int, int, float, tesseract::CharSegmentationType, char const*, WERD_RES*) tesseract/src/classify/adaptmatch.cpp:430:5 #4 0x5f16ee in tesseract::Classify::LearnWord(char const*, WERD_RES*) tesseract/src/classify/adaptmatch.cpp:293:7 This catches the out of bounds data reads in release builds. Add also assertions for debug builds. See https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=13818. Signed-off-by: Stefan Weil --- src/classify/intmatcher.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/classify/intmatcher.cpp b/src/classify/intmatcher.cpp index 4f93d39d61..55367f74a6 100644 --- a/src/classify/intmatcher.cpp +++ b/src/classify/intmatcher.cpp @@ -24,6 +24,8 @@ ----------------------------------------------------------------------------*/ #include "intmatcher.h" +#include +#include #include "fontinfo.h" #include "intproto.h" #include "callcpp.h" @@ -32,7 +34,6 @@ #include "helpers.h" #include "classify.h" #include "shapetable.h" -#include using tesseract::ScoredFont; using tesseract::UnicharRating; @@ -680,7 +681,8 @@ int IntegerMatcher::FindBadFeatures( /* Find Best Evidence for Current Feature */ int best = 0; - for (int i = 0; i < ClassTemplate->NumConfigs; i++) + assert(ClassTemplate->NumConfigs < MAX_NUM_CONFIGS); + for (int i = 0; i < MAX_NUM_CONFIGS && i < ClassTemplate->NumConfigs; i++) if (tables->feature_evidence_[i] > best) best = tables->feature_evidence_[i]; @@ -1111,7 +1113,8 @@ void IntegerMatcher::DisplayFeatureDebugInfo( /* Find Best Evidence for Current Feature */ int best = 0; - for (int i = 0; i < ClassTemplate->NumConfigs; i++) + assert(ClassTemplate->NumConfigs < MAX_NUM_CONFIGS); + for (int i = 0; i < MAX_NUM_CONFIGS && i < ClassTemplate->NumConfigs; i++) if (tables->feature_evidence_[i] > best) best = tables->feature_evidence_[i]; @@ -1154,6 +1157,7 @@ void ScratchEvidence::UpdateSumOfProtoEvidences( ((ProtoNum < PROTOS_PER_PROTO_SET) && (ActualProtoNum < NumProtos)); ProtoNum++, ActualProtoNum++) { int temp = 0; + assert(ClassTemplate->ProtoLengths[ActualProtoNum] < MAX_PROTO_INDEX); for (uint8_t i = 0; i < MAX_PROTO_INDEX && i < ClassTemplate->ProtoLengths[ActualProtoNum]; i++) temp += proto_evidence_[ActualProtoNum] [i]; @@ -1178,7 +1182,8 @@ void ScratchEvidence::UpdateSumOfProtoEvidences( void ScratchEvidence::NormalizeSums( INT_CLASS ClassTemplate, int16_t NumFeatures) { - for (int i = 0; i < ClassTemplate->NumConfigs; i++) { + assert(ClassTemplate->NumConfigs < MAX_NUM_CONFIGS); + for (int i = 0; i < MAX_NUM_CONFIGS && i < ClassTemplate->NumConfigs; i++) { sum_feature_evidence_[i] = (sum_feature_evidence_[i] << 8) / (NumFeatures + ClassTemplate->ConfigLengths[i]); } @@ -1199,7 +1204,8 @@ int IntegerMatcher::FindBestMatch( result->fonts.reserve(class_template->NumConfigs); /* Find best match */ - for (int c = 0; c < class_template->NumConfigs; ++c) { + assert(class_template->NumConfigs < MAX_NUM_CONFIGS); + for (int c = 0; c < MAX_NUM_CONFIGS && c < class_template->NumConfigs; ++c) { int rating = tables.sum_feature_evidence_[c]; if (*classify_debug_level_ > 2) tprintf("Config %d, rating=%d\n", c, rating);