From 4b35701a31092e25e5226205d550dc294737a69a Mon Sep 17 00:00:00 2001 From: Alexander Lohnau Date: Mon, 25 Jul 2022 15:05:29 +0000 Subject: [PATCH] runners/calculator: Do not show results when expression is invalid See https://github.com/Qalculate/libqalculate/issues/442 for the code snippets. I have only adjusted those to compile inside of the plugin. BUG: 454132 --- .../autotests/calculatorrunnertest.cpp | 7 ++++ runners/calculator/qalculate_engine.cpp | 40 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/runners/calculator/autotests/calculatorrunnertest.cpp b/runners/calculator/autotests/calculatorrunnertest.cpp index 21133efe3..d222d3107 100644 --- a/runners/calculator/autotests/calculatorrunnertest.cpp +++ b/runners/calculator/autotests/calculatorrunnertest.cpp @@ -18,6 +18,7 @@ private Q_SLOTS: void test42(); void testApproximation(); void testQuery_data(); + void testErrorDetection(); }; void CalculatorRunnerTest::initTestCase() @@ -83,6 +84,12 @@ void CalculatorRunnerTest::test42() QCOMPARE(manager->matches().constFirst().text(), "42"); } +void CalculatorRunnerTest::testErrorDetection() +{ + launchQuery("SDL_VIDEODRIVER="); + QVERIFY(manager->matches().isEmpty()); +} + QTEST_MAIN(CalculatorRunnerTest) #include "calculatorrunnertest.moc" diff --git a/runners/calculator/qalculate_engine.cpp b/runners/calculator/qalculate_engine.cpp index aaa34a217..6e369abe2 100644 --- a/runners/calculator/qalculate_engine.cpp +++ b/runners/calculator/qalculate_engine.cpp @@ -65,6 +65,42 @@ void QalculateEngine::updateResult(KJob *job) } } +bool has_error() +{ + while (CALCULATOR->message()) { + if (CALCULATOR->message()->type() == MESSAGE_ERROR) { + CALCULATOR->clearMessages(); + return true; + } + CALCULATOR->nextMessage(); + } + return false; +} + +bool check_valid_before(const std::string &expression, const EvaluationOptions &search_eo) +{ + bool b_valid = false; + if (!b_valid) + b_valid = (expression.find_first_of(OPERATORS NUMBERS PARENTHESISS) != std::string::npos); + if (!b_valid) + b_valid = CALCULATOR->hasToExpression(expression, false, search_eo); + if (!b_valid) { + std::string str = expression; + CALCULATOR->parseSigns(str); + b_valid = (str.find_first_of(OPERATORS NUMBERS PARENTHESISS) != std::string::npos); + if (!b_valid) { + size_t i = str.find_first_of(SPACES); + MathStructure m; + if (!b_valid) { + CALCULATOR->parse(&m, str, search_eo.parse_options); + if (!has_error() && (m.isUnit() || m.isFunction() || (m.isVariable() && (i != std::string::npos || m.variable()->isKnown())))) + b_valid = true; + } + } + } + return b_valid; +} + QString QalculateEngine::evaluate(const QString &expression, bool *isApproximate) { if (expression.isEmpty()) { @@ -89,6 +125,10 @@ QString QalculateEngine::evaluate(const QString &expression, bool *isApproximate // to avoid memory overflow for seemingly innocent calculations (Bug 277011) eo.approximation = APPROXIMATION_APPROXIMATE; + if (!check_valid_before(expression.toStdString(), eo)) { + return QString(); // See https://github.com/Qalculate/libqalculate/issues/442 + } + CALCULATOR->setPrecision(16); MathStructure result = CALCULATOR->calculate(ctext, eo);