svn commit: r303556 - head/sys/boot/common

Allan Jude allanjude at FreeBSD.org
Sat Jul 30 17:53:39 UTC 2016


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 <tsoome at me.com>
  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';


More information about the svn-src-head mailing list