Skip to content

Commit cf93424

Browse files
authored
added engine to rule XML to specify regex engine (danmar#8383)
1 parent d2f98f3 commit cf93424

File tree

10 files changed

+256
-196
lines changed

10 files changed

+256
-196
lines changed

.github/workflows/valgrind.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
- name: Run valgrind
5252
run: |
5353
ec=0
54-
valgrind --error-limit=yes --leak-check=full --num-callers=50 --show-reachable=yes --track-origins=yes --suppressions=valgrind/testrunner.supp --gen-suppressions=all -s --log-fd=9 --error-exitcode=42 ./testrunner TestGarbage TestOther TestSimplifyTemplate TestRegEx 9>memcheck.log || ec=1
54+
valgrind --error-limit=yes --leak-check=full --num-callers=50 --show-reachable=yes --track-origins=yes --suppressions=valgrind/testrunner.supp --gen-suppressions=all -s --log-fd=9 --error-exitcode=42 ./testrunner TestGarbage TestOther TestSimplifyTemplate TestRegExPcre 9>memcheck.log || ec=1
5555
cat memcheck.log
5656
exit $ec
5757
# TODO: debuginfod.ubuntu.com is currently not responding to any requests causing it to run into a 40(!) minute timeout

Makefile

Lines changed: 129 additions & 129 deletions
Large diffs are not rendered by default.

cli/cmdlineparser.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,7 +1294,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
12941294
}
12951295

12961296
std::string regex_err;
1297-
auto regex = Regex::create(rule.pattern, regex_err);
1297+
auto regex = Regex::create(rule.pattern, Regex::Engine::Pcre, regex_err);
12981298
if (!regex) {
12991299
mLogger.printError("failed to compile rule pattern '" + rule.pattern + "' (" + regex_err + ").");
13001300
return Result::Fail;
@@ -1351,6 +1351,16 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
13511351
}
13521352
}
13531353
}
1354+
else if (std::strcmp(subname, "engine") == 0) {
1355+
const char * const engine = empty_if_null(subtext);
1356+
if (std::strcmp(engine, "pcre") == 0) {
1357+
rule.engine = Regex::Engine::Pcre;
1358+
}
1359+
else {
1360+
mLogger.printError(std::string("unknown regex engine '") + engine + "'.");
1361+
return Result::Fail;
1362+
}
1363+
}
13541364
else {
13551365
mLogger.printError("unable to load rule-file '" + ruleFile + "' - unknown element '" + subname + "' encountered in 'rule'.");
13561366
return Result::Fail;
@@ -1378,7 +1388,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
13781388
}
13791389

13801390
std::string regex_err;
1381-
auto regex = Regex::create(rule.pattern, regex_err);
1391+
auto regex = Regex::create(rule.pattern, rule.engine, regex_err);
13821392
if (!regex) {
13831393
mLogger.printError("unable to load rule-file '" + ruleFile + "' - pattern '" + rule.pattern + "' failed to compile (" + regex_err + ").");
13841394
return Result::Fail;

lib/regex.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,15 +188,15 @@ namespace {
188188
std::string PcreRegex::compile()
189189
{
190190
if (mRe)
191-
return "pcre_compile failed: regular expression has already been compiled";
191+
return "regular expression has already been compiled";
192192

193193
const char *pcreCompileErrorStr = nullptr;
194194
int erroffset = 0;
195195
pcre * const re = pcre_compile(mPattern.c_str(),0,&pcreCompileErrorStr,&erroffset,nullptr);
196196
if (!re) {
197197
if (pcreCompileErrorStr)
198-
return "pcre_compile failed: " + std::string(pcreCompileErrorStr);
199-
return "pcre_compile failed: unknown error";
198+
return pcreCompileErrorStr;
199+
return "unknown error";
200200
}
201201

202202
// Optimize the regex, but only if PCRE_CONFIG_JIT is available
@@ -209,7 +209,7 @@ namespace {
209209
if (pcreStudyErrorStr) {
210210
// pcre_compile() worked, but pcre_study() returned an error. Free the resources allocated by pcre_compile().
211211
pcre_free(re);
212-
return "pcre_study failed: " + std::string(pcreStudyErrorStr);
212+
return std::string(pcreStudyErrorStr) + " (pcre_study)";
213213
}
214214
mExtra = pcreExtra;
215215
#endif
@@ -222,7 +222,7 @@ namespace {
222222
std::string PcreRegex::match(const std::string& str, const MatchFn& match) const
223223
{
224224
if (!mRe)
225-
return "pcre_exec failed: regular expression has not been compiled yet";
225+
return "regular expression has not been compiled yet";
226226

227227
int pos = 0;
228228
int ovector[30]= {0};
@@ -231,7 +231,7 @@ namespace {
231231
if (pcreExecRet == PCRE_ERROR_NOMATCH)
232232
return "";
233233
if (pcreExecRet < 0) {
234-
return "pcre_exec failed (pos: " + std::to_string(pos) + "): " + pcreErrorCodeToString(pcreExecRet);
234+
return pcreErrorCodeToString(pcreExecRet) + " (pos: " + std::to_string(pos) + ")";
235235
}
236236
const auto pos1 = static_cast<unsigned int>(ovector[0]);
237237
const auto pos2 = static_cast<unsigned int>(ovector[1]);
@@ -246,10 +246,22 @@ namespace {
246246
}
247247
}
248248

249-
std::shared_ptr<Regex> Regex::create(std::string pattern, std::string& err)
249+
template<typename T>
250+
static T* createAndCompileRegex(std::string pattern, std::string& err)
250251
{
251-
auto* regex = new PcreRegex(std::move(pattern));
252+
T* regex = new T(std::move(pattern));
252253
err = regex->compile();
254+
return regex;
255+
}
256+
257+
std::shared_ptr<Regex> Regex::create(std::string pattern, Engine engine, std::string& err)
258+
{
259+
Regex* regex = nullptr;
260+
if (engine == Engine::Pcre)
261+
regex = createAndCompileRegex<PcreRegex>(std::move(pattern), err);
262+
else {
263+
err = "unknown regular expression engine";
264+
}
253265
if (!err.empty()) {
254266
delete regex;
255267
return nullptr;

lib/regex.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "config.h"
2727

28+
#include <cstdint>
2829
#include <functional>
2930
#include <memory>
3031
#include <string>
@@ -37,7 +38,13 @@ class CPPCHECKLIB Regex
3738
using MatchFn = std::function<void (int start, int end)>;
3839
virtual std::string match(const std::string& str, const MatchFn& matchFn) const = 0;
3940

40-
static std::shared_ptr<Regex> create(std::string pattern, std::string& err);
41+
enum class Engine : std::uint8_t
42+
{
43+
Unknown = 0,
44+
Pcre = 1
45+
};
46+
47+
static std::shared_ptr<Regex> create(std::string pattern, Engine engine, std::string& err);
4148
};
4249

4350
#endif // HAVE_RULES

lib/settings.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
#include <unordered_set>
4141
#include <utility>
4242

43+
#include "regex.h"
44+
4345
#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
4446
#include <cstdio>
4547
#endif
@@ -371,6 +373,7 @@ class CPPCHECKLIB WARN_UNUSED Settings {
371373
std::string id = "rule"; // default id
372374
std::string summary;
373375
Severity severity = Severity::style; // default severity
376+
Regex::Engine engine = Regex::Engine::Pcre;
374377
std::shared_ptr<Regex> regex;
375378
};
376379

0 commit comments

Comments
 (0)