1 #include <string.h>
2 #include "regexp.h"
3 #include "debug.h"
4 #include "error.h"
5 #include "util/xmalloc.h"
6 
regexp_match_nosub(const char * pattern,const char * buf,size_t size)7 bool regexp_match_nosub(const char *pattern, const char *buf, size_t size)
8 {
9     regex_t re;
10     bool compiled = regexp_compile(&re, pattern, REG_NEWLINE | REG_NOSUB);
11     BUG_ON(!compiled);
12     regmatch_t m;
13     bool ret = regexp_exec(&re, buf, size, 1, &m, 0);
14     regfree(&re);
15     return ret;
16 }
17 
regexp_match(const char * pattern,const char * buf,size_t size,PointerArray * m)18 bool regexp_match (
19     const char *pattern,
20     const char *buf,
21     size_t size,
22     PointerArray *m
23 ) {
24     regex_t re;
25     bool compiled = regexp_compile(&re, pattern, REG_NEWLINE);
26     BUG_ON(!compiled);
27     bool ret = regexp_exec_sub(&re, buf, size, m, 0);
28     regfree(&re);
29     return ret;
30 }
31 
regexp_compile_internal(regex_t * re,const char * pattern,int flags)32 bool regexp_compile_internal(regex_t *re, const char *pattern, int flags)
33 {
34     int err = regcomp(re, pattern, flags);
35 
36     if (err) {
37         char msg[1024];
38         regerror(err, re, msg, sizeof(msg));
39         error_msg("%s: %s", msg, pattern);
40         return false;
41     }
42     return true;
43 }
44 
regexp_exec(const regex_t * re,const char * buf,size_t size,size_t nr_m,regmatch_t * m,int flags)45 bool regexp_exec (
46     const regex_t *re,
47     const char *buf,
48     size_t size,
49     size_t nr_m,
50     regmatch_t *m,
51     int flags
52 ) {
53     BUG_ON(!nr_m);
54 // Clang's address sanitizer seemingly doesn't take REG_STARTEND into
55 // account when checking for buffer overflow.
56 #if defined(REG_STARTEND) && !defined(CLANG_ASAN_ENABLED)
57     m[0].rm_so = 0;
58     m[0].rm_eo = size;
59     return !regexec(re, buf, nr_m, m, flags | REG_STARTEND);
60 #else
61     // Buffer must be null-terminated if REG_STARTEND isn't supported
62     char *tmp = xstrcut(buf, size);
63     int ret = !regexec(re, tmp, nr_m, m, flags);
64     free(tmp);
65     return ret;
66 #endif
67 }
68 
regexp_exec_sub(const regex_t * re,const char * buf,size_t size,PointerArray * matches,int flags)69 bool regexp_exec_sub (
70     const regex_t *re,
71     const char *buf,
72     size_t size,
73     PointerArray *matches,
74     int flags
75 ) {
76     regmatch_t m[16];
77     bool ret = regexp_exec(re, buf, size, ARRAY_COUNT(m), m, flags);
78     if (!ret) {
79         return false;
80     }
81     for (size_t i = 0; i < ARRAY_COUNT(m); i++) {
82         if (m[i].rm_so == -1) {
83             break;
84         }
85         ptr_array_add(matches, xstrslice(buf, m[i].rm_so, m[i].rm_eo));
86     }
87     return true;
88 }
89