rule parsing: reduce mallocs and clean up

Reduce mallocs during rule parsing. Also, no longer recursively
call the option parse function.
pull/663/head
Victor Julien 11 years ago
parent 2ce8895f0a
commit 67989e7e4e

@ -480,16 +480,13 @@ void SigParsePrepare(void) {
} }
} }
static int SigParseOptions(DetectEngineCtx *de_ctx, Signature *s, char *optstr) { static int SigParseOptions(DetectEngineCtx *de_ctx, Signature *s, char *optstr, char *output, size_t output_size) {
#define MAX_SUBSTRINGS 30 #define MAX_SUBSTRINGS 30
int ov[MAX_SUBSTRINGS]; int ov[MAX_SUBSTRINGS];
int ret = 0, i = 0; int ret = 0;
SigTableElmt *st = NULL; SigTableElmt *st = NULL;
char *optname = NULL, *optvalue = NULL, *optmore = NULL; char optname[64];
char optvalue[8192];
const char **arr = SCCalloc(OPTION_PARTS+1, sizeof(char *));
if (unlikely(arr == NULL))
return -1;
ret = pcre_exec(option_pcre, option_pcre_extra, optstr, strlen(optstr), 0, 0, ov, MAX_SUBSTRINGS); ret = pcre_exec(option_pcre, option_pcre_extra, optstr, strlen(optstr), 0, 0, ov, MAX_SUBSTRINGS);
/* if successful, we either have: /* if successful, we either have:
@ -503,64 +500,49 @@ static int SigParseOptions(DetectEngineCtx *de_ctx, Signature *s, char *optstr)
} }
/* extract the substrings */ /* extract the substrings */
for (i = 1; i <= ret-1; i++) { if (pcre_copy_substring(optstr, ov, MAX_SUBSTRINGS, 1, optname, sizeof(optname)) < 0) {
if (pcre_get_substring(optstr, ov, MAX_SUBSTRINGS, i, &arr[i-1]) < 0) { goto error;
goto error;
}
//printf("SigParseOptions: arr[%" PRId32 "] = \"%s\"\n", i-1, arr[i-1]);
} }
arr[i-1]=NULL;
/* Call option parsing */ /* Call option parsing */
st = SigTableGet((char *)arr[0]); st = SigTableGet(optname);
if (st == NULL) { if (st == NULL) {
SCLogError(SC_ERR_RULE_KEYWORD_UNKNOWN, "unknown rule keyword '%s'.", (char *)arr[0]); SCLogError(SC_ERR_RULE_KEYWORD_UNKNOWN, "unknown rule keyword '%s'.", optname);
goto error; goto error;
} }
if (st->flags & SIGMATCH_NOOPT) { if (ret == 3) {
optname = (char *)arr[0]; if (st->flags & SIGMATCH_NOOPT) {
optvalue = NULL; if (pcre_copy_substring(optstr, ov, MAX_SUBSTRINGS, 2, output, output_size) < 0) {
if (ret == 3) optmore = (char *)arr[1]; goto error;
else if (ret == 4) optmore = (char *)arr[2]; }
else optmore = NULL; } else {
} else { if (pcre_copy_substring(optstr, ov, MAX_SUBSTRINGS, 2, optvalue, sizeof(optvalue)) < 0) {
optname = (char *)arr[0]; goto error;
optvalue = (char *)arr[1]; }
if (ret == 4) optmore = (char *)arr[2]; }
else optmore = NULL; } else if (ret == 4) {
if (pcre_copy_substring(optstr, ov, MAX_SUBSTRINGS, 2, optvalue, sizeof(optvalue)) < 0) {
goto error;
}
if (pcre_copy_substring(optstr, ov, MAX_SUBSTRINGS, 3, output, output_size) < 0) {
goto error;
}
} }
/* setup may or may not add a new SigMatch to the list */ /* setup may or may not add a new SigMatch to the list */
if (st->Setup(de_ctx, s, optvalue) < 0) { if (st->Setup(de_ctx, s, strlen(optvalue) ? optvalue : NULL) < 0) {
SCLogDebug("\"%s\" failed to setup", st->name); SCLogDebug("\"%s\" failed to setup", st->name);
goto error; goto error;
} }
if (ret == 4 && optmore != NULL) { if (ret == 4) {
//printf("SigParseOptions: recursive call for more options... (s:%p,m:%p)\n", s, m); return 1;
if (optname) pcre_free_substring(optname);
if (optvalue) pcre_free_substring(optvalue);
if (optstr) SCFree(optstr);
//if (optmore) pcre_free_substring(optmore);
if (arr != NULL) pcre_free_substring_list(arr);
return SigParseOptions(de_ctx, s, optmore);
} }
if (optname) pcre_free_substring(optname);
if (optvalue) pcre_free_substring(optvalue);
if (optmore) pcre_free_substring(optmore);
if (optstr) SCFree(optstr);
if (arr != NULL) pcre_free_substring_list(arr);
return 0; return 0;
error: error:
if (optname) pcre_free_substring(optname);
if (optvalue) pcre_free_substring(optvalue);
if (optmore) pcre_free_substring(optmore);
if (optstr) SCFree(optstr);
if (arr != NULL) pcre_free_substring_list(arr);
return -1; return -1;
} }
@ -891,8 +873,23 @@ int SigParse(DetectEngineCtx *de_ctx, Signature *s, char *sigstr, uint8_t addrs_
/* we can have no options, so make sure we have them */ /* we can have no options, so make sure we have them */
if (basics[CONFIG_OPTS] != NULL) { if (basics[CONFIG_OPTS] != NULL) {
ret = SigParseOptions(de_ctx, s, SCStrdup(basics[CONFIG_OPTS])); size_t buffer_size = strlen(basics[CONFIG_OPTS]) + 1;
SCLogDebug("ret from SigParseOptions %d", ret); char input[buffer_size];
char output[buffer_size];
memset(input, 0x00, buffer_size);
memcpy(input, basics[CONFIG_OPTS], strlen(basics[CONFIG_OPTS])+1);
/* loop the option parsing. Each run processes one option
* and returns the rest of the option string through the
* output variable. */
do {
memset(output, 0x00, buffer_size);
ret = SigParseOptions(de_ctx, s, input, output, buffer_size);
if (ret == 1) {
memcpy(input, output, buffer_size);
}
} while (ret == 1);
} }
/* cleanup */ /* cleanup */

Loading…
Cancel
Save