[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] [tor/master 5/6] Tweak continuation-and-comment logic



Author: Nick Mathewson <nickm@xxxxxxxxxxxxxx>
Date: Thu, 23 Sep 2010 22:58:04 -0400
Subject: Tweak continuation-and-comment logic
Commit: 0a0cc4599fd743d124d6ee90671c7c8e205b86e8

I think there was a read-off-the-end-of-the-buffer bug that I fixed.
At least I added some good comments, I hope.
---
 changes/torrc_continuation |    2 +-
 src/common/util.c          |   46 ++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/changes/torrc_continuation b/changes/torrc_continuation
index f63937e..5b6e086 100644
--- a/changes/torrc_continuation
+++ b/changes/torrc_continuation
@@ -2,5 +2,5 @@
     - Support line continuations in torrc.  If a line ends with a
       single backslash character, the newline is ignored, and the
       configuration value is treated as continuing on the next line.
-      Implements bug 1929.
+      Resolves bug 1929.
 
diff --git a/src/common/util.c b/src/common/util.c
index e47ac78..904fd82 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -2284,6 +2284,36 @@ unescape_string(const char *s, char **result, size_t *size_out)
 const char *
 parse_config_line_from_str(const char *line, char **key_out, char **value_out)
 {
+  /* I believe the file format here is supposed to be:
+     FILE = (EMPTYLINE | LINE)*
+
+     EMPTYLINE = SPACE* NL | COMMENT NL
+     SPACE = ' ' | '\r' | '\t'
+     COMMENT = '#' NOT-NL*
+     NOT-NL = Any character except '\n'
+     NL = '\n'
+
+     LINE = SPACE* KEY SPACE* VALUES NL
+     KEY = KEYCHAR+
+     KEYCHAR = Any character except ' ', '\r', '\n', '\t', '#', "\"
+
+     VALUES = QUOTEDVALUE | NORMALVALUE
+     QUOTEDVALUE = QUOTE QVITEM* QUOTE EOLSPACE?
+     QUOTE = '"'
+     QVCHAR = KEYCHAR | ESC ('n' | 't' | 'r' | '"' | ESC |'\'' | OCTAL | HEX)
+     ESC = "\\"
+     OCTAL = ODIGIT (ODIGIT ODIGIT?)?
+     HEX = ('x' | 'X') HEXDIGIT HEXDIGIT
+     ODIGIT = '0' .. '7'
+     HEXDIGIT = '0'..'9' | 'a' .. 'f' | 'A' .. 'F'
+     EOLSPACE = SPACE* COMMENT?
+
+     NORMALVALUE = (VALCHAR | ESC ESC_IGNORE | CONTINUATION)* EOLSPACE?
+     VALCHAR = Any character except ESC, '#', and '\n'
+     ESC_IGNORE = Any character except '#' or '\n'
+     CONTINUATION = ESC NL ( COMMENT NL )*
+   */
+
   const char *key, *val, *cp;
   int continuation = 0;
 
@@ -2323,7 +2353,7 @@ parse_config_line_from_str(const char *line, char **key_out, char **value_out)
   val = line;
 
   /* Find the end of the line. */
-  if (*line == '\"') { // XXX No continuation here
+  if (*line == '\"') { // XXX No continuation handling is done here
     if (!(line = unescape_string(line, value_out, NULL)))
        return NULL;
     while (*line == ' ' || *line == '\t')
@@ -2331,27 +2361,34 @@ parse_config_line_from_str(const char *line, char **key_out, char **value_out)
     if (*line && *line != '#' && *line != '\n')
       return NULL;
   } else {
+    /* Look for the end of the line. */
     while (*line && *line != '\n' && (*line != '#' || continuation)) {
       if (*line == '\\' && line[1] == '\n') {
         continuation = 1;
-        ++line;
+        line += 2;
       } else if (*line == '#') {
         do {
           ++line;
         } while (*line && *line != '\n');
+        if (*line == '\n')
+          ++line;
+      } else {
+        ++line;
       }
-      ++line;
     }
+
     if (*line == '\n') {
       cp = line++;
     } else {
       cp = line;
     }
+    /* Now back cp up to be the last nonspace character */
     while (cp>val && TOR_ISSPACE(*(cp-1)))
       --cp;
 
     tor_assert(cp >= val);
 
+    /* Now copy out and decode the value. */
     *value_out = tor_strndup(val, cp-val);
     if (continuation) {
       char *v_out, *v_in;
@@ -2361,7 +2398,8 @@ parse_config_line_from_str(const char *line, char **key_out, char **value_out)
           do {
             ++v_in;
           } while (*v_in && *v_in != '\n');
-          ++v_in;
+          if (*v_in == '\n')
+            ++v_in;
         } else if (v_in[0] == '\\' && v_in[1] == '\n') {
           v_in += 2;
         } else {
-- 
1.7.1