Skip to content

Commit 09edd1a

Browse files
committed
Fix out-of-bounds writes in Classify::ReadNewCutoffs
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 <[email protected]>
1 parent 639781b commit 09edd1a

File tree

1 file changed

+13
-7
lines changed

1 file changed

+13
-7
lines changed

src/classify/cutoffs.cpp

+13-7
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "cutoffs.h"
2121

2222
#include <cstdio>
23+
#include <sstream> // for std::istringstream
24+
#include <string> // for std::string
2325

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

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

5555
const int kMaxLineSize = 100;
5656
char line[kMaxLineSize];
57-
while (fp->FGets(line, kMaxLineSize) != nullptr &&
58-
sscanf(line, "%" REALLY_QUOTE_IT(UNICHAR_LEN) "s %d", Class,
59-
&Cutoff) == 2) {
60-
if (strcmp(Class, "NULL") == 0) {
57+
while (fp->FGets(line, kMaxLineSize) != nullptr) {
58+
std::string Class;
59+
CLASS_ID ClassId;
60+
std::istringstream stream(line);
61+
stream >> Class >> Cutoff;
62+
if (stream.fail()) {
63+
break;
64+
}
65+
if (Class.compare("NULL") == 0) {
6166
ClassId = unicharset.unichar_to_id(" ");
6267
} else {
63-
ClassId = unicharset.unichar_to_id(Class);
68+
ClassId = unicharset.unichar_to_id(Class.c_str());
6469
}
70+
ASSERT_HOST(ClassId >= 0 && ClassId < MAX_NUM_CLASSES);
6571
Cutoffs[ClassId] = Cutoff;
6672
}
6773
}

0 commit comments

Comments
 (0)