commit db87c88965806ec13f9888c220879af45fc65e44 Author: Damian Johnson atagar@torproject.org Date: Sat Sep 8 11:54:33 2012 -0700
Validating that fields aren't duplicated
Almost all of the fields in a network status document can only appear once. Checking that this is a case. This also includes a unit test for the validation. I'm a little surprised that the old parser doesn't choke on duplicated content, but I'm about to replace it so probably not worth investigating. --- stem/descriptor/networkstatus.py | 19 ++++++++++++++++ test/unit/descriptor/networkstatus/document.py | 28 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py index 5676c16..2140b4d 100644 --- a/stem/descriptor/networkstatus.py +++ b/stem/descriptor/networkstatus.py @@ -297,8 +297,27 @@ class NetworkStatusDocument(stem.descriptor.Descriptor): raise ValueError("Network status documents must have a 'vote-status' line to say if they're a vote or consensus")
is_consensus = header_entries['vote-status'][0][0] == "consensus" + is_vote = not is_consensus self._check_for_missing_and_disallowed_fields(is_consensus, header_entries, footer_entries) self._check_for_misordered_fields(is_consensus, header_entries, footer_entries) + + known_fields = [attr[0] for attr in HEADER_STATUS_DOCUMENT_FIELDS + FOOTER_STATUS_DOCUMENT_FIELDS] + content = header + '\n' + footer + + entries = dict() + entries.update(header_entries) + entries.update(footer_entries) + + for keyword, values in entries.items(): + value, block_contents = values[0] + line = "%s %s" % (keyword, value) + + # All known fields can only appear once except... + # * 'directory-signature' in a consensus + + if validate and len(values) > 1 and keyword in known_fields: + if not (keyword == 'directory-signature' and is_consensus): + raise ValueError("Network status documents can only have a single '%s' line, got %i:\n%s" % (keyword, len(values), content))
def _parse_old(self, raw_content, validate): # preamble diff --git a/test/unit/descriptor/networkstatus/document.py b/test/unit/descriptor/networkstatus/document.py index d2bbe90..ef77391 100644 --- a/test/unit/descriptor/networkstatus/document.py +++ b/test/unit/descriptor/networkstatus/document.py @@ -186,4 +186,32 @@ class TestNetworkStatusDocument(unittest.TestCase): content = "\n".join(test_lines) self.assertRaises(ValueError, NetworkStatusDocument, content) NetworkStatusDocument(content, False) # constructs without validation + + def test_duplicate_fields(self): + """ + Almost all fields can only appear once. Checking that duplicates cause + validation errors. + """ + + for is_consensus in (True, False): + attr = {"vote-status": "consensus"} if is_consensus else {"vote-status": "vote"} + lines = get_network_status_document(attr).split("\n") + + for i in xrange(len(lines)): + # Stop when we hit the 'directory-signature' for a couple reasons... + # - that is the one field that can validly appear multiple times + # - after it is a crypto blob, which won't trigger this kind of + # validation failure + + test_lines = list(lines) + if test_lines[i].startswith("directory-signature "): + break + + # duplicates the line + test_lines.insert(i, test_lines[i]) + + content = "\n".join(test_lines) + self.assertRaises(ValueError, NetworkStatusDocument, content) + NetworkStatusDocument(content, False) # constructs without validation +
tor-commits@lists.torproject.org