Skip to content

Commit e7aca53

Browse files
committed
access_control: use Regex instead of pcre
Updates the access_control plugin to use tsutil Regex instead of pcre.
1 parent 28878f7 commit e7aca53

File tree

3 files changed

+32
-95
lines changed

3 files changed

+32
-95
lines changed

plugins/experimental/access_control/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ add_atsplugin(
2828
utils.cc
2929
)
3030

31-
target_link_libraries(access_control PRIVATE OpenSSL::SSL OpenSSL::Crypto PCRE::PCRE)
31+
target_link_libraries(access_control PRIVATE OpenSSL::SSL OpenSSL::Crypto)
3232

3333
verify_remap_plugin(access_control)
3434

plugins/experimental/access_control/pattern.cc

Lines changed: 26 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
#include "pattern.h"
2626

27+
#include <tsutil/Regex.h>
28+
2729
static void
2830
replaceString(String &str, const String &from, const String &to)
2931
{
@@ -40,6 +42,8 @@ replaceString(String &str, const String &from, const String &to)
4042

4143
Pattern::Pattern() : _pattern(""), _replacement("") {}
4244

45+
Pattern::~Pattern() = default;
46+
4347
/**
4448
* @brief Initializes PCRE pattern by providing the subject and replacement strings.
4549
* @param pattern PCRE pattern, a string containing PCRE patterns, capturing groups.
@@ -49,8 +53,6 @@ Pattern::Pattern() : _pattern(""), _replacement("") {}
4953
bool
5054
Pattern::init(const String &pattern, const String &replacement, bool replace)
5155
{
52-
pcreFree();
53-
5456
_pattern.assign(pattern);
5557
_replacement.assign(replacement);
5658
_replace = replace;
@@ -59,7 +61,7 @@ Pattern::init(const String &pattern, const String &replacement, bool replace)
5961

6062
if (!compile()) {
6163
AccessControlDebug("failed to initialize pattern:'%s', replacement:'%s'", pattern.c_str(), replacement.c_str());
62-
pcreFree();
64+
_re.reset();
6365
return false;
6466
}
6567

@@ -139,33 +141,12 @@ Pattern::getPattern()
139141
bool
140142
Pattern::empty() const
141143
{
142-
return _pattern.empty() || nullptr == _re;
143-
}
144-
145-
/**
146-
* @brief Frees PCRE library related resources.
147-
*/
148-
void
149-
Pattern::pcreFree()
150-
{
151-
if (_re) {
152-
pcre_free(_re);
153-
_re = nullptr;
154-
}
155-
156-
if (_extra) {
157-
pcre_free(_extra);
158-
_extra = nullptr;
159-
}
144+
return _pattern.empty() || !_re || _re->empty();
160145
}
161146

162147
/**
163148
* @brief Destructor, frees PCRE related resources.
164149
*/
165-
Pattern::~Pattern()
166-
{
167-
pcreFree();
168-
}
169150

170151
/**
171152
* @brief Capture or capture-and-replace depending on whether a replacement string is specified.
@@ -214,22 +195,13 @@ Pattern::process(const String &subject, StringVector &result)
214195
bool
215196
Pattern::match(const String &subject)
216197
{
217-
int matchCount;
218198
AccessControlDebug("matching '%s' to '%s'", _pattern.c_str(), subject.c_str());
219199

220-
if (!_re) {
221-
return false;
222-
}
223-
224-
matchCount = pcre_exec(_re, _extra, subject.c_str(), subject.length(), 0, PCRE_NOTEMPTY, nullptr, 0);
225-
if (matchCount < 0) {
226-
if (matchCount != PCRE_ERROR_NOMATCH) {
227-
AccessControlError("matching error %d", matchCount);
228-
}
200+
if (!_re || _re->empty()) {
229201
return false;
230202
}
231203

232-
return true;
204+
return _re->exec(subject, RE_NOTEMPTY);
233205
}
234206

235207
/**
@@ -240,31 +212,24 @@ Pattern::match(const String &subject)
240212
bool
241213
Pattern::capture(const String &subject, StringVector &result)
242214
{
243-
int matchCount;
244-
int ovector[OVECOUNT];
245-
246215
AccessControlDebug("capturing '%s' from '%s'", _pattern.c_str(), subject.c_str());
247216

248-
if (!_re) {
217+
if (!_re || _re->empty()) {
249218
AccessControlError("regular expression not initialized");
250219
return false;
251220
}
252221

253-
matchCount = pcre_exec(_re, nullptr, subject.c_str(), subject.length(), 0, PCRE_NOTEMPTY, ovector, OVECOUNT);
222+
RegexMatches matches(TOKENCOUNT);
223+
int matchCount = _re->exec(subject, matches, RE_NOTEMPTY);
254224
if (matchCount < 0) {
255-
if (matchCount != PCRE_ERROR_NOMATCH) {
256-
AccessControlError("matching error %d", matchCount);
257-
}
258225
return false;
259226
}
260227

261228
for (int i = 0; i < matchCount; i++) {
262-
int start = ovector[2 * i];
263-
int length = ovector[2 * i + 1] - ovector[2 * i];
229+
std::string_view match_view = matches[i];
230+
String dst(match_view.data(), match_view.size());
264231

265-
String dst(subject, start, length);
266-
267-
AccessControlDebug("capturing '%s' %d[%d,%d]", dst.c_str(), i, ovector[2 * i], ovector[2 * i + 1]);
232+
AccessControlDebug("capturing '%s' %d", dst.c_str(), i);
268233
result.push_back(dst);
269234
}
270235

@@ -280,21 +245,16 @@ Pattern::capture(const String &subject, StringVector &result)
280245
bool
281246
Pattern::replace(const String &subject, String &result)
282247
{
283-
int matchCount;
284-
int ovector[OVECOUNT];
285-
286248
AccessControlDebug("replacing:'%s' in pattern:'%s', subject:'%s'", _replacement.c_str(), _pattern.c_str(), subject.c_str());
287249

288-
if (!_re || !_replace) {
250+
if (!_re || _re->empty() || !_replace) {
289251
AccessControlError("regular expression not initialized or not configured to replace");
290252
return false;
291253
}
292254

293-
matchCount = pcre_exec(_re, nullptr, subject.c_str(), subject.length(), 0, PCRE_NOTEMPTY, ovector, OVECOUNT);
255+
RegexMatches matches(TOKENCOUNT);
256+
int matchCount = _re->exec(subject, matches, RE_NOTEMPTY);
294257
if (matchCount < 0) {
295-
if (matchCount != PCRE_ERROR_NOMATCH) {
296-
AccessControlError("matching error %d", matchCount);
297-
}
298258
return false;
299259
}
300260

@@ -308,12 +268,11 @@ Pattern::replace(const String &subject, String &result)
308268

309269
int previous = 0;
310270
for (int i = 0; i < _tokenCount; i++) {
311-
int replIndex = _tokens[i];
312-
int start = ovector[2 * replIndex];
313-
int length = ovector[2 * replIndex + 1] - ovector[2 * replIndex];
271+
int replIndex = _tokens[i];
272+
std::string_view match_view = matches[replIndex];
314273

315274
String src(_replacement, _tokenOffset[i], 2);
316-
String dst(subject, start, length);
275+
String dst(match_view.data(), match_view.size());
317276

318277
AccessControlDebug("replacing '%s' with '%s'", src.c_str(), dst.c_str());
319278

@@ -337,31 +296,16 @@ Pattern::replace(const String &subject, String &result)
337296
bool
338297
Pattern::compile()
339298
{
340-
const char *errPtr; /* PCRE error */
299+
std::string error; /* PCRE error description */
341300
int errOffset; /* PCRE error offset */
342301

343302
AccessControlDebug("compiling pattern:'%s', replace: %s, replacement:'%s'", _pattern.c_str(), _replace ? "true" : "false",
344303
_replacement.c_str());
345304

346-
_re = pcre_compile(_pattern.c_str(), /* the pattern */
347-
0, /* options */
348-
&errPtr, /* for error message */
349-
&errOffset, /* for error offset */
350-
nullptr); /* use default character tables */
351-
352-
if (nullptr == _re) {
353-
AccessControlError("compile of regex '%s' at char %d: %s", _pattern.c_str(), errOffset, errPtr);
354-
355-
return false;
356-
}
357-
358-
_extra = pcre_study(_re, 0, &errPtr);
359-
360-
if ((nullptr == _extra) && (nullptr != errPtr) && (0 != *errPtr)) {
361-
AccessControlError("failed to study regex '%s': %s", _pattern.c_str(), errPtr);
362-
363-
pcre_free(_re);
364-
_re = nullptr;
305+
_re = std::make_unique<Regex>();
306+
if (!_re->compile(_pattern, error, errOffset, 0)) {
307+
AccessControlError("compile of regex '%s' at char %d: %s", _pattern.c_str(), errOffset, error.c_str());
308+
_re.reset();
365309
return false;
366310
}
367311

@@ -398,7 +342,7 @@ Pattern::compile()
398342
}
399343

400344
if (!success) {
401-
pcreFree();
345+
_re.reset();
402346
}
403347

404348
return success;

plugins/experimental/access_control/pattern.h

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,20 @@
2323

2424
#pragma once
2525

26-
#ifdef HAVE_PCRE_PCRE_H
27-
#include <pcre/pcre.h>
28-
#else
29-
#include <pcre.h>
30-
#endif
31-
3226
#include "common.h"
3327

28+
class Regex;
29+
3430
/**
3531
* @brief PCRE matching, capturing and replacing
3632
*/
3733
class Pattern
3834
{
3935
public:
40-
static const int TOKENCOUNT = 10; /**< @brief Capturing groups $0..$9 */
41-
static const int OVECOUNT = TOKENCOUNT * 3; /**< @brief pcre_exec() array count, handle 10 capture groups */
36+
static const int TOKENCOUNT = 10; /**< @brief Capturing groups $0..$9 */
4237

4338
Pattern();
44-
virtual ~Pattern();
39+
~Pattern(); // Keep in pattern.cc for pimpl use of Regex.
4540

4641
bool init(const String &pattern, const String &replacement, bool replace);
4742
bool init(const String &config);
@@ -54,10 +49,8 @@ class Pattern
5449

5550
private:
5651
bool compile();
57-
void pcreFree();
5852

59-
pcre *_re = nullptr; /**< @brief PCRE compiled info structure, computed during initialization */
60-
pcre_extra *_extra = nullptr; /**< @brief PCRE study data block, computed during initialization */
53+
std::unique_ptr<Regex> _re; /**< @brief Regex compiled object, computed during initialization */
6154

6255
String _pattern; /**< @brief PCRE pattern string, containing PCRE patterns and capturing groups. */
6356
String _replacement; /**< @brief PCRE replacement string, containing $0..$9 to be replaced with content of the capturing groups */

0 commit comments

Comments
 (0)