Merge "implement partial matching using PCRE"
diff --git a/Android.mk b/Android.mk
index dbabaad..f46c6c1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -48,6 +48,8 @@
LOCAL_MODULE:= libselinux
LOCAL_MODULE_TAGS := eng
LOCAL_STATIC_LIBRARIES := libmincrypt
+LOCAL_C_INCLUDES := external/pcre
+LOCAL_WHOLE_STATIC_LIBRARIES := libpcre
# 1003 corresponds to auditd, from system/core/logd/event.logtags
LOCAL_CFLAGS := -DAUDITD_LOG_TAG=1003
include $(BUILD_STATIC_LIBRARY)
@@ -64,6 +66,8 @@
LOCAL_MODULE_TAGS := eng
LOCAL_COPY_HEADERS_TO := $(common_COPY_HEADERS_TO)
LOCAL_COPY_HEADERS := $(common_COPY_HEADERS)
+LOCAL_WHOLE_STATIC_LIBRARIES := libpcre
+LOCAL_C_INCLUDES := external/pcre
include $(BUILD_HOST_STATIC_LIBRARY)
include $(CLEAR_VARS)
@@ -74,7 +78,8 @@
LOCAL_COPY_HEADERS := $(common_COPY_HEADERS)
LOCAL_PRELINK_MODULE := false
LOCAL_STATIC_LIBRARIES := libmincrypt
-LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_C_INCLUDES := external/pcre
+LOCAL_SHARED_LIBRARIES := liblog libpcre
# 1003 corresponds to auditd, from system/core/logd/event.logtags
LOCAL_CFLAGS := -DAUDITD_LOG_TAG=1003
include $(BUILD_SHARED_LIBRARY)
diff --git a/src/label_file.c b/src/label_file.c
index 279a83d..1952cd0 100644
--- a/src/label_file.c
+++ b/src/label_file.c
@@ -11,12 +11,12 @@
#include <ctype.h>
#include <errno.h>
#include <limits.h>
-#include <regex.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "callbacks.h"
#include "label_internal.h"
+#include <pcre.h>
/*
* Internals, mostly moved over from matchpathcon.c
@@ -27,7 +27,8 @@
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; /* pcre study result */
char regcomp; /* regex_str has been compiled to regex */
mode_t mode; /* mode format value */
int matches; /* number of matching pathnames */
@@ -224,12 +225,13 @@
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 */
@@ -254,21 +256,20 @@
*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 = (char *) 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;
}
- free(anchored_regex);
+
+ spec->sd = pcre_study(spec->regex, 0, &tmperrbuf);
+ if (!spec->sd) {
+ if (errbuf)
+ *errbuf=tmperrbuf;
+ return -1;
+ }
/* Done. */
spec->regcomp = 1;
@@ -317,7 +318,7 @@
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 = strdup(regex);
if (!spec_arr[nspec].regex_str) {
@@ -552,8 +553,10 @@
free(spec->type_str);
free(spec->lr.ctx_raw);
free(spec->lr.ctx_trans);
- if (spec->regcomp)
- 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++) {
@@ -576,14 +579,13 @@
{
struct saved_data *data = (struct saved_data *)rec->data;
spec_t *spec_arr = data->spec_arr;
- int i, rc, file_stem;
+ int i, rc, file_stem, pcre_options = 0;
mode_t mode = (mode_t)type;
const char *buf;
spec_t *ret = NULL;
char *clean_key = NULL;
const char *prev_slash, *next_slash;
unsigned int sofar = 0;
- size_t keylen = strlen(key);
if (!data->nspec) {
errno = ENOENT;
@@ -610,6 +612,9 @@
file_stem = find_stem_from_file(data, &buf);
mode &= S_IFMT;
+ if (partial)
+ pcre_options |= PCRE_PARTIAL_SOFT;
+
/*
* Check for matching specifications in reverse order, so that
* the last matching specification is used.
@@ -626,38 +631,17 @@
if (compile_regex(data, &spec_arr[i], NULL) < 0)
goto finish;
if (spec_arr[i].stem_id == -1)
- rc = regexec(&spec_arr[i].regex, key, 0, 0, 0);
+ rc = pcre_exec(spec_arr[i].regex, spec_arr[i].sd, key, strlen(key), 0, pcre_options, NULL, 0);
else
- rc = regexec(&spec_arr[i].regex, buf, 0, 0, 0);
+ rc = pcre_exec(spec_arr[i].regex, spec_arr[i].sd, buf, strlen(buf), 0, pcre_options, NULL, 0);
if (rc == 0) {
spec_arr[i].matches++;
break;
- }
+ } else if (partial && rc == PCRE_ERROR_PARTIAL)
+ break;
- if (partial) {
- /*
- * We already checked above to see if the
- * key has any direct match. Now we just need
- * to check for partial matches.
- * Since POSIX regex functions do not support
- * partial match, we crudely approximate it
- * via a prefix match.
- * This is imprecise and could yield
- * false positives or negatives but
- * appears to work with our current set of
- * regex strings.
- * Convert to using pcre partial match
- * if/when pcre becomes available in Android.
- */
- if (spec_arr[i].prefix_len > 1 &&
- !strncmp(key, spec_arr[i].regex_str,
- keylen < spec_arr[i].prefix_len ?
- keylen : spec_arr[i].prefix_len))
- break;
- }
-
- if (rc == REG_NOMATCH)
+ if (rc == PCRE_ERROR_NOMATCH)
continue;
/* else it's an error */
goto finish;