summaryrefslogtreecommitdiffstats
path: root/nselib/nsedebug.lua
blob: 9effa3928321f973312f2b3145ec5a70b9a49974 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
---
-- Debugging functions for Nmap scripts.
--
-- This module contains various handy functions for debugging. These should
-- never be used for actual results, only during testing.
--
-- @copyright Same as Nmap--See https://nmap.org/book/man-legal.html

local coroutine = require "coroutine"
local debug = require "debug"
local io = require "io"
local math = require "math"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"
_ENV = stdnse.module("nsedebug", stdnse.seeall)

local EMPTY = {}; -- Empty constant table

---
-- Converts an arbitrary data type into a string. Will recursively convert
-- tables. This can be very useful for debugging.
--
--@param data   The data to convert.
--@param indent (optional) The number of times to indent the line. Default
--              is 0.
--@return A string representation of a data, will be one or more full lines.
function tostr(data, indent)
  local str

  if(indent == nil) then
    indent = 0
  end

  -- Check the type
  local typ = type(data)
  if(typ == "nil" or typ == "number" or typ == "boolean" or typ == "function" or typ == "thread" or typ == "userdata") then
    str = {(" "):rep(indent), tostring(data), "\n"}
  elseif(type(data) == "string") then
    str = {(" "):rep(indent), string.format("%q", data), "\n"}
  elseif(type(data) == "table") then
    local i, v
    str = {}
    for i, v in pairs(data) do
      -- Check for a table in a table
      str[#str+1] = (" "):rep(indent)
      str[#str+1] = tostring(i)
      if(type(v) == "table") then
        str[#str+1] = ":\n"
        str[#str+1] = tostr(v, indent + 2)
      else
        str[#str+1] = ": "
        str[#str+1] = tostr(v, 0)
      end
    end
  else
    stdnse.debug1("Error: unknown data type: %s", type(data))
  end

  return table.concat(str)
end

--- Print out a string in hex, for debugging.
--
--@param str The data to print in hex.
function print_hex(str)

  -- Prints out the full lines
  for line=1, #str/16, 1 do
    io.write(string.format("%08x ", (line - 1) * 16))

    -- Loop through the string, printing the hex
    for char=1, 16, 1 do
      local ch = string.byte(str, ((line - 1) * 16) + char)
      io.write(string.format("%02x ", ch))
    end

    io.write("   ")

    -- Loop through the string again, this time the ascii
    for char=1, 16, 1 do
      local ch = string.byte(str, ((line - 1) * 16) + char)
      if ch < 0x20 or ch > 0x7f then
        ch = string.byte(".", 1)
      end
      io.write(string.format("%c", ch))
    end

    io.write("\n")
  end

  -- Prints out the final, partial line
  if (#str % 16 ~= 0) then
    local line = math.floor((#str/16)) + 1
    io.write(string.format("%08x ", (line - 1) * 16))

    for char=1, #str % 16, 1 do
      local ch = string.byte(str, ((line - 1) * 16) + char)
      io.write(string.format("%02x ", ch))
    end
    io.write(string.rep("   ", 16 - (#str % 16)));
    io.write("   ")

    for char=1, #str % 16, 1 do
      local ch = string.byte(str, ((line - 1) * 16) + char)
      if ch < 0x20 or ch > 0x7f then
        ch = string.byte(".", 1)
      end
      io.write(string.format("%c", ch))
    end

    io.write("\n")
  end

  -- Print out the length
  io.write(string.format("         Length: %d [0x%x]\n", #str, #str))

end

---Print out a stacktrace. The stacktrace will naturally include this function call.
function print_stack()
  local thread = coroutine.running()
  local trace = debug.traceback(thread);
  if trace ~= "stack traceback:" then
    print(thread, "\n", trace, "\n");
  end
end



return _ENV;