Commit e6f09a37 for tesseract
commit e6f09a3772eb5938df7a042de406506e9f53ed03
Author: Stefan Weil <sw@weilnetz.de>
Date: Fri Nov 13 17:30:40 2026 +0100
dawg: limit the number of positions in a DawgPositionVector
add_unique() searches the vector linearly, and nothing limited its
size. With dawgs which accept every string, the number of distinct
positions grows with the square of the word length, and the
recognition of a page took minutes.
Keep at most 256 positions. Real dictionaries only need a few.
Fix proposed by the Anthropic OSS Scanner (finding ANT-2026-Q7Q3JVSG).
Assisted-by: OpenCode / Claude Fable 5.2 (Anthropic)
Signed-off-by: Stefan Weil <sw@weilnetz.de>
diff --git a/src/dict/dawg.h b/src/dict/dawg.h
index 1453e284..b56db39d 100644
--- a/src/dict/dawg.h
+++ b/src/dict/dawg.h
@@ -375,11 +375,24 @@ struct DawgPosition {
class DawgPositionVector : public std::vector<DawgPosition> {
public:
+ /// Hard upper bound on the number of positions kept for one word.
+ /// Real dictionaries only ever need a handful, but a crafted set of dawgs
+ /// (every node accepting every unichar, with pattern and end-of-word edges
+ /// everywhere) makes the number of distinct positions grow with the square
+ /// of the word length, and add_unique() is linear in it.
+ static constexpr size_t kMaxPositions = 256;
+
/// Adds an entry for the given dawg_index with the given node to the vec.
- /// Returns false if the same entry already exists in the vector,
- /// true otherwise.
+ /// Returns false if the same entry already exists in the vector or if
+ /// kMaxPositions has been reached, true otherwise.
inline bool add_unique(const DawgPosition &new_pos, bool debug,
const char *debug_msg) {
+ if (size() >= kMaxPositions) {
+ if (debug) {
+ tprintf("%sdropped, too many dawg positions\n", debug_msg);
+ }
+ return false;
+ }
for (auto &&position : *this) {
if (position == new_pos) {
return false;