Package: spamprobe
Version: 1.4d-15
Severity: normal
Tags: patch upstream

Following the lack of reaction (upstream or here) to my previous bug
report (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1014201),
I tried to interface spamprobe to MySQL (MariaDB) myself.

While I got it somewhat working, I hit some performance problems
and a data corruption bug in MariaDB
(https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1015293),
so I'm deferring this project to a later time.

Anyway, in the process of doing so, I found some patches and had to
write some myself for some minor issues (nothing to do with MySQL)
that might be useful, e.g. when building spamprobe with newer
compiler versions.

Since upstream seems to be dead, the Debian package might be the
best place to keep the patches for anyone interested, so you might
want to include them.

Series:

warnings.patch
spamprobe.patch
strstream.patch
random.patch
Description: Fixing warnings (-Wall -Wno-deprecated)
Author: Mikhail T. (https://sourceforge.net/p/spamprobe/patches/9/)
Index: spamprobe-1.4d/src/includes/FrequencyDB.h
===================================================================
--- spamprobe-1.4d.orig/src/includes/FrequencyDB.h
+++ spamprobe-1.4d/src/includes/FrequencyDB.h
@@ -164,9 +164,9 @@ private:
 
 private:
   const DatabaseConfig *m_config;
-  Ptr<FrequencyDBImpl> m_db;
   bool m_isInterrupted;
   bool m_isBusy;
+  Ptr<FrequencyDBImpl> m_db;
 };
 
 #endif // _FrequencyDB_h
Index: spamprobe-1.4d/src/database/HashDataFile.h
===================================================================
--- spamprobe-1.4d.orig/src/database/HashDataFile.h
+++ spamprobe-1.4d/src/database/HashDataFile.h
@@ -93,7 +93,7 @@ public:
 
   bool isReadOnly() const
   {
-    m_isReadOnly;
+    return m_isReadOnly;
   }
 
   int createMode() const
Index: spamprobe-1.4d/src/includes/LRUCache.h
===================================================================
--- spamprobe-1.4d.orig/src/includes/LRUCache.h
+++ spamprobe-1.4d/src/includes/LRUCache.h
@@ -212,8 +212,8 @@ private:
 
 private:
   int m_maxSize;
-  int m_lockedCount;
   int m_normalCount;
+  int m_lockedCount;
   ListType m_normalList;
   ListType m_lockedList;
   MapType m_index;
Index: spamprobe-1.4d/src/includes/Ref.h
===================================================================
--- spamprobe-1.4d.orig/src/includes/Ref.h
+++ spamprobe-1.4d/src/includes/Ref.h
@@ -70,7 +70,7 @@ public:
 
 protected:
   RefBase()
-    : m_ptr(0), m_count(0)
+    : m_count(0), m_ptr(0)
   {
   }
 
Index: spamprobe-1.4d/src/database/FrequencyDBImpl_hash.cc
===================================================================
--- spamprobe-1.4d.orig/src/database/FrequencyDBImpl_hash.cc
+++ spamprobe-1.4d/src/database/FrequencyDBImpl_hash.cc
@@ -199,7 +199,7 @@ string FrequencyDBImpl_hash::getWordForI
     return FrequencyDB::COUNT_WORD;
   } else {
     char buffer[128];
-    sprintf(buffer, "I0x%08x", key);
+    sprintf(buffer, "I0x%08lx", key);
     return buffer;
   }
 }
@@ -210,7 +210,7 @@ HashDataFile::ulong_t FrequencyDBImpl_ha
   if (word == FrequencyDB::COUNT_WORD) {
     // key not used for count
   } else if (starts_with(word, "I0x")) {
-    sscanf(word.c_str() + 3, "%x", &key);
+    sscanf(word.c_str() + 3, "%lx", &key);
   } else {
     key = hash_string(word);
   }
Index: spamprobe-1.4d/src/database/HashDataFile.cc
===================================================================
--- spamprobe-1.4d.orig/src/database/HashDataFile.cc
+++ spamprobe-1.4d/src/database/HashDataFile.cc
@@ -122,7 +122,7 @@ void HashDataFile::populateEmptyFile(int
   unsigned char zeros[SIZE_MULTIPLE * WordArray::ENTRY_SIZE];
   WordArray::fillNullBuffer(zeros, SIZE_MULTIPLE);
 
-  for (int i = 0; i < m_indexLimit; i += SIZE_MULTIPLE) {
+  for (unsigned i = 0; i < m_indexLimit; i += SIZE_MULTIPLE) {
     ::write(fd, &zeros, min(m_indexLimit - i, (HashDataFile::ulong_t)SIZE_MULTIPLE) * WordArray::ENTRY_SIZE);
   }
 }
@@ -269,7 +269,7 @@ bool HashDataFile::write(ulong_t key,
   assert(m_base);
 
   int index = computeIndexForKey(key);
-  for (int i = 0; i < m_divisor; ++i) {
+  for (unsigned i = 0; i < m_divisor; ++i) {
     ulong_t old_key = m_array.readKey(index);
     if (old_key == key || old_key == 0) {
       m_array.writeWord(index, key, word_data);
@@ -310,7 +310,7 @@ bool HashDataFile::read(ulong_t key,
 
   ulong_t old_key = 0;
   int index = computeIndexForKey(key);
-  for (int i = 0; i < m_divisor; ++i) {
+  for (unsigned i = 0; i < m_divisor; ++i) {
     m_array.readWord(index, old_key, word_data);
     if (old_key == key) {
       // slot matches our key so return it's value
@@ -333,7 +333,7 @@ void HashDataFile::copyHeadersToFile(Has
 {
   ulong_t key = 0;
   WordData word_data;
-  for (int i = 0; i < m_numHeaders; ++i) {
+  for (unsigned i = 0; i < m_numHeaders; ++i) {
     readRecord(i, key, word_data);
     file.writeRecord(i, key, word_data);
   }
@@ -343,7 +343,7 @@ void HashDataFile::copyContentsToFile(Ha
 {
   ulong_t key = 0;
   WordData word_data;
-  for (int i = m_numHeaders; i < m_indexLimit; ++i) {
+  for (unsigned i = m_numHeaders; i < m_indexLimit; ++i) {
     readRecord(i, key, word_data);
     if (key != 0) {
       file.write(key, word_data);
Index: spamprobe-1.4d/src/database/Message.cc
===================================================================
--- spamprobe-1.4d.orig/src/database/Message.cc
+++ spamprobe-1.4d/src/database/Message.cc
@@ -115,7 +115,7 @@ void Message::addToken(const string &wor
   if (tok) {
     tok->incrementCount();
     m_tokensInOrder.push_back(tok);
-  } else if (m_maxTokenCount <= 0 || m_tokensByName.size() < m_maxTokenCount) {
+  } else if (m_maxTokenCount <= 0 || m_tokensByName.size() < (unsigned long)m_maxTokenCount) {
     tok = new Token(word, flags);
     m_tokensByIndex.push_back(tok);
     m_tokensByName.insert(make_pair(word, tok));
Index: spamprobe-1.4d/src/includes/Buffer.h
===================================================================
--- spamprobe-1.4d.orig/src/includes/Buffer.h
+++ spamprobe-1.4d/src/includes/Buffer.h
@@ -42,9 +42,9 @@ class Buffer
 {
 public:
   explicit Buffer(int capacity)
-    : m_length(0),
-      m_capacity(capacity),
-      m_ptr(new T[capacity])
+    : m_ptr(new T[capacity]),
+      m_length(0),
+      m_capacity(capacity)
   {
     assert(capacity > 0);
   }
Index: spamprobe-1.4d/src/input/SimpleMultiLineStringCharReader.cc
===================================================================
--- spamprobe-1.4d.orig/src/input/SimpleMultiLineStringCharReader.cc
+++ spamprobe-1.4d/src/input/SimpleMultiLineStringCharReader.cc
@@ -36,8 +36,8 @@ class SimpleMultiLineStringCharReaderPos
 public:
   SimpleMultiLineStringCharReaderPosition(const string *terminator,
                                           const AbstractMultiLineString *target)
-    : m_terminator(terminator),
-      m_target(target)
+    : m_target(target),
+      m_terminator(terminator)
   {
     assert(m_terminator);
     assert(m_target);
Index: spamprobe-1.4d/src/input/StringReader.cc
===================================================================
--- spamprobe-1.4d.orig/src/input/StringReader.cc
+++ spamprobe-1.4d/src/input/StringReader.cc
@@ -60,22 +60,22 @@ bool StringReader::forward()
 
 bool StringReader::hasChar()
 {
-    return m_index >= 0 && m_index < m_source.length();
+    return m_index >= 0 && (unsigned)m_index < m_source.length();
 }
 
 bool StringReader::skip(int nchars)
 {
     m_index += nchars;
-    if (m_index >= m_source.length()) {
+    if ((unsigned)m_index >= m_source.length()) {
         return false;
     }
     setCurrentChar(m_source[m_index]);
-    return m_index < m_source.length();
+    return (unsigned)m_index < m_source.length();
 }
 
 bool StringReader::atEnd()
 {
-    return m_index >= m_source.length();
+    return (unsigned)m_index >= m_source.length();
 }
 
 OWNED AbstractCharReaderPosition *StringReader::createMark()
Index: spamprobe-1.4d/src/parser/GifParser.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/GifParser.cc
+++ spamprobe-1.4d/src/parser/GifParser.cc
@@ -94,6 +94,7 @@ bool GifParser::parseImage()
   } catch (runtime_error &ex) {
     return false;
   }
+  return true;
 }
 
 void GifParser::openImage()
Index: spamprobe-1.4d/src/parser/MailMessage.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/MailMessage.cc
+++ spamprobe-1.4d/src/parser/MailMessage.cc
@@ -40,6 +40,7 @@
 
 static const string IS_HTML_REGEX("<!|</?html>|<p>|<br/?>|</?tr>|</?td>|</?font |</?b>|<a ");
 
+#if 0
 static void dump(MailMessage *msg)
 {
   cerr << "PARSING MESSAGE: " << endl;
@@ -50,6 +51,7 @@ static void dump(MailMessage *msg)
     cerr << "BODY: '" << msg->bodyText()->line(i) << "'" << endl;
   }
 }
+#endif
 
 MailMessage::MailMessage(const CRef<AbstractMultiLineString> &full_text)
   : m_fullText(full_text)
Index: spamprobe-1.4d/src/parser/MbxMailMessageReader.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/MbxMailMessageReader.cc
+++ spamprobe-1.4d/src/parser/MbxMailMessageReader.cc
@@ -54,8 +54,7 @@ MbxMailMessageReader::~MbxMailMessageRea
 
 bool MbxMailMessageReader::readMBXRecordHeader()
 {
-  bool again = true;
-  while (again) {
+  for (;;) {
     m_recordLength = 0;
     if (!reader()->hasLine()) {
       return false;
Index: spamprobe-1.4d/src/parser/MessageHeaderList.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/MessageHeaderList.cc
+++ spamprobe-1.4d/src/parser/MessageHeaderList.cc
@@ -39,7 +39,7 @@ static const string CONTENT_TYPE("conten
 CRef<AbstractMultiLineString> MessageHeaderList::header(const string &name) const
 {
     MultiLineStringList values;
-    for (int i = 0; i < m_headers.size(); ++i) {
+    for (unsigned i = 0; i < m_headers.size(); ++i) {
         if (m_headers[i]->hasName(name)) {
             values.push_back(m_headers[i]->lines());
         }
Index: spamprobe-1.4d/src/parser/MimeDecoder.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/MimeDecoder.cc
+++ spamprobe-1.4d/src/parser/MimeDecoder.cc
@@ -71,7 +71,7 @@ static const int BASE64_CHARS[256] = {
     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
 };
-static const int MAX_CHAR_INDEX = sizeof(BASE64_CHARS) / sizeof(BASE64_CHARS[0]);
+static const unsigned MAX_CHAR_INDEX = sizeof(BASE64_CHARS) / sizeof(BASE64_CHARS[0]);
 
 inline bool next_char64(AbstractCharReader *reader,
                         char &ch,
@@ -222,9 +222,9 @@ CRef<AbstractMultiLineString> MimeDecode
         bool add_new_line = true;
         const string &line(messageBody->line(k));
         const char *line_chars = line.c_str();
-        const int line_length = line.length();
-        const int last_index = line_length - 1;
-        const int hex_limit = line_length - 2;
+        const string::size_type line_length = line.length();
+        const string::size_type last_index = line_length - 1;
+        const string::size_type hex_limit = line_length - 2;
         for (string::size_type i = 0; i < line_length; ++i) {
             char ch = line_chars[i];
             if (ch == '=') {
Index: spamprobe-1.4d/src/parser/ParserConfig.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/ParserConfig.cc
+++ spamprobe-1.4d/src/parser/ParserConfig.cc
@@ -39,12 +39,12 @@ ParserConfig::ParserConfig()
     m_removeHTML(true),
     m_keepSuspiciousTags(false),
     m_ignoreBody(false),
+    m_spamprobeFieldName("x-spamprobe"),
     m_minPhraseTerms(1),
     m_maxPhraseTerms(2),
     m_minPhraseChars(0),
     m_maxPhraseChars(0),
-    m_maxTermsPerMessage(0),
-    m_spamprobeFieldName("x-spamprobe")
+    m_maxTermsPerMessage(0)
 {
 #ifdef USE_8BIT
     setReplaceNonAsciiChars(0);
Index: spamprobe-1.4d/src/parser/PhrasingTokenizer.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/PhrasingTokenizer.cc
+++ spamprobe-1.4d/src/parser/PhrasingTokenizer.cc
@@ -86,7 +86,7 @@ void PhrasingTokenizer::compactChars()
 void PhrasingTokenizer::receiveToken(const string &prefix,
                                      const string &token)
 {
-  while (m_offsets.size() >= m_maxWordsInList) {
+  while (m_offsets.size() >= (unsigned)m_maxWordsInList) {
     m_offsets.pop_back();
   }
   compactChars();
@@ -99,10 +99,10 @@ void PhrasingTokenizer::receiveToken(con
     assert(*i < m_chars.length());
     const char *phrase = m_chars.c_str() + *i;
     string::size_type phrase_length = m_chars.length() - *i;
-    if (m_maxCharLength > 0 && phrase_length > m_maxCharLength) {
+    if (m_maxCharLength > 0 && phrase_length > (string::size_type)m_maxCharLength) {
       break;
     }
-    if ((num_words > m_maxWords) && (m_minCharLength <= 0 || phrase_length > m_minCharLength)) {
+    if ((num_words > m_maxWords) && (m_minCharLength <= 0 || phrase_length > (string::size_type)m_minCharLength)) {
       break;
     }
     if (num_words >= m_minWords) {
Index: spamprobe-1.4d/src/parser/PngParser.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/PngParser.cc
+++ spamprobe-1.4d/src/parser/PngParser.cc
@@ -76,6 +76,7 @@ bool PngParser::parseImage()
   } catch (runtime_error &ex) {
     return false;
   }
+  return true;
 }
 
 void PngParser::initializeImage()
Index: spamprobe-1.4d/src/parser/TokenFilteringTokenizer.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/TokenFilteringTokenizer.cc
+++ spamprobe-1.4d/src/parser/TokenFilteringTokenizer.cc
@@ -37,7 +37,7 @@ TokenFilteringTokenizer::TokenFilteringT
                                                  int min_length,
                                                  int max_length,
                                                  bool allow_numbers)
-: m_tokenizer(tokenizer), m_minLength(min_length), m_maxLength(max_length), m_allowNumbers(allow_numbers)
+: m_minLength(min_length), m_maxLength(max_length), m_allowNumbers(allow_numbers), m_tokenizer(tokenizer)
 {
 }
 
@@ -48,11 +48,11 @@ TokenFilteringTokenizer::~TokenFiltering
 void TokenFilteringTokenizer::receiveToken(const string &prefix,
                                            const string &token)
 {
-    if (token.length() < m_minLength) {
+    if (token.length() < (unsigned)m_minLength) {
         return;
     }
 
-    if (token.length() > m_maxLength) {
+    if (token.length() > (unsigned)m_maxLength) {
         return;
     }
 
Index: spamprobe-1.4d/src/parser/TraditionalMailMessageParser.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/TraditionalMailMessageParser.cc
+++ spamprobe-1.4d/src/parser/TraditionalMailMessageParser.cc
@@ -54,8 +54,8 @@ static const string IP_ADDRESS_TERM("IP_
 static const string LINE_SEPARATOR(" ");
 
 TraditionalMailMessageParser::TraditionalMailMessageParser(ParserConfig *config)
-  : m_config(config),
-    m_ipRegex(IP_ADDRESS_REGEX)
+  : m_ipRegex(IP_ADDRESS_REGEX),
+    m_config(config)
 {
 }
 
Index: spamprobe-1.4d/src/utility/MD5Digester.cc
===================================================================
--- spamprobe-1.4d.orig/src/utility/MD5Digester.cc
+++ spamprobe-1.4d/src/utility/MD5Digester.cc
@@ -32,8 +32,8 @@
 #include "MD5Digester.h"
 
 MD5Digester::MD5Digester()
-  : m_running(false),
-    m_state(new md5_state_s)
+  : m_state(new md5_state_s),
+    m_running(false)
 {
 }
 
Index: spamprobe-1.4d/src/hdl/HdlStandardStatementConstraint.cc
===================================================================
--- spamprobe-1.4d.orig/src/hdl/HdlStandardStatementConstraint.cc
+++ spamprobe-1.4d/src/hdl/HdlStandardStatementConstraint.cc
@@ -63,7 +63,7 @@ void HdlStandardStatementConstraint::val
   }
 
   if (stmt->numArguments() > m_minArgCount) {
-    if (m_minArgCount > 0 && m_minArgCount >= m_arguments.size()) {
+    if (m_minArgCount > 0 && (unsigned)m_minArgCount >= m_arguments.size()) {
       cerr << "m_minArgCount: " << m_minArgCount << endl;
       cerr << "num_args " << m_arguments.size() << endl;
       throw HdlError("internal error: insufficient argument definitions", stmt->name());
Index: spamprobe-1.4d/src/hdl/HdlSyntaxChecker.cc
===================================================================
--- spamprobe-1.4d.orig/src/hdl/HdlSyntaxChecker.cc
+++ spamprobe-1.4d/src/hdl/HdlSyntaxChecker.cc
@@ -162,7 +162,6 @@ int HdlSyntaxChecker::parseArgs(const Re
 void HdlSyntaxChecker::parseTable(const Ref<HdlArgumentConstraint> &table,
                                   const CRef<HdlStatement> &stmt)
 {
-  int id_index = 0;
   for (int i = 0; i < stmt->numArguments(); ++i) {
     const CRef<HdlToken> &token = stmt->argument(i);
     if (token->strValue() == "string") {
Index: spamprobe-1.4d/src/spamprobe/AbstractMessageCommand.cc
===================================================================
--- spamprobe-1.4d.orig/src/spamprobe/AbstractMessageCommand.cc
+++ spamprobe-1.4d/src/spamprobe/AbstractMessageCommand.cc
@@ -74,7 +74,6 @@ void AbstractMessageCommand::processMail
                                                const File *stream_file,
                                                Ptr<AbstractMailMessageReader> &mail_reader)
 {
-  const CommandConfig *cmd_config = config.commandConfig();
   const ParserConfig *prs_config = config.parserConfig();
 
   TraditionalMailMessageParser parser(config.parserConfig());
Index: spamprobe-1.4d/src/spamprobe/Command_auto_train.cc
===================================================================
--- spamprobe-1.4d.orig/src/spamprobe/Command_auto_train.cc
+++ spamprobe-1.4d/src/spamprobe/Command_auto_train.cc
@@ -177,7 +177,6 @@ int Command_auto_train::execute(const Co
     spam_command = Command_spam::createTrainSpamCommand();
   }
 
-  bool is_message_spam = false;
   int message_num = 0;
 
   ParserConfig *parser_config = config.parserConfig();
@@ -186,7 +185,6 @@ int Command_auto_train::execute(const Co
   MailMessageDigester digester;
 
   AutoPurger purger(config, filter);
-  int cumulative_message_count = 0;
   Ptr<MailMessage> mail_message;
   mail_message.set(mail_reader->readMessage());
   while (mail_message.isNotNull()) {
@@ -198,7 +196,6 @@ int Command_auto_train::execute(const Co
       if (should_log) {
         score = filter.scoreMessage(*msg);
       }
-      bool scored_as_spam = should_log && filter.scoreMessage(*msg).isSpam();
       bool is_spam = mail_reader->messageWasSpam();
       if (should_log) {
         logMessage(config, filter, is_spam ? "SPAM" : "GOOD", score.isSpam() == is_spam, *msg);
Index: spamprobe-1.4d/src/spamprobe/FilterConfig.cc
===================================================================
--- spamprobe-1.4d.orig/src/spamprobe/FilterConfig.cc
+++ spamprobe-1.4d/src/spamprobe/FilterConfig.cc
@@ -32,8 +32,8 @@
 #include "FilterConfig.h"
 
 FilterConfig::FilterConfig()
-  : m_termsForScore(27),
-    m_defaultMinWordCount(5),
+  : m_defaultMinWordCount(5),
+    m_termsForScore(27),
     m_maxWordRepeats(2),
     m_extendTopTerms(false),
     m_newWordScore(0.3),
Description: spamprobe crashes when parsing jpeg mime attachment
Author: Torsten Hilbrich (https://sourceforge.net/p/spamprobe/bugs/39/)
Index: spamprobe-1.4d/src/parser/GifParser.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/GifParser.cc
+++ spamprobe-1.4d/src/parser/GifParser.cc
@@ -91,6 +91,7 @@ bool GifParser::parseImage()
     openImage();
     digestImage();
     parseImageRecords();
+    return true;
   } catch (runtime_error &ex) {
     return false;
   }
Index: spamprobe-1.4d/src/parser/JpegParser.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/JpegParser.cc
+++ spamprobe-1.4d/src/parser/JpegParser.cc
@@ -61,6 +61,7 @@ bool JpegParser::parseImage()
     initializeSource();
     digestImage();
     tokenizeImage();
+    return true;
   } catch (runtime_error &ex) {
     return false;
   }
Index: spamprobe-1.4d/src/parser/MbxMailMessageReader.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/MbxMailMessageReader.cc
+++ spamprobe-1.4d/src/parser/MbxMailMessageReader.cc
@@ -85,6 +85,7 @@ bool MbxMailMessageReader::readMBXRecord
       cerr << "MBX: SKIPPED DELETED MESSAGE" << endl;
     }
   }
+  return true;
 }
 
 OWNED MailMessage *MbxMailMessageReader::readMessage()
Index: spamprobe-1.4d/src/parser/PngParser.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/PngParser.cc
+++ spamprobe-1.4d/src/parser/PngParser.cc
@@ -73,6 +73,7 @@ bool PngParser::parseImage()
   try {
     digestImage();
     initializeImage();
+    return true;
   } catch (runtime_error &ex) {
     return false;
   }
Description: Avoid deprecated strstream
Author: Frank Heckenbach <f.heckenb...@fh-soft.de>
Index: spamprobe-1.4d/src/database/FrequencyDBImpl_bdb.cc
===================================================================
--- spamprobe-1.4d.orig/src/database/FrequencyDBImpl_bdb.cc
+++ spamprobe-1.4d/src/database/FrequencyDBImpl_bdb.cc
@@ -32,7 +32,7 @@
 
 #include <unistd.h>
 #include <stdexcept>
-#include <strstream>
+#include <sstream>
 #include "CleanupManager.h"
 #include "LockFile.h"
 #include "WordData.h"
@@ -67,10 +67,9 @@ inline int throw_on_error(const char *fu
     return rc;
   }
   if (rc != 0) {
-    static char buffer[4096];
-    ostrstream msg(buffer, sizeof(buffer));
+    ostringstream msg;
     msg << function_name << ": " << db_strerror(rc) << " (" << rc << ")" << ends;
-    throw runtime_error(buffer);
+    throw runtime_error(msg.str());
   }
   return rc;
 }
Index: spamprobe-1.4d/src/database/FrequencyDBImpl_pbl.cc
===================================================================
--- spamprobe-1.4d.orig/src/database/FrequencyDBImpl_pbl.cc
+++ spamprobe-1.4d/src/database/FrequencyDBImpl_pbl.cc
@@ -32,7 +32,7 @@
 
 #include <unistd.h>
 #include <fcntl.h>
-#include <strstream>
+#include <sstream>
 #include <stdexcept>
 #include "CleanupManager.h"
 #include "LockFile.h"
@@ -55,10 +55,9 @@ inline int throw_on_error(const char *fu
     return PBL_ERROR_NOT_FOUND;
   }
 
-  static char buffer[4096];
-  ostrstream msg(buffer, sizeof(buffer));
+  ostringstream msg;
   msg << function_name << ": " << pbl_errstr << " (" << pbl_errno << ")" << ends;
-  throw runtime_error(buffer);
+  throw runtime_error(msg.str());
 }
 
 inline int warn_on_error(const char *function_name,
Description: use reproducible pseudo-random numbers in AutoTrainMailMessageReader
Author: Frank Heckenbach <f.heckenb...@fh-soft.de>
Index: spamprobe-1.4d/src/parser/AutoTrainMailMessageReader.cc
===================================================================
--- spamprobe-1.4d.orig/src/parser/AutoTrainMailMessageReader.cc
+++ spamprobe-1.4d/src/parser/AutoTrainMailMessageReader.cc
@@ -29,6 +29,7 @@
 //
 
 #include <cstdlib>
+#include <random>
 #include "MailMessage.h"
 #include "AutoTrainMailMessageReader.h"
 
@@ -140,5 +141,15 @@ OWNED MailMessage *AutoTrainMailMessageR
 
 bool AutoTrainMailMessageReader::shouldUseSpam()
 {
-  return (m_totalCount >= 0) && ((random() % m_totalCount) < m_spamCount);
+  /* The original code uses "random" here without seeding it.
+     But some DB backends (e.g. BDB) seed the PRNG internally.
+     This gives the worst of both worlds: No real randomness,
+     yet different results with different backends which makes
+     it hard to compare them for performance or correctness.
+     Now, this uses a separate PRNG and leaves it unseeded,
+     to make results comparable, at the cost of no real
+     randomness which does not seem so important here. */
+  static mt19937 PRNG;
+  uniform_int_distribution<mt19937::result_type> dist(0, m_totalCount - 1);
+  return (m_totalCount >= 0) && (dist(PRNG) < m_spamCount);
 }

Reply via email to