diff --git a/dpkt/tcp.py b/dpkt/tcp.py index cdfb288..fe1a3b9 100644 --- a/dpkt/tcp.py +++ b/dpkt/tcp.py @@ -99,14 +99,54 @@ def parse_opts(buf): o = ord(buf[0]) if o > TCP_OPT_NOP: try: - l = ord(buf[1]) + # advance buffer at least 2 bytes = 1 type + 1 length + l = max(2, ord(buf[1])) d, buf = buf[2:l], buf[l:] - except ValueError: + except (IndexError, ValueError): # print 'bad option', repr(str(buf)) opts.append(None) # XXX break else: + # options 0 and 1 are not followed by length byte d, buf = '', buf[1:] opts.append((o, d)) return opts + +def test_parse_opts(): + # normal scenarios + buf = '\x02\x04\x23\x00\x01\x01\x04\x02' + opts = parse_opts(buf) + assert opts == [ + (TCP_OPT_MSS, '\x23\x00'), + (TCP_OPT_NOP, ''), + (TCP_OPT_NOP, ''), + (TCP_OPT_SACKOK, '') + ] + + buf = '\x01\x01\x05\x0a\x37\xf8\x19\x70\x37\xf8\x29\x78' + opts = parse_opts(buf) + assert opts == [ + (TCP_OPT_NOP, ''), + (TCP_OPT_NOP, ''), + (TCP_OPT_SACK, '\x37\xf8\x19\x70\x37\xf8\x29\x78') + ] + + # test a zero-length option + buf = '\x02\x00\x01' + opts = parse_opts(buf) + assert opts == [ + (TCP_OPT_MSS, ''), + (TCP_OPT_NOP, '') + ] + + # test a one-byte malformed option + buf = '\xff' + opts = parse_opts(buf) + assert opts == [None] + + +if __name__ == '__main__': + # Runs all the test associated with this class/file + test_parse_opts() + print 'Tests Successful...'