From owner-svn-src-all@freebsd.org Sat Jul 30 17:53:38 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id DA744BA865A; Sat, 30 Jul 2016 17:53:38 +0000 (UTC) (envelope-from allanjude@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9CEAE1588; Sat, 30 Jul 2016 17:53:38 +0000 (UTC) (envelope-from allanjude@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u6UHrbUF037322; Sat, 30 Jul 2016 17:53:37 GMT (envelope-from allanjude@FreeBSD.org) Received: (from allanjude@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u6UHrb9v037321; Sat, 30 Jul 2016 17:53:37 GMT (envelope-from allanjude@FreeBSD.org) Message-Id: <201607301753.u6UHrb9v037321@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: allanjude set sender to allanjude@FreeBSD.org using -f From: Allan Jude Date: Sat, 30 Jul 2016 17:53:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r303556 - head/sys/boot/common X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 30 Jul 2016 17:53:39 -0000 Author: allanjude Date: Sat Jul 30 17:53:37 2016 New Revision: 303556 URL: https://svnweb.freebsd.org/changeset/base/303556 Log: Improve boot loader quote parsing parse() is the boot loader's interp_parse.c is too naive about quotes both single and double quotes were allowed to be mixed, and single quotes did not follow the usual semantics (re variable expansion). The old code did not check for terminating quotes This update implements: * distinguishing single and double quote * variable expansion will not be done inside single quote protected area * will preserve inner quote for values like "value 'some list'" * ending quote check. this diff does not implement ending quote order check, it shouldn't be too hard, needs some improvements on parser state machine. PR: 204602 Submitted by: Toomas Soome Relnotes: yes Differential Revision: https://reviews.freebsd.org/D6000 Modified: head/sys/boot/common/interp_parse.c Modified: head/sys/boot/common/interp_parse.c ============================================================================== --- head/sys/boot/common/interp_parse.c Sat Jul 30 17:45:56 2016 (r303555) +++ head/sys/boot/common/interp_parse.c Sat Jul 30 17:53:37 2016 (r303556) @@ -72,7 +72,13 @@ isdelim(int ch) static int isquote(int ch) { - return (ch == '\'' || ch == '"'); + return (ch == '\''); +} + +static int +isdquote(int ch) +{ + return (ch == '"'); } int @@ -81,11 +87,11 @@ parse(int *argc, char ***argv, char *str int ac; char *val, *p, *q, *copy = NULL; size_t i = 0; - char token, tmp, quote, *buf; + char token, tmp, quote, dquote, *buf; enum { STR, VAR, WHITE } state; ac = *argc = 0; - quote = 0; + dquote = quote = 0; if (!str || (p = copy = backslash(str)) == NULL) return 1; @@ -105,9 +111,19 @@ parse(int *argc, char ***argv, char *str buf[i++] = *p++; } else if (isquote(*p)) { quote = quote ? 0 : *p; - ++p; - } - else if (isspace(*p) && !quote) { + if (dquote) { /* keep quote */ + PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); + buf[i++] = *p++; + } else + ++p; + } else if (isdquote(*p)) { + dquote = dquote ? 0 : *p; + if (quote) { /* keep dquote */ + PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); + buf[i++] = *p++; + } else + ++p; + } else if (isspace(*p) && !quote && !dquote) { state = WHITE; if (i) { buf[i] = '\0'; @@ -115,7 +131,7 @@ parse(int *argc, char ***argv, char *str i = 0; } ++p; - } else if (*p == '$') { + } else if (*p == '$' && !quote) { token = isdelim(*(p + 1)); if (token) p += 2; @@ -157,6 +173,8 @@ parse(int *argc, char ***argv, char *str break; } } + /* missing terminating ' or " */ + PARSE_FAIL(quote || dquote); /* If at end of token, add it */ if (i && state == STR) { buf[i] = '\0';