}
}
-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
int ov[MAX_SUBSTRINGS];
- int ret = 0, i = 0;
+ int ret = 0;
SigTableElmt *st = NULL;
- char *optname = NULL, *optvalue = NULL, *optmore = NULL;
-
- const char **arr = SCCalloc(OPTION_PARTS+1, sizeof(char *));
- if (unlikely(arr == NULL))
- return -1;
+ char optname[64];
+ char optvalue[8192];
ret = pcre_exec(option_pcre, option_pcre_extra, optstr, strlen(optstr), 0, 0, ov, MAX_SUBSTRINGS);
/* if successful, we either have:
}
/* extract the substrings */
- for (i = 1; i <= ret-1; i++) {
- if (pcre_get_substring(optstr, ov, MAX_SUBSTRINGS, i, &arr[i-1]) < 0) {
- goto error;
- }
- //printf("SigParseOptions: arr[%" PRId32 "] = \"%s\"\n", i-1, arr[i-1]);
+ if (pcre_copy_substring(optstr, ov, MAX_SUBSTRINGS, 1, optname, sizeof(optname)) < 0) {
+ goto error;
}
- arr[i-1]=NULL;
/* Call option parsing */
- st = SigTableGet((char *)arr[0]);
+ st = SigTableGet(optname);
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;
}
- if (st->flags & SIGMATCH_NOOPT) {
- optname = (char *)arr[0];
- optvalue = NULL;
- if (ret == 3) optmore = (char *)arr[1];
- else if (ret == 4) optmore = (char *)arr[2];
- else optmore = NULL;
- } else {
- optname = (char *)arr[0];
- optvalue = (char *)arr[1];
- if (ret == 4) optmore = (char *)arr[2];
- else optmore = NULL;
+ if (ret == 3) {
+ if (st->flags & SIGMATCH_NOOPT) {
+ if (pcre_copy_substring(optstr, ov, MAX_SUBSTRINGS, 2, output, output_size) < 0) {
+ goto error;
+ }
+ } else {
+ if (pcre_copy_substring(optstr, ov, MAX_SUBSTRINGS, 2, optvalue, sizeof(optvalue)) < 0) {
+ goto error;
+ }
+ }
+ } 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 */
- 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);
goto error;
}
- if (ret == 4 && optmore != NULL) {
- //printf("SigParseOptions: recursive call for more options... (s:%p,m:%p)\n", s, m);
-
- 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 (ret == 4) {
+ return 1;
}
- 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;
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;
}
/* we can have no options, so make sure we have them */
if (basics[CONFIG_OPTS] != NULL) {
- ret = SigParseOptions(de_ctx, s, SCStrdup(basics[CONFIG_OPTS]));
- SCLogDebug("ret from SigParseOptions %d", ret);
+ size_t buffer_size = strlen(basics[CONFIG_OPTS]) + 1;
+ 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 */