From: Dmitry V. Levin Date: Fri, 25 Nov 2016 23:47:32 +0000 (+0000) Subject: Change parser of fault expressions to conform the documentation X-Git-Tag: v4.15~86 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d5b9c75d61946a65ec38837094403d72049d69e9;p=strace Change parser of fault expressions to conform the documentation Make expressions like fault=SYSCALL1,SYSCALL2:error=EPERM work as documented, i.e. fail both SYSCALL1 and SYSCALL2 with EPERM. * syscall.c (parse_fault_expression): Remove const qualifier from "name" and "token: variables, as well as from the return value. (qual_fault): Remove const qualifier from "name" variables. Split "name" into comma delimited tokens and pass each token to individual qual_syscall_ex call. (qualify): For QUAL_FAULT options, pass the whole option value to their qualify methods without prior splitting into comma delimited tokens. * tests/fault_injection.test: Check it. * tests/fault_syntax.test: Check empty syscall sets. --- diff --git a/syscall.c b/syscall.c index 4143bc0c..57c2945a 100644 --- a/syscall.c +++ b/syscall.c @@ -628,13 +628,13 @@ parse_fault_token(const char *const token, struct fault_opts *const fopts) return true; } -static const char * +static char * parse_fault_expression(const char *const s, char **buf, struct fault_opts *const fopts) { char *saveptr = NULL; - const char *name = NULL; - const char *token; + char *name = NULL; + char *token; *buf = xstrdup(s); for (token = strtok_r(*buf, ":", &saveptr); token; @@ -663,12 +663,20 @@ qual_fault(const char *const s, const unsigned int bitflag, const int not) }; char *buf = NULL; - const char *name = parse_fault_expression(s, &buf, &opts); + char *name = parse_fault_expression(s, &buf, &opts); + char *saveptr = NULL; + const char *token; + int rc = -1; if (!name) return -1; - int rc = qual_syscall_ex(name, bitflag, not, &opts); + for (token = strtok_r(name, ",", &saveptr); token; + token = strtok_r(NULL, ",", &saveptr)) { + rc = qual_syscall_ex(token, bitflag, not, &opts); + if (rc) + break; + } free(buf); return rc; @@ -744,16 +752,21 @@ qualify(const char *s) not = 1 - not; s = "all"; } - if (opt->bitflag != QUAL_FAULT) { - if (strcmp(s, "all") == 0) { - for (i = 0; i < num_quals; ++i) { - qualify_one(i, opt->bitflag, not, -1, NULL); - } - return; + if (opt->bitflag == QUAL_FAULT) { + if (opt->qualify(s, opt->bitflag, not)) { + error_msg_and_die("invalid %s '%s'", + opt->argument_name, s); } + return; + } + if (strcmp(s, "all") == 0) { for (i = 0; i < num_quals; ++i) { - qualify_one(i, opt->bitflag, !not, -1, NULL); + qualify_one(i, opt->bitflag, not, -1, NULL); } + return; + } + for (i = 0; i < num_quals; ++i) { + qualify_one(i, opt->bitflag, !not, -1, NULL); } copy = xstrdup(s); for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) { diff --git a/tests/fault_injection.test b/tests/fault_injection.test index 004bcb0d..40d44aac 100755 --- a/tests/fault_injection.test +++ b/tests/fault_injection.test @@ -85,7 +85,7 @@ check_fault_injection() } for err in '' ENOSYS 22 EINVAL; do - for fault in writev 51,desc; do + for fault in writev desc,51; do check_fault_injection \ writev $fault "$err" '' '' -efault=chdir for F in 1 2 3 5 7 11; do diff --git a/tests/fault_syntax.test b/tests/fault_syntax.test index 97766d25..bd306bb3 100755 --- a/tests/fault_syntax.test +++ b/tests/fault_syntax.test @@ -40,7 +40,8 @@ fail_with() "strace -e fault=$* failed to handle an argument error properly" } -for arg in invalid_syscall_name \ +for arg in '' , ,, ,,, : :: ::: \ + invalid_syscall_name \ invalid_syscall_name:when=3 \ -1 \ -1:when=4 \