summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Uwe Broulik <kde@privat.broulik.de>2017-03-27 16:57:39 (GMT)
committerKai Uwe Broulik <kde@privat.broulik.de>2017-03-28 08:26:58 (GMT)
commit34b74d7b5dac9dd458a960e392954ac6c30df3d2 (patch)
tree89bdabcc134d8687f3c85d683b65da993489b43f
parent37ac27c59d97db3bb173ae1786a639cce0c6feb6 (diff)
[Calculator Runner] Use "approximate" approximation mode
The runner calculator isn't entitled for being a scientifically correct calculator. This keeps seemingly innocent calculations such as "2^0.333333333" from eating all RAM until it crashes. A hint is added to the result if it is only an approximation. BUG: 277011 FIXED-IN: 5.8.7 CCMAIL: kde-i18n-doc@kde.org Differential Revision: https://phabricator.kde.org/D4290 (cherry picked from commit df7f1ed1eb7df7e3c039dc19db4893ca01b3327f)
-rw-r--r--runners/calculator/calculatorrunner.cpp10
-rw-r--r--runners/calculator/calculatorrunner.h2
-rw-r--r--runners/calculator/qalculate_engine.cpp10
-rw-r--r--runners/calculator/qalculate_engine.h2
4 files changed, 18 insertions, 6 deletions
diff --git a/runners/calculator/calculatorrunner.cpp b/runners/calculator/calculatorrunner.cpp
index f9552d2..86111c9 100644
--- a/runners/calculator/calculatorrunner.cpp
+++ b/runners/calculator/calculatorrunner.cpp
@@ -258,7 +258,8 @@ void CalculatorRunner::match(Plasma::RunnerContext &context)
cmd.replace(QRegExp(QStringLiteral("([a-zA-Z]+)")), QStringLiteral("Math.\\1")); //needed for accessing math funktions like sin(),....
#endif
- QString result = calculate(cmd);
+ bool isApproximate = false;
+ QString result = calculate(cmd, &isApproximate);
if (!result.isEmpty() && result != cmd) {
if (toHex) {
result = "0x" + QString::number(result.toInt(), 16).toUpper();
@@ -268,19 +269,22 @@ void CalculatorRunner::match(Plasma::RunnerContext &context)
match.setType(Plasma::QueryMatch::InformationalMatch);
match.setIconName(QStringLiteral("accessories-calculator"));
match.setText(result);
+ if (isApproximate) {
+ match.setSubtext(i18nc("The result of the calculation is only an approximation", "Approximation"));
+ }
match.setData(result);
match.setId(term);
context.addMatch(match);
}
}
-QString CalculatorRunner::calculate(const QString& term)
+QString CalculatorRunner::calculate(const QString& term, bool *isApproximate)
{
#ifdef ENABLE_QALCULATE
QString result;
try {
- result = m_engine->evaluate(term);
+ result = m_engine->evaluate(term, isApproximate);
} catch(std::exception& e) {
qDebug() << "qalculate error: " << e.what();
}
diff --git a/runners/calculator/calculatorrunner.h b/runners/calculator/calculatorrunner.h
index f14de4d..9ab1a86 100644
--- a/runners/calculator/calculatorrunner.h
+++ b/runners/calculator/calculatorrunner.h
@@ -47,7 +47,7 @@ class CalculatorRunner : public Plasma::AbstractRunner
QMimeData * mimeDataForMatch(const Plasma::QueryMatch &match) override;
private:
- QString calculate(const QString& term);
+ QString calculate(const QString& term, bool *isApproximate);
void userFriendlySubstitutions(QString& cmd);
void powSubstitutions(QString& cmd);
void hexSubstitutions(QString& cmd);
diff --git a/runners/calculator/qalculate_engine.cpp b/runners/calculator/qalculate_engine.cpp
index f47cee7..39a3e67 100644
--- a/runners/calculator/qalculate_engine.cpp
+++ b/runners/calculator/qalculate_engine.cpp
@@ -79,7 +79,7 @@ void QalculateEngine::updateResult(KJob* job)
}
}
-QString QalculateEngine::evaluate(const QString& expression)
+QString QalculateEngine::evaluate(const QString& expression, bool *isApproximate)
{
if (expression.isEmpty()) {
return "";
@@ -98,6 +98,10 @@ QString QalculateEngine::evaluate(const QString& expression)
eo.parse_options.angle_unit = ANGLE_UNIT_RADIANS;
eo.structuring = STRUCTURING_SIMPLIFY;
+ // suggested in https://github.com/Qalculate/libqalculate/issues/16
+ // to avoid memory overflow for seemingly innocent calculations (Bug 277011)
+ eo.approximation = APPROXIMATION_APPROXIMATE;
+
CALCULATOR->setPrecision(16);
MathStructure result = CALCULATOR->calculate(ctext, eo);
@@ -114,6 +118,10 @@ QString QalculateEngine::evaluate(const QString& expression)
m_lastResult = result.print(po).c_str();
+ if (isApproximate) {
+ *isApproximate = result.isApproximate();
+ }
+
return m_lastResult;
}
diff --git a/runners/calculator/qalculate_engine.h b/runners/calculator/qalculate_engine.h
index 5fd8887..5bdff27 100644
--- a/runners/calculator/qalculate_engine.h
+++ b/runners/calculator/qalculate_engine.h
@@ -35,7 +35,7 @@ public:
QString lastResult() const { return m_lastResult; }
public Q_SLOTS:
- QString evaluate(const QString& expression);
+ QString evaluate(const QString& expression, bool *isApproximate = nullptr);
void updateExchangeRates();
void copyToClipboard(bool flag = true);