libselinux: label_file: use PCRE instead of glibc regex functions
The PCRE functions are about x10 faster than the glibc functions. So use the external library. Signed-off-by: Eric Paris <eparis@redhat.com>
This commit is contained in:
parent
ac5f5645b6
commit
091eb526dd
2 changed files with 35 additions and 30 deletions
|
@ -20,6 +20,8 @@ RUBYINC ?= $(shell pkg-config --cflags ruby-$(RUBYLIBVER))
|
|||
RUBYINSTALL ?= $(LIBDIR)/ruby/site_ruby/$(RUBYLIBVER)/$(RUBYPLATFORM)
|
||||
LIBBASE=$(shell basename $(LIBDIR))
|
||||
|
||||
LDFLAGS ?= -lpcre
|
||||
|
||||
VERSION = $(shell cat ../VERSION)
|
||||
LIBVERSION = 1
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <regex.h>
|
||||
#include <pcre.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
@ -32,7 +32,8 @@ typedef struct spec {
|
|||
struct selabel_lookup_rec lr; /* holds contexts for lookup result */
|
||||
char *regex_str; /* regular expession string for diagnostics */
|
||||
char *type_str; /* type string for diagnostic messages */
|
||||
regex_t regex; /* compiled regular expression */
|
||||
pcre *regex; /* compiled regular expression */
|
||||
pcre_extra *sd; /* extra compiled stuff */
|
||||
char regcomp; /* regex_str has been compiled to regex */
|
||||
mode_t mode; /* mode format value */
|
||||
int matches; /* number of matching pathnames */
|
||||
|
@ -223,12 +224,13 @@ static void spec_hasMetaChars(struct spec *spec)
|
|||
return;
|
||||
}
|
||||
|
||||
static int compile_regex(struct saved_data *data, spec_t *spec, char **errbuf)
|
||||
static int compile_regex(struct saved_data *data, spec_t *spec, const char **errbuf)
|
||||
{
|
||||
const char *tmperrbuf;
|
||||
char *reg_buf, *anchored_regex, *cp;
|
||||
stem_t *stem_arr = data->stem_arr;
|
||||
size_t len;
|
||||
int regerr;
|
||||
int erroff;
|
||||
|
||||
if (spec->regcomp)
|
||||
return 0; /* already done */
|
||||
|
@ -245,6 +247,7 @@ static int compile_regex(struct saved_data *data, spec_t *spec, char **errbuf)
|
|||
cp = anchored_regex = malloc(len + 3);
|
||||
if (!anchored_regex)
|
||||
return -1;
|
||||
|
||||
/* Create ^...$ regexp. */
|
||||
*cp++ = '^';
|
||||
cp = mempcpy(cp, reg_buf, len);
|
||||
|
@ -252,21 +255,20 @@ static int compile_regex(struct saved_data *data, spec_t *spec, char **errbuf)
|
|||
*cp = '\0';
|
||||
|
||||
/* Compile the regular expression. */
|
||||
regerr = regcomp(&spec->regex, anchored_regex,
|
||||
REG_EXTENDED | REG_NOSUB);
|
||||
if (regerr != 0) {
|
||||
size_t errsz = 0;
|
||||
errsz = regerror(regerr, &spec->regex, NULL, 0);
|
||||
if (errsz && errbuf)
|
||||
*errbuf = malloc(errsz);
|
||||
if (errbuf && *errbuf)
|
||||
(void)regerror(regerr, &spec->regex,
|
||||
*errbuf, errsz);
|
||||
|
||||
free(anchored_regex);
|
||||
spec->regex = pcre_compile(anchored_regex, 0, &tmperrbuf, &erroff, NULL);
|
||||
free(anchored_regex);
|
||||
if (!spec->regex) {
|
||||
if (errbuf)
|
||||
*errbuf=tmperrbuf;
|
||||
return -1;
|
||||
}
|
||||
|
||||
spec->sd = pcre_study(spec->regex, 0, &tmperrbuf);
|
||||
if (!spec->sd) {
|
||||
if (errbuf)
|
||||
*errbuf=tmperrbuf;
|
||||
return -1;
|
||||
}
|
||||
free(anchored_regex);
|
||||
|
||||
/* Done. */
|
||||
spec->regcomp = 1;
|
||||
|
@ -320,7 +322,7 @@ static int process_line(struct selabel_handle *rec,
|
|||
|
||||
if (pass == 1) {
|
||||
/* On the second pass, process and store the specification in spec. */
|
||||
char *errbuf = NULL;
|
||||
const char *errbuf = NULL;
|
||||
spec_arr[nspec].stem_id = find_stem_from_spec(data, regex);
|
||||
spec_arr[nspec].regex_str = regex;
|
||||
if (rec->validating && compile_regex(data, &spec_arr[nspec], &errbuf)) {
|
||||
|
@ -575,7 +577,10 @@ static void closef(struct selabel_handle *rec)
|
|||
free(spec->type_str);
|
||||
free(spec->lr.ctx_raw);
|
||||
free(spec->lr.ctx_trans);
|
||||
regfree(&spec->regex);
|
||||
if (spec->regcomp) {
|
||||
pcre_free(spec->regex);
|
||||
pcre_free_study(spec->sd);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < (unsigned int)data->num_stems; i++) {
|
||||
|
@ -634,26 +639,24 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
|
|||
* the last matching specification is used.
|
||||
*/
|
||||
for (i = data->nspec - 1; i >= 0; i--) {
|
||||
spec_t *spec = &spec_arr[i];
|
||||
/* if the spec in question matches no stem or has the same
|
||||
* stem as the file AND if the spec in question has no mode
|
||||
* specified or if the mode matches the file mode then we do
|
||||
* a regex check */
|
||||
if ((spec_arr[i].stem_id == -1
|
||||
|| spec_arr[i].stem_id == file_stem)
|
||||
&& (!mode || !spec_arr[i].mode
|
||||
|| mode == spec_arr[i].mode)) {
|
||||
if (compile_regex(data, &spec_arr[i], NULL) < 0)
|
||||
if ((spec->stem_id == -1 || spec->stem_id == file_stem) &&
|
||||
(!mode || !spec->mode || mode == spec->mode)) {
|
||||
if (compile_regex(data, spec, NULL) < 0)
|
||||
goto finish;
|
||||
if (spec_arr[i].stem_id == -1)
|
||||
rc = regexec(&spec_arr[i].regex, key, 0, 0, 0);
|
||||
if (spec->stem_id == -1)
|
||||
rc = pcre_exec(spec->regex, spec->sd, key, strlen(key), 0, 0, NULL, 0);
|
||||
else
|
||||
rc = regexec(&spec_arr[i].regex, buf, 0, 0, 0);
|
||||
rc = pcre_exec(spec->regex, spec->sd, buf, strlen(buf), 0, 0, NULL, 0);
|
||||
|
||||
if (rc == 0) {
|
||||
spec_arr[i].matches++;
|
||||
spec->matches++;
|
||||
break;
|
||||
}
|
||||
if (rc == REG_NOMATCH)
|
||||
} else if (rc == PCRE_ERROR_NOMATCH)
|
||||
continue;
|
||||
/* else it's an error */
|
||||
goto finish;
|
||||
|
|
Loading…
Reference in a new issue