1-- $Id: heavy.lua,v 1.7 2017/12/29 15:42:15 roberto Exp $
  2-- See Copyright Notice in file all.lua
  3
  4local function teststring ()
  5  print("creating a string too long")
  6  do
  7    local a = "x"
  8    local st, msg = pcall(function ()
  9      while true do
 10        a = a .. a.. a.. a.. a.. a.. a.. a.. a.. a
 11         .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
 12         .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
 13         .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
 14         .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
 15         .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
 16         .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
 17         .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
 18         .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
 19         .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
 20         print(string.format("string with %d bytes", #a))
 21      end
 22    end)
 23    assert(not st and
 24      (string.find(msg, "string length overflow") or
 25       string.find(msg, "not enough memory")))
 26    print("string length overflow with " .. #a * 100)
 27  end
 28  print('+')
 29end
 30
 31local function loadrep (x, what)
 32  local p = 1<<20
 33  local s = string.rep(x, p)
 34  local count = 0
 35  local function f()
 36    count = count + p
 37    if count % (0x80*p) == 0 then
 38      io.stderr:write("(", count // 2^20, " M)")
 39    end
 40    return s
 41  end
 42  local st, msg = load(f, "=big")
 43  print("\nmemory: ", collectgarbage'count' * 1024)
 44  msg = string.match(msg, "^[^\n]+")    -- get only first line
 45  print(string.format("total: 0x%x %s ('%s')", count, what, msg))
 46  return st, msg
 47end
 48
 49
 50function controlstruct ()
 51  print("control structure too long")
 52  local lim = ((1 << 24) - 2) // 3
 53  local s = string.rep("a = a + 1\n", lim)
 54  s = "while true do " .. s .. "end"
 55  assert(load(s))
 56  print("ok with " .. lim .. " lines")
 57  lim = lim + 3
 58  s = string.rep("a = a + 1\n", lim)
 59  s = "while true do " .. s .. "end"
 60  local st, msg = load(s)
 61  assert(not st and string.find(msg, "too long"))
 62  print(msg)
 63end
 64
 65
 66function manylines ()
 67  print("loading chunk with too many lines")
 68  local st, msg = loadrep("\n", "lines")
 69  assert(not st and string.find(msg, "too many lines"))
 70  print('+')
 71end
 72
 73
 74function hugeid ()
 75  print("loading chunk with huge identifier")
 76  local st, msg = loadrep("a", "chars")
 77  assert(not st and 
 78    (string.find(msg, "lexical element too long") or
 79     string.find(msg, "not enough memory")))
 80  print('+')
 81end
 82
 83function toomanyinst ()
 84  print("loading chunk with too many instructions")
 85  local st, msg = loadrep("a = 10; ", "instructions")
 86  print('+')
 87end
 88
 89
 90local function loadrepfunc (prefix, f)
 91  local count = -1
 92  local function aux ()
 93    count = count + 1
 94    if count == 0 then
 95      return prefix
 96    else
 97      if count % (0x100000) == 0 then
 98        io.stderr:write("(", count // 2^20, " M)")
 99      end
100      return f(count)
101    end
102  end
103  local st, msg = load(aux, "k")
104  print("\nmemory: ", collectgarbage'count' * 1024)
105  msg = string.match(msg, "^[^\n]+")    -- get only first line
106  print("expected error: ", msg)
107end
108
109
110function toomanyconst ()
111  print("loading function with too many constants")
112  loadrepfunc("function foo () return {0,",
113      function (n)
114        -- convert 'n' to a string in the format [["...",]],
115        -- where '...' is a kind of number in base 128
116        -- (in a range that does not include either the double quote
117        -- and the escape.)
118        return string.char(34,
119          ((n // 128^0) & 127) + 128,
120          ((n // 128^1) & 127) + 128,
121          ((n // 128^2) & 127) + 128,
122          ((n // 128^3) & 127) + 128,
123          ((n // 128^4) & 127) + 128,
124          34, 44)
125      end)
126end
127
128
129function toomanystr ()
130  local a = {}
131  local st, msg = pcall(function ()
132    for i = 1, math.huge do
133      if i % (0x100000) == 0 then
134        io.stderr:write("(", i // 2^20, " M)")
135      end
136      a[i] = string.pack("I", i)
137     end
138  end)
139  local size = #a
140  a = collectgarbage'count'
141  print("\nmemory:", a * 1024)
142  print("expected error:", msg)
143  print("size:", size)
144end
145
146
147function toomanyidx ()
148  local a = {}
149  local st, msg = pcall(function ()
150    for i = 1, math.huge do
151      if i % (0x100000) == 0 then
152        io.stderr:write("(", i // 2^20, " M)")
153      end
154      a[i] = i
155     end
156  end)
157  print("\nmemory: ", collectgarbage'count' * 1024)
158  print("expected error: ", msg)
159  print("size:", #a)
160end
161  
162
163
164-- teststring()
165-- controlstruct()
166-- manylines()
167-- hugeid()
168-- toomanyinst()
169-- toomanyconst()
170-- toomanystr()
171toomanyidx()
172
173print "OK"