Localization: make cache thread safe and robust against use-after-free

The old trGettext() was not thread-safe and the returned C-strings
could be freed in the case of empty translations strings. Therefore:

1) Introduce a mutex protecting access to the cache.

2) Never change existing entries, even if the translation string is empty.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2018-06-17 23:28:44 +02:00 committed by Tomaz Canabrava
parent 879cb73b8b
commit db0dd54c37
2 changed files with 9 additions and 4 deletions

View file

@ -1,13 +1,17 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include "gettextfromc.h" #include "gettextfromc.h"
#include <QHash> #include <QHash>
#include <QMutex>
static QHash<QByteArray, QByteArray> translationCache; static QHash<QByteArray, QByteArray> translationCache;
static QMutex lock;
extern "C" const char *trGettext(const char *text) extern "C" const char *trGettext(const char *text)
{ {
QByteArray &result = translationCache[QByteArray(text)]; QByteArray key(text);
if (result.isEmpty()) QMutexLocker l(&lock);
result = gettextFromC::tr(text).toUtf8(); auto it = translationCache.find(key);
return result.constData(); if (it == translationCache.end())
it = translationCache.insert(key, gettextFromC::tr(text).toUtf8());
return it->constData();
} }

View file

@ -14,6 +14,7 @@
#include <QToolBar> #include <QToolBar>
#include <QStatusBar> #include <QStatusBar>
#include "core/gettextfromc.h"
#include "core/version.h" #include "core/version.h"
#include "core/subsurface-string.h" #include "core/subsurface-string.h"
#include "desktop-widgets/divelistview.h" #include "desktop-widgets/divelistview.h"