[tor-commits] [bridgedb/master] Refactor networkstatus.parseALine() raise/return more sane values.

isis at torproject.org isis at torproject.org
Sun Jan 12 06:06:34 UTC 2014


commit df4b5a48abba5b6987070894230182018af09596
Author: Isis Lovecruft <isis at torproject.org>
Date:   Fri Nov 22 01:15:11 2013 +0000

    Refactor networkstatus.parseALine() raise/return more sane values.
    
    There were some cases raised within the unittests where, when the IP
    address had failed to parse, `networkstatus.parseALine()` would return
    an `addr.PortList` and `None` (for the IP). Having a PortList without an
    IP address is useless, so instead we should deal with parsing the IP
    first, and checking its validity. Then, if we have the IP, we should
    parse and check the ports, then create the PortList.
    
     * CHANGE logic of the bridgedb.parse.networkstatus.parseALine()
       function so that all of the parsing takes place in one `try:`
       block, and the `except`s catch any and all raised errors, logging
       messages and reseting variables to None as appropriate.
    
     * ADD a FutureWarning if we ever see a networkstatus document with a
       valid IPc4 address as one of its `ORAddress`es, because this means
       that tor/torspec and the descriptors have changed format.
    
     * CHANGE networkstatus.parseALine() to only return a PortList if an IP
       address was successfully parsed.
---
 lib/bridgedb/parse/networkstatus.py |   55 ++++++++++++++++++++++-------------
 1 file changed, 35 insertions(+), 20 deletions(-)

diff --git a/lib/bridgedb/parse/networkstatus.py b/lib/bridgedb/parse/networkstatus.py
index 294e465..cb08bef 100644
--- a/lib/bridgedb/parse/networkstatus.py
+++ b/lib/bridgedb/parse/networkstatus.py
@@ -174,38 +174,53 @@ def parseALine(line, fingerprint=None):
         :class:`bridgedb.parse.addr.PortList`.
     """
     ip = None
-    address = None
     portlist = None
 
     if not line.startswith('a '):
-        logging.error("Networkstatus parser received non 'a'-line for %r:"
-                      % (fingerprint or 'Unknown'))
-        logging.error("\t%r" % line)
-        return address, portlist
+        logging.error("Networkstatus parser received non 'a'-line for %r:"\
+                      "  %r" % (fingerprint or 'Unknown', line))
+        return ip, portlist
 
     line = line[2:] # Chop off the 'a '
 
     try:
         ip, portlist = line.rsplit(':', 1)
-    except (IndexError, ValueError, addr.InvalidPort) as error:
-        logging.exception(error)
-        raise NetworkstatusParsingError(
-            "Parsing networkstatus 'a'-line for %r failed! Line: %r"
-            %(fingerprint, line))
-    else:
-        ip = ip.strip('[]') 
-        address = addr.isIPAddress(ip)
-        if not ip:
+    except ValueError as error:
+        logging.error("Bad separator in networkstatus 'a'-line: %r" % line)
+        return (None, None)
+
+    if ip.startswith('[') and ip.endswith(']'):
+        ip = ip.strip('[]')
+
+    try:
+        if not addr.isIPAddress(ip):
             raise NetworkstatusParsingError(
                 "Got invalid IP Address in networkstatus 'a'-line for %r: %r"
-                % (fingerprint, ip))
-        
-        portlist = addr.PortList(portlist)
+                % (fingerprint or 'Unknown', line))
 
-    logging.debug("Parsed networkstatus ORAddress line for %r:" % fingerprint)
-    logging.debug("\tAddress: %s  \tPorts: %s" % (address, portlist))
+        if addr.isIPv4(ip):
+            warnings.warn(FutureWarning(
+                "Got IPv4 address in networkstatus 'a'-line! "\
+                "Networkstatus document format may have changed!"))
+    except NetworkstatusParsingError as error:
+        logging.error(error)
+        ip, portlist = None, None
 
-    return address, portlist
+    try:
+        portlist = addr.PortList(portlist)
+        if not portlist:
+            raise NetworkstatusParsingError(
+                "Got invalid portlist in 'a'-line for %r!\n  Line: %r"
+                % (fingerprint or 'Unknown', line))
+    except (addr.InvalidPort, NetworkstatusParsingError) as error:
+        logging.exception(error)
+        portlist = None
+    else:
+        logging.debug("Parsed networkstatus ORAddress line for %r:"\
+                      "\n  Address: %s  \tPorts: %s"
+                      % (fingerprint or 'Unknown', ip, portlist))
+    finally:
+        return (ip, portlist)
 
 def parseSLine(line):
     """Parse an 's'-line from a bridge networkstatus document.





More information about the tor-commits mailing list