mirror of
https://github.com/nmap/nmap.git
synced 2026-02-07 22:16:33 +00:00
Use bdecode function to parse buffer instead of reimplementing. Fixes #1203
This commit is contained in:
@@ -152,6 +152,7 @@ bdecode = function(buf)
|
||||
cur.ref = t
|
||||
table.insert(stack, cur)
|
||||
cur.ref.type="list"
|
||||
cur.ref.start = pos
|
||||
|
||||
while true do
|
||||
if pos == len or (len-pos)==-1 then break end
|
||||
@@ -180,6 +181,7 @@ bdecode = function(buf)
|
||||
cur = {}
|
||||
cur.type = "list"
|
||||
cur.ref = new_list
|
||||
cur.ref.start = pos
|
||||
table.insert(stack, cur)
|
||||
pos = pos+1
|
||||
|
||||
@@ -192,11 +194,13 @@ bdecode = function(buf)
|
||||
cur = {}
|
||||
cur.type = "dict"
|
||||
cur.ref = new_dict
|
||||
cur.ref.start = pos
|
||||
table.insert(stack, cur)
|
||||
pos = pos+1
|
||||
|
||||
--escape from the list
|
||||
elseif "e" == string.char(buf:byte(pos)) then
|
||||
stack[#stack].ref.endpos = pos
|
||||
table.remove(stack, #stack)
|
||||
cur = stack[#stack]
|
||||
if not cur then return nil, "Problem with list closure:", pos end
|
||||
@@ -218,6 +222,7 @@ bdecode = function(buf)
|
||||
if not str then return nil, "Error parsing string.", pos end
|
||||
item.key = str
|
||||
elseif "e" == string.char(buf:byte(pos)) then
|
||||
stack[#stack].ref.endpos = pos
|
||||
table.remove(stack, #stack)
|
||||
cur = stack[#stack]
|
||||
if not cur then return nil, "Problem with list closure:", pos end
|
||||
@@ -256,6 +261,7 @@ bdecode = function(buf)
|
||||
cur = {}
|
||||
cur.type = "list"
|
||||
cur.ref = item.value
|
||||
cur.ref.start = pos
|
||||
|
||||
table.insert(stack, cur)
|
||||
pos = pos+1
|
||||
@@ -269,12 +275,14 @@ bdecode = function(buf)
|
||||
cur = {}
|
||||
cur.type = "dict"
|
||||
cur.ref = item.value
|
||||
cur.ref.start = pos
|
||||
|
||||
table.insert(stack, cur)
|
||||
pos = pos+1
|
||||
|
||||
--escape from the dict
|
||||
elseif "e" == string.char(buf:byte(pos)) then
|
||||
stack[#stack].ref.endpos = pos
|
||||
table.remove(stack, #stack)
|
||||
cur = stack[#stack]
|
||||
if not cur then return false, "Problem with dict closure", pos end
|
||||
@@ -752,200 +760,18 @@ Torrent =
|
||||
-- This function is similar to the bdecode function but it has a few
|
||||
-- additions for calculating torrent file specific fields
|
||||
parse_buffer = function(self)
|
||||
local buf = self.buffer
|
||||
|
||||
local len = #buf
|
||||
|
||||
-- the main table
|
||||
local t = {}
|
||||
self.tor_struct = t
|
||||
local stack = {}
|
||||
|
||||
local pos = 1
|
||||
local cur = {}
|
||||
cur.type = "list"
|
||||
cur.ref = t
|
||||
table.insert(stack, cur)
|
||||
cur.ref.type="list"
|
||||
|
||||
-- starting and ending position of the info dict
|
||||
local info_pos_start, info_pos_end, info_buf_count = nil, nil, 0
|
||||
|
||||
while true do
|
||||
if pos == len or (len-pos)==-1 then break end
|
||||
|
||||
if cur.type == "list" then
|
||||
-- next element is a string
|
||||
if tonumber( string.char( buf:byte(pos) ) ) then
|
||||
local str
|
||||
str, pos = bdec_string(buf, pos)
|
||||
if not str then return nil, "Error parsing string", pos end
|
||||
table.insert(cur.ref, str)
|
||||
|
||||
-- next element is a number
|
||||
elseif "i" == string.char(buf:byte(pos)) then
|
||||
local num
|
||||
num, pos = bdec_number(buf, pos)
|
||||
if not num then return nil, "Error parsing number", pos end
|
||||
table.insert(cur.ref, num)
|
||||
|
||||
-- next element is a list
|
||||
elseif "l" == string.char(buf:byte(pos)) then
|
||||
if info_pos_start and (not info_pos_end) then
|
||||
info_buf_count = info_buf_count +1
|
||||
end
|
||||
|
||||
local new_list = {}
|
||||
new_list.type="list"
|
||||
table.insert(cur.ref, new_list)
|
||||
|
||||
cur = {}
|
||||
cur.type = "list"
|
||||
cur.ref = new_list
|
||||
table.insert(stack, cur)
|
||||
pos = pos+1
|
||||
|
||||
--next element is a dict
|
||||
elseif "d" == string.char(buf:byte(pos)) then
|
||||
if info_pos_start and (not info_pos_end) then
|
||||
info_buf_count = info_buf_count +1
|
||||
end
|
||||
|
||||
local new_dict = {}
|
||||
new_dict.type = "dict"
|
||||
table.insert(cur.ref, new_dict)
|
||||
|
||||
cur = {}
|
||||
cur.type = "dict"
|
||||
cur.ref = new_dict
|
||||
table.insert(stack, cur)
|
||||
pos = pos+1
|
||||
|
||||
--escape from the list
|
||||
elseif "e" == string.char(buf:byte(pos)) then
|
||||
if info_buf_count == 0 then
|
||||
info_pos_end = pos-1
|
||||
end
|
||||
if info_pos_start and (not info_pos_end) then
|
||||
info_buf_count = info_buf_count -1
|
||||
end
|
||||
|
||||
table.remove(stack, #stack)
|
||||
cur = stack[#stack]
|
||||
if not cur then return nil, "Problem with list closure:", pos end
|
||||
pos = pos+1
|
||||
else
|
||||
return nil, "Unknown type found.", pos
|
||||
end
|
||||
|
||||
elseif cur.type == "dict" then
|
||||
local item = {} -- {key = <string>, value = <.*>}
|
||||
-- key
|
||||
if tonumber( string.char( buf:byte(pos) ) ) then
|
||||
local str
|
||||
local tmp_pos = pos
|
||||
str, pos = bdec_string(buf, pos)
|
||||
if not str then return nil, "Error parsing string.", pos end
|
||||
item.key = str
|
||||
-- fill the info_pos_start
|
||||
if item.key == "info" and not info_pos_start then info_pos_start = pos end
|
||||
|
||||
elseif "e" == string.char(buf:byte(pos)) then
|
||||
if info_buf_count == 0 then
|
||||
info_pos_end = pos-1
|
||||
end
|
||||
if info_pos_start and (not info_pos_end) then
|
||||
info_buf_count = info_buf_count -1
|
||||
end
|
||||
|
||||
table.remove(stack, #stack)
|
||||
cur = stack[#stack]
|
||||
if not cur then return nil, "Problem with list closure:", pos end
|
||||
pos = pos+1
|
||||
|
||||
else
|
||||
return nil, "A dict key has to be a string or escape.", pos
|
||||
end
|
||||
|
||||
-- value
|
||||
-- next element is a string
|
||||
if tonumber( string.char( buf:byte(pos) ) ) then
|
||||
local str
|
||||
str, pos = bdec_string(buf, pos)
|
||||
if not str then return nil, "Error parsing string.", pos end
|
||||
item.value = str
|
||||
table.insert(cur.ref, item)
|
||||
|
||||
--next element is a number
|
||||
elseif "i" == string.char(buf:byte(pos)) then
|
||||
local num
|
||||
num, pos = bdec_number(buf, pos)
|
||||
if not num then return nil, "Error parsing number.", pos end
|
||||
item.value = num
|
||||
table.insert(cur.ref, item)
|
||||
|
||||
-- next element is a list
|
||||
elseif "l" == string.char(buf:byte(pos)) then
|
||||
if info_pos_start and (not info_pos_end) then
|
||||
info_buf_count = info_buf_count +1
|
||||
end
|
||||
|
||||
item.value = {}
|
||||
item.value.type = "list"
|
||||
table.insert(cur.ref, item)
|
||||
|
||||
cur = {}
|
||||
cur.type = "list"
|
||||
cur.ref = item.value
|
||||
|
||||
table.insert(stack, cur)
|
||||
pos = pos+1
|
||||
|
||||
--next element is a dict
|
||||
elseif "d" == string.char(buf:byte(pos)) then
|
||||
if info_pos_start and (not info_pos_end) then
|
||||
info_buf_count = info_buf_count +1
|
||||
end
|
||||
|
||||
item.value = {}
|
||||
item.value.type = "dict"
|
||||
table.insert(cur.ref, item)
|
||||
|
||||
cur = {}
|
||||
cur.type = "dict"
|
||||
cur.ref = item.value
|
||||
|
||||
table.insert(stack, cur)
|
||||
pos = pos+1
|
||||
|
||||
--escape from the dict
|
||||
elseif "e" == string.char(buf:byte(pos)) then
|
||||
if info_buf_count == 0 then
|
||||
info_pos_end = pos-1
|
||||
end
|
||||
if info_pos_start and (not info_pos_end) then
|
||||
info_buf_count = info_buf_count -1
|
||||
end
|
||||
|
||||
table.remove(stack, #stack)
|
||||
cur = stack[#stack]
|
||||
if not cur then return false, "Problem with dict closure", pos end
|
||||
pos = pos+1
|
||||
else
|
||||
return false, "Error parsing file, unknown type found", pos
|
||||
end
|
||||
else
|
||||
return false, "Invalid type of structure. Fix the code."
|
||||
end
|
||||
end -- while(true)
|
||||
|
||||
-- next(stack) is never gonna be nil because we're always in the main list
|
||||
-- next(stack, next(stack)) should be nil if we're in the main list
|
||||
if next(stack, next(stack)) then
|
||||
return false, "Probably file incorrect format"
|
||||
local status, t = bdecode(self.buffer)
|
||||
if not status then
|
||||
return status, t
|
||||
end
|
||||
self.tor_struct = t
|
||||
|
||||
self.info_buf = buf:sub(info_pos_start, info_pos_end)
|
||||
for _, i in ipairs(t[1]) do
|
||||
if i.key == "info" then
|
||||
self.info_buf = self.buffer:sub(i.value.start, i.value.endpos)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end,
|
||||
|
||||
Reference in New Issue
Block a user