dissect-wireshark: fix tvb overflow

refs #3603

Change-Id: Ibb56398e59f70a8498329def0344a0cf67ee375e
diff --git a/tests/dissect-wireshark/README.md b/tests/dissect-wireshark/README.md
index 701f512..93bbc1d 100644
--- a/tests/dissect-wireshark/README.md
+++ b/tests/dissect-wireshark/README.md
@@ -105,3 +105,13 @@
 
 Expected result of the dissection:
 - interest packet is dissected from packet 6.
+
+### 8. tvb Overflow
+
+Trace file: `bug3603.pcap`
+
+Trace summary: A Data whose payload could be read as incomplete TLV and may cause tvb overflow
+if parser does not check packet length.
+
+Expected result of the dissection:
+- data packet is dissected at packet 12 without Lua error.
diff --git a/tests/dissect-wireshark/bug3603.pcap b/tests/dissect-wireshark/bug3603.pcap
new file mode 100755
index 0000000..436a264
--- /dev/null
+++ b/tests/dissect-wireshark/bug3603.pcap
Binary files differ
diff --git a/tools/dissect-wireshark/ndn.lua b/tools/dissect-wireshark/ndn.lua
index 6872d48..b6f31c7 100644
--- a/tools/dissect-wireshark/ndn.lua
+++ b/tools/dissect-wireshark/ndn.lua
@@ -1,4 +1,4 @@
--- Copyright (c) 2015,  Regents of the University of California.
+-- Copyright (c) 2015-2016,  Regents of the University of California.
 --
 -- This file is part of ndn-tools (Named Data Networking Essential Tools).
 -- See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -238,16 +238,22 @@
 -----------------------------------------------------
 
 function readVarNumber(tvb, offset)
+   if offset >= tvb:len() then
+      return 0, 0
+   end
+
    local firstOctet = tvb(offset, 1):uint()
    if (firstOctet < 253) then
       return firstOctet, 1
-   elseif (firstOctet == 253) then
+   elseif (firstOctet == 253) and (offset + 3 < tvb:len()) then
       return tvb(offset + 1, 2):uint(), 3
-   elseif (firstOctet == 254) then
+   elseif (firstOctet == 254) and (offset + 5 < tvb:len()) then
       return tvb(offset + 1, 4):uint(), 5
-   elseif (firstOctet == 255) then
-      return tvb(offset + 1, 8):uint64(), 6
+   elseif (firstOctet == 255) and (offset + 9 < tvb:len()) then
+      return tvb(offset + 1, 8):uint64(), 9
    end
+
+   return 0, 0
 end
 
 function getBlock(tvb, offset)
@@ -256,7 +262,14 @@
    block.offset = offset
 
    block.type, block.typeLen = readVarNumber(block.tvb, block.offset)
+   if block.typeLen == 0 then
+      return nil
+   end
+
    block.length, block.lengthLen = readVarNumber(block.tvb, block.offset + block.typeLen)
+   if block.lengthLen == 0 then
+      return nil
+   end
 
    block.size = block.typeLen + block.lengthLen + block.length
 
@@ -277,7 +290,7 @@
    while offset + 2 < tvb:len() do
       local block = getBlock(tvb, offset)
 
-      if canBeValidNdnPacket(block) then
+      if (block ~= nil) and canBeValidNdnPacket(block) then
          return block
       end
 
@@ -292,8 +305,11 @@
    local subBlocks = {}
 
    while valueLeft > 0 do
-      local child = getBlock(block.tvb,
-                             block.offset + block.typeLen + block.lengthLen + (block.length - valueLeft))
+      local offset = block.offset + block.typeLen + block.lengthLen + (block.length - valueLeft)
+      local child = getBlock(block.tvb, offset)
+      if child == nil then
+         return nil
+      end
 
       valueLeft = valueLeft - child.size
       table.insert(subBlocks, child)