Skip to content

Commit

Permalink
Fix out-of-bounds writes in Classify::ReadNewCutoffs
Browse files Browse the repository at this point in the history
The function did not correctly read Chinese unichars into the local
Class variable if the locale was set to de_DE.UTF-8 (or other
incompatible locales). That resulted in a wrong ClassId which was
used to write into the Cutoffs array without checking for valid bounds.

On macOS the result was a runtime error in baseapi_test (see GitHub
issue #1250):

    [ RUN      ] TesseractTest.InitConfigOnlyTest
    baseapi_test(21845,0x1134c45c0) malloc: *** error for object 0x927f96c28005e0: pointer being freed was not allocated
    baseapi_test(21845,0x1134c45c0) malloc: *** set a breakpoint in malloc_error_break to debug

Replacing sscanf by std::istringstream fixes that.
Add also an assertion to catch future out-of-bounds writes.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
  • Loading branch information
stweil committed May 18, 2019
1 parent 4763f24 commit 3452c8e
Showing 1 changed file with 13 additions and 7 deletions.
20 changes: 13 additions & 7 deletions src/classify/cutoffs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "cutoffs.h"

#include <cstdio>
#include <sstream> // for std::istringstream
#include <string> // for std::string

#include "classify.h"
#include "helpers.h"
Expand All @@ -40,8 +42,6 @@ namespace tesseract {
* @param Cutoffs array to put cutoffs into
*/
void Classify::ReadNewCutoffs(TFile* fp, CLASS_CUTOFF_ARRAY Cutoffs) {
char Class[UNICHAR_LEN + 1];
CLASS_ID ClassId;
int Cutoff;

if (shape_table_ != nullptr) {
Expand All @@ -54,14 +54,20 @@ void Classify::ReadNewCutoffs(TFile* fp, CLASS_CUTOFF_ARRAY Cutoffs) {

const int kMaxLineSize = 100;
char line[kMaxLineSize];
while (fp->FGets(line, kMaxLineSize) != nullptr &&
sscanf(line, "%" REALLY_QUOTE_IT(UNICHAR_LEN) "s %d", Class,
&Cutoff) == 2) {
if (strcmp(Class, "NULL") == 0) {
while (fp->FGets(line, kMaxLineSize) != nullptr) {
std::string Class;
CLASS_ID ClassId;
std::istringstream stream(line);
stream >> Class >> Cutoff;
if (stream.fail()) {
break;
}
if (Class.compare("NULL") == 0) {
ClassId = unicharset.unichar_to_id(" ");
} else {
ClassId = unicharset.unichar_to_id(Class);
ClassId = unicharset.unichar_to_id(Class.c_str());
}
ASSERT_HOST(ClassId >= 0 && ClassId < MAX_NUM_CLASSES);
Cutoffs[ClassId] = Cutoff;
}
}
Expand Down

0 comments on commit 3452c8e

Please sign in to comment.