[tor-commits] [tor/master] Fix version number parsing to allow 2- and 3-part versions.

nickm at torproject.org nickm at torproject.org
Tue Jan 6 20:16:39 UTC 2015


commit fc62721b06e3ac231b570741e21dba03b5cadaca
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Nov 5 13:28:29 2014 -0500

    Fix version number parsing to allow 2- and 3-part versions.
    
    Fixes bug 13661; bugfix on 0.0.8pre1.
---
 changes/bug13661     |    6 +++++
 src/or/routerparse.c |   62 +++++++++++++++++++++++++++++---------------------
 src/test/test_dir.c  |   36 +++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 26 deletions(-)

diff --git a/changes/bug13661 b/changes/bug13661
new file mode 100644
index 0000000..7f0cb5e
--- /dev/null
+++ b/changes/bug13661
@@ -0,0 +1,6 @@
+  o Minor bugfixes:
+
+    - Support two-number and three-number version numbers correctly, in
+      case we change the Tor versioning system in the future.  Fixes bug
+      13661; bugfix on 0.0.8pre1.
+
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index f990ceb..68dbc70 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -4207,40 +4207,50 @@ tor_version_parse(const char *s, tor_version_t *out)
   char *eos=NULL;
   const char *cp=NULL;
   /* Format is:
-   *   "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
+   *   "Tor " ? NUM dot NUM [ dot NUM [ ( pre | rc | dot ) NUM ] ] [ - tag ]
    */
   tor_assert(s);
   tor_assert(out);
 
   memset(out, 0, sizeof(tor_version_t));
-
+  out->status = VER_RELEASE;
   if (!strcasecmpstart(s, "Tor "))
     s += 4;
 
-  /* Get major. */
-  out->major = (int)strtol(s,&eos,10);
-  if (!eos || eos==s || *eos != '.') return -1;
-  cp = eos+1;
-
-  /* Get minor */
-  out->minor = (int) strtol(cp,&eos,10);
-  if (!eos || eos==cp || *eos != '.') return -1;
-  cp = eos+1;
-
-  /* Get micro */
-  out->micro = (int) strtol(cp,&eos,10);
-  if (!eos || eos==cp) return -1;
-  if (!*eos) {
-    out->status = VER_RELEASE;
-    out->patchlevel = 0;
+  cp = s;
+
+#define NUMBER(m)                               \
+  do {                                          \
+    out->m = (int)strtol(cp, &eos, 10);         \
+    if (!eos || eos == cp)                      \
+      return -1;                                \
+    cp = eos;                                   \
+  } while (0)
+
+#define DOT()                                   \
+  do {                                          \
+    if (*cp != '.')                             \
+      return -1;                                \
+    ++cp;                                       \
+  } while (0)
+
+  NUMBER(major);
+  DOT();
+  NUMBER(minor);
+  if (*cp == 0)
     return 0;
-  }
-  cp = eos;
+  else if (*cp == '-')
+    goto status_tag;
+  DOT();
+  NUMBER(micro);
 
   /* Get status */
-  if (*cp == '.') {
-    out->status = VER_RELEASE;
+  if (*cp == 0) {
+    return 0;
+  } else if (*cp == '.') {
     ++cp;
+  } else if (*cp == '-') {
+    goto status_tag;
   } else if (0==strncmp(cp, "pre", 3)) {
     out->status = VER_PRE;
     cp += 3;
@@ -4251,11 +4261,9 @@ tor_version_parse(const char *s, tor_version_t *out)
     return -1;
   }
 
-  /* Get patchlevel */
-  out->patchlevel = (int) strtol(cp,&eos,10);
-  if (!eos || eos==cp) return -1;
-  cp = eos;
+  NUMBER(patchlevel);
 
+ status_tag:
   /* Get status tag. */
   if (*cp == '-' || *cp == '.')
     ++cp;
@@ -4291,6 +4299,8 @@ tor_version_parse(const char *s, tor_version_t *out)
   }
 
   return 0;
+#undef NUMBER
+#undef DOT
 }
 
 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index c03b63b..61484f5 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -337,6 +337,42 @@ test_dir_versions(void)
   test_eq(VER_RELEASE, ver1.status);
   test_streq("", ver1.status_tag);
 
+  test_eq(0, tor_version_parse("10.1", &ver1));
+  test_eq(10, ver1.major);
+  test_eq(1, ver1.minor);
+  test_eq(0, ver1.micro);
+  test_eq(0, ver1.patchlevel);
+  test_eq(VER_RELEASE, ver1.status);
+  test_streq("", ver1.status_tag);
+  test_eq(0, tor_version_parse("5.99.999", &ver1));
+  test_eq(5, ver1.major);
+  test_eq(99, ver1.minor);
+  test_eq(999, ver1.micro);
+  test_eq(0, ver1.patchlevel);
+  test_eq(VER_RELEASE, ver1.status);
+  test_streq("", ver1.status_tag);
+  test_eq(0, tor_version_parse("10.1-alpha", &ver1));
+  test_eq(10, ver1.major);
+  test_eq(1, ver1.minor);
+  test_eq(0, ver1.micro);
+  test_eq(0, ver1.patchlevel);
+  test_eq(VER_RELEASE, ver1.status);
+  test_streq("alpha", ver1.status_tag);
+  test_eq(0, tor_version_parse("2.1.700-alpha", &ver1));
+  test_eq(2, ver1.major);
+  test_eq(1, ver1.minor);
+  test_eq(700, ver1.micro);
+  test_eq(0, ver1.patchlevel);
+  test_eq(VER_RELEASE, ver1.status);
+  test_streq("alpha", ver1.status_tag);
+  test_eq(0, tor_version_parse("1.6.8-alpha-dev", &ver1));
+  test_eq(1, ver1.major);
+  test_eq(6, ver1.minor);
+  test_eq(8, ver1.micro);
+  test_eq(0, ver1.patchlevel);
+  test_eq(VER_RELEASE, ver1.status);
+  test_streq("alpha-dev", ver1.status_tag);
+
 #define tt_versionstatus_op(vs1, op, vs2)                               \
   tt_assert_test_type(vs1,vs2,#vs1" "#op" "#vs2,version_status_t,       \
                       (val1_ op val2_),"%d",TT_EXIT_TEST_FUNCTION)





More information about the tor-commits mailing list