errors.lua 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. -- $Id: testes/errors.lua $
  2. -- See Copyright Notice in file lua.h
  3. print("testing errors")
  4. local debug = require"debug"
  5. -- avoid problems with 'strict' module (which may generate other error messages)
  6. local mt = getmetatable(_G) or {}
  7. local oldmm = mt.__index
  8. mt.__index = nil
  9. local function checkerr (msg, f, ...)
  10. local st, err = pcall(f, ...)
  11. assert(not st and string.find(err, msg))
  12. end
  13. local function doit (s)
  14. local f, msg = load(s)
  15. if not f then return msg end
  16. local cond, msg = pcall(f)
  17. return (not cond) and msg
  18. end
  19. local function checkmessage (prog, msg, debug)
  20. local m = doit(prog)
  21. if debug then print(m, msg) end
  22. assert(string.find(m, msg, 1, true))
  23. end
  24. local function checksyntax (prog, extra, token, line)
  25. local msg = doit(prog)
  26. if not string.find(token, "^<%a") and not string.find(token, "^char%(")
  27. then token = "'"..token.."'" end
  28. token = string.gsub(token, "(%p)", "%%%1")
  29. local pt = string.format([[^%%[string ".*"%%]:%d: .- near %s$]],
  30. line, token)
  31. assert(string.find(msg, pt))
  32. assert(string.find(msg, msg, 1, true))
  33. end
  34. -- test error message with no extra info
  35. assert(doit("error('hi', 0)") == 'hi')
  36. -- test nil error message
  37. assert(doit("error()") == "<no error object>")
  38. -- test common errors/errors that crashed in the past
  39. assert(doit("table.unpack({}, 1, n=2^30)"))
  40. assert(doit("a=math.sin()"))
  41. assert(not doit("tostring(1)") and doit("tostring()"))
  42. assert(doit"tonumber()")
  43. assert(doit"repeat until 1; a")
  44. assert(doit"return;;")
  45. assert(doit"assert(false)")
  46. assert(doit"assert(nil)")
  47. assert(doit("function a (... , ...) end"))
  48. assert(doit("function a (, ...) end"))
  49. assert(doit("local t={}; t = t[#t] + 1"))
  50. checksyntax([[
  51. local a = {4
  52. ]], "'}' expected (to close '{' at line 1)", "<eof>", 3)
  53. do -- testing errors in goto/break
  54. local function checksyntax (prog, msg, line)
  55. local st, err = load(prog)
  56. assert(string.find(err, "line " .. line))
  57. assert(string.find(err, msg, 1, true))
  58. end
  59. checksyntax([[
  60. ::A:: a = 1
  61. ::A::
  62. ]], "label 'A' already defined", 1)
  63. checksyntax([[
  64. a = 1
  65. goto A
  66. do ::A:: end
  67. ]], "no visible label 'A'", 2)
  68. end
  69. if not T then
  70. (Message or print)
  71. ('\n >>> testC not active: skipping tests for messages in C <<<\n')
  72. else
  73. print "testing memory error message"
  74. local a = {}
  75. for i = 1, 10000 do a[i] = true end -- preallocate array
  76. collectgarbage()
  77. T.totalmem(T.totalmem() + 10000)
  78. -- force a memory error (by a small margin)
  79. local st, msg = pcall(function()
  80. for i = 1, 100000 do a[i] = tostring(i) end
  81. end)
  82. T.totalmem(0)
  83. assert(not st and msg == "not enough" .. " memory")
  84. -- stack space for luaL_traceback (bug in 5.4.6)
  85. local res = T.testC[[
  86. # push 16 elements on the stack
  87. pushnum 1; pushnum 1; pushnum 1; pushnum 1; pushnum 1;
  88. pushnum 1; pushnum 1; pushnum 1; pushnum 1; pushnum 1;
  89. pushnum 1; pushnum 1; pushnum 1; pushnum 1; pushnum 1;
  90. pushnum 1;
  91. # traceback should work with 4 remaining slots
  92. traceback xuxu 1;
  93. return 1
  94. ]]
  95. assert(string.find(res, "xuxu.-main chunk"))
  96. do -- tests for error messages about extra arguments from __call
  97. local function createobj (n)
  98. -- function that raises an error on its n-th argument
  99. local code = string.format("argerror %d 'msg'", n)
  100. local func = T.makeCfunc(code)
  101. -- create a chain of 2 __call objects
  102. local M = setmetatable({}, {__call = func})
  103. M = setmetatable({}, {__call = M})
  104. -- put it as a method for a new object
  105. return {foo = M}
  106. end
  107. _G.a = createobj(1) -- error in first (extra) argument
  108. checkmessage("a:foo()", "bad extra argument #1")
  109. _G.a = createobj(2) -- error in second (extra) argument
  110. checkmessage("a:foo()", "bad extra argument #2")
  111. _G.a = createobj(3) -- error in self (after two extra arguments)
  112. checkmessage("a:foo()", "bad self")
  113. _G.a = createobj(4) -- error in first regular argument (after self)
  114. checkmessage("a:foo()", "bad argument #1")
  115. end
  116. end
  117. -- tests for better error messages
  118. checkmessage("a = {} + 1", "arithmetic")
  119. checkmessage("a = {} | 1", "bitwise operation")
  120. checkmessage("a = {} < 1", "attempt to compare")
  121. checkmessage("a = {} <= 1", "attempt to compare")
  122. checkmessage("aaa=1; bbbb=2; aaa=math.sin(3)+bbbb(3)", "global 'bbbb'")
  123. checkmessage("aaa={}; do local aaa=1 end aaa:bbbb(3)", "method 'bbbb'")
  124. checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'")
  125. assert(not string.find(doit"aaa={13}; local bbbb=1; aaa[bbbb](3)", "'bbbb'"))
  126. checkmessage("aaa={13}; local bbbb=1; aaa[bbbb](3)", "number")
  127. checkmessage("aaa=(1)..{}", "a table value")
  128. -- bug in 5.4.6
  129. checkmessage("a = {_ENV = {}}; print(a._ENV.x + 1)", "field 'x'")
  130. -- a similar bug, since 5.4.0
  131. checkmessage("print(('_ENV').x + 1)", "field 'x'")
  132. _G.aaa, _G.bbbb = nil
  133. -- calls
  134. checkmessage("local a; a(13)", "local 'a'")
  135. checkmessage([[
  136. local a = setmetatable({}, {__add = 34})
  137. a = a + 1
  138. ]], "metamethod 'add'")
  139. checkmessage([[
  140. local a = setmetatable({}, {__lt = {}})
  141. a = a > a
  142. ]], "metamethod 'lt'")
  143. -- tail calls
  144. checkmessage("local a={}; return a.bbbb(3)", "field 'bbbb'")
  145. checkmessage("aaa={}; do local aaa=1 end; return aaa:bbbb(3)", "method 'bbbb'")
  146. checkmessage("aaa = #print", "length of a function value")
  147. checkmessage("aaa = #3", "length of a number value")
  148. _G.aaa = nil
  149. checkmessage("aaa.bbb:ddd(9)", "global 'aaa'")
  150. checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'")
  151. checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'")
  152. checkmessage("local a,b,c; (function () a = b+1.1 end)()", "upvalue 'b'")
  153. assert(not doit"local aaa={bbb={ddd=next}}; aaa.bbb:ddd(nil)")
  154. -- upvalues being indexed do not go to the stack
  155. checkmessage("local a,b,cc; (function () a = cc[1] end)()", "upvalue 'cc'")
  156. checkmessage("local a,b,cc; (function () a.x = 1 end)()", "upvalue 'a'")
  157. checkmessage("local _ENV = {x={}}; a = a + 1", "global 'a'")
  158. checkmessage("BB=1; local aaa={}; x=aaa+BB", "local 'aaa'")
  159. checkmessage("aaa={}; x=3.3/aaa", "global 'aaa'")
  160. checkmessage("aaa=2; BB=nil;x=aaa*BB", "global 'BB'")
  161. checkmessage("aaa={}; x=-aaa", "global 'aaa'")
  162. -- short circuit
  163. checkmessage("aaa=1; local aaa,bbbb=2,3; aaa = math.sin(1) and bbbb(3)",
  164. "local 'bbbb'")
  165. checkmessage("aaa=1; local aaa,bbbb=2,3; aaa = bbbb(1) or aaa(3)",
  166. "local 'bbbb'")
  167. checkmessage("local a,b,c,f = 1,1,1; f((a and b) or c)", "local 'f'")
  168. checkmessage("local a,b,c = 1,1,1; ((a and b) or c)()", "call a number value")
  169. assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'"))
  170. assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'"))
  171. checkmessage("print(print < 10)", "function with number")
  172. checkmessage("print(print < print)", "two function values")
  173. checkmessage("print('10' < 10)", "string with number")
  174. checkmessage("print(10 < '23')", "number with string")
  175. -- float->integer conversions
  176. checkmessage("local a = 2.0^100; x = a << 2", "local a")
  177. checkmessage("local a = 1 >> 2.0^100", "has no integer representation")
  178. checkmessage("local a = 10.1 << 2.0^100", "has no integer representation")
  179. checkmessage("local a = 2.0^100 & 1", "has no integer representation")
  180. checkmessage("local a = 2.0^100 & 1e100", "has no integer representation")
  181. checkmessage("local a = 2.0 | 1e40", "has no integer representation")
  182. checkmessage("local a = 2e100 ~ 1", "has no integer representation")
  183. checkmessage("string.sub('a', 2.0^100)", "has no integer representation")
  184. checkmessage("string.rep('a', 3.3)", "has no integer representation")
  185. checkmessage("return 6e40 & 7", "has no integer representation")
  186. checkmessage("return 34 << 7e30", "has no integer representation")
  187. checkmessage("return ~-3e40", "has no integer representation")
  188. checkmessage("return ~-3.009", "has no integer representation")
  189. checkmessage("return 3.009 & 1", "has no integer representation")
  190. checkmessage("return 34 >> {}", "table value")
  191. checkmessage("aaa = 24 // 0", "divide by zero")
  192. checkmessage("aaa = 1 % 0", "'n%0'")
  193. -- type error for an object which is neither in an upvalue nor a register.
  194. -- The following code will try to index the value 10 that is stored in
  195. -- the metatable, without moving it to a register.
  196. checkmessage("local a = setmetatable({}, {__index = 10}).x",
  197. "attempt to index a number value")
  198. -- numeric for loops
  199. checkmessage("for i = {}, 10 do end", "table")
  200. checkmessage("for i = io.stdin, 10 do end", "FILE")
  201. checkmessage("for i = {}, 10 do end", "initial value")
  202. checkmessage("for i = 1, 'x', 10 do end", "string")
  203. checkmessage("for i = 1, {}, 10 do end", "limit")
  204. checkmessage("for i = 1, {} do end", "limit")
  205. checkmessage("for i = 1, 10, print do end", "step")
  206. checkmessage("for i = 1, 10, print do end", "function")
  207. -- passing light userdata instead of full userdata
  208. _G.D = debug
  209. checkmessage([[
  210. -- create light udata
  211. local x = D.upvalueid(function () return debug end, 1)
  212. D.setuservalue(x, {})
  213. ]], "light userdata")
  214. _G.D = nil
  215. do -- named objects (field '__name')
  216. checkmessage("math.sin(io.input())", "(number expected, got FILE*)")
  217. _G.XX = setmetatable({}, {__name = "My Type"})
  218. assert(string.find(tostring(XX), "^My Type"))
  219. checkmessage("io.input(XX)", "(FILE* expected, got My Type)")
  220. checkmessage("return XX + 1", "on a My Type value")
  221. checkmessage("return ~io.stdin", "on a FILE* value")
  222. checkmessage("return XX < XX", "two My Type values")
  223. checkmessage("return {} < XX", "table with My Type")
  224. checkmessage("return XX < io.stdin", "My Type with FILE*")
  225. _G.XX = nil
  226. if T then -- extra tests for 'luaL_tolstring'
  227. -- bug in 5.4.3; 'luaL_tolstring' with negative indices
  228. local x = setmetatable({}, {__name="TABLE"})
  229. assert(T.testC("Ltolstring -1; return 1", x) == tostring(x))
  230. local a, b = T.testC("pushint 10; Ltolstring -2; return 2", x)
  231. assert(a == 10 and b == tostring(x))
  232. setmetatable(x, {__tostring=function (o)
  233. assert(o == x)
  234. return "ABC"
  235. end})
  236. local a, b, c = T.testC("pushint 10; Ltolstring -2; return 3", x)
  237. assert(a == x and b == 10 and c == "ABC")
  238. end
  239. end
  240. -- global functions
  241. checkmessage("(io.write or print){}", "io.write")
  242. checkmessage("(collectgarbage or print){}", "collectgarbage")
  243. -- errors in functions without debug info
  244. do
  245. local f = function (a) return a + 1 end
  246. f = assert(load(string.dump(f, true)))
  247. assert(f(3) == 4)
  248. checkerr("^%?:%?:", f, {})
  249. -- code with a move to a local var ('OP_MOV A B' with A<B)
  250. f = function () local a; a = {}; return a + 2 end
  251. -- no debug info (so that 'a' is unknown)
  252. f = assert(load(string.dump(f, true)))
  253. -- symbolic execution should not get lost
  254. checkerr("^%?:%?:.*table value", f)
  255. end
  256. -- tests for field accesses after RK limit
  257. local t = {}
  258. for i = 1, 1000 do
  259. t[i] = "aaa = x" .. i
  260. end
  261. local s = table.concat(t, "; ")
  262. t = nil
  263. checkmessage(s.."; aaa = bbb + 1", "global 'bbb'")
  264. checkmessage("local _ENV=_ENV;"..s.."; aaa = bbb + 1", "global 'bbb'")
  265. checkmessage(s.."; local t = {}; aaa = t.bbb + 1", "field 'bbb'")
  266. -- cannot use 'self' opcode
  267. checkmessage(s.."; local t = {}; t:bbb()", "field 'bbb'")
  268. checkmessage([[aaa=9
  269. repeat until 3==3
  270. local x=math.sin(math.cos(3))
  271. if math.sin(1) == x then return math.sin(1) end -- tail call
  272. local a,b = 1, {
  273. {x='a'..'b'..'c', y='b', z=x},
  274. {1,2,3,4,5} or 3+3<=3+3,
  275. 3+1>3+1,
  276. {d = x and aaa[x or y]}}
  277. ]], "global 'aaa'")
  278. checkmessage([[
  279. local x,y = {},1
  280. if math.sin(1) == 0 then return 3 end -- return
  281. x.a()]], "field 'a'")
  282. checkmessage([[
  283. prefix = nil
  284. insert = nil
  285. while 1 do
  286. local a
  287. if nil then break end
  288. insert(prefix, a)
  289. end]], "global 'insert'")
  290. checkmessage([[ -- tail call
  291. return math.sin("a")
  292. ]], "sin")
  293. checkmessage([[collectgarbage("nooption")]], "invalid option")
  294. checkmessage([[x = print .. "a"]], "concatenate")
  295. checkmessage([[x = "a" .. false]], "concatenate")
  296. checkmessage([[x = {} .. 2]], "concatenate")
  297. checkmessage("getmetatable(io.stdin).__gc()", "no value")
  298. checkmessage([[
  299. local Var
  300. local function main()
  301. NoSuchName (function() Var=0 end)
  302. end
  303. main()
  304. ]], "global 'NoSuchName'")
  305. print'+'
  306. aaa = {}; setmetatable(aaa, {__index = string})
  307. checkmessage("aaa:sub()", "bad self")
  308. checkmessage("string.sub('a', {})", "#2")
  309. checkmessage("('a'):sub{}", "#1")
  310. checkmessage("table.sort({1,2,3}, table.sort)", "'table.sort'")
  311. checkmessage("string.gsub('s', 's', setmetatable)", "'setmetatable'")
  312. _G.aaa = nil
  313. -- tests for errors in coroutines
  314. local function f (n)
  315. local c = coroutine.create(f)
  316. local a,b = coroutine.resume(c)
  317. return b
  318. end
  319. assert(string.find(f(), "C stack overflow"))
  320. checkmessage("coroutine.yield()", "outside a coroutine")
  321. f = coroutine.wrap(function () table.sort({1,2,3}, coroutine.yield) end)
  322. checkerr("yield across", f)
  323. -- testing size of 'source' info; size of buffer for that info is
  324. -- LUA_IDSIZE, declared as 60 in luaconf. Get one position for '\0'.
  325. local idsize = 60 - 1
  326. local function checksize (source)
  327. -- syntax error
  328. local _, msg = load("x", source)
  329. msg = string.match(msg, "^([^:]*):") -- get source (1st part before ':')
  330. assert(msg:len() <= idsize)
  331. end
  332. for i = 60 - 10, 60 + 10 do -- check border cases around 60
  333. checksize("@" .. string.rep("x", i)) -- file names
  334. checksize(string.rep("x", i - 10)) -- string sources
  335. checksize("=" .. string.rep("x", i)) -- exact sources
  336. end
  337. -- testing line error
  338. local function lineerror (s, l, w)
  339. local err,msg = pcall(load(s))
  340. local line = tonumber(string.match(msg, ":(%d+):"))
  341. assert((line == l or (not line and not l)) and string.find(msg, w))
  342. end
  343. lineerror("local a\n for i=1,'a' do \n print(i) \n end", 2, "limit")
  344. lineerror("\n local a \n for k,v in 3 \n do \n print(k) \n end", 3, "to call")
  345. lineerror("\n\n for k,v in \n 3 \n do \n print(k) \n end", 4, "to call")
  346. lineerror("function a.x.y ()\na=a+1\nend", 1, "index")
  347. lineerror("a = \na\n+\n{}", 3, "arithmetic")
  348. lineerror("a = \n3\n+\n(\n4\n/\nprint)", 6, "arithmetic")
  349. lineerror("a = \nprint\n+\n(\n4\n/\n7)", 3, "arithmetic")
  350. lineerror("a\n=\n-\n\nprint\n;", 3, "arithmetic")
  351. lineerror([[
  352. a
  353. ( -- <<
  354. 23)
  355. ]], 2, "call")
  356. lineerror([[
  357. local a = {x = 13}
  358. a
  359. .
  360. x
  361. ( -- <<
  362. 23
  363. )
  364. ]], 5, "call")
  365. lineerror([[
  366. local a = {x = 13}
  367. a
  368. .
  369. x
  370. (
  371. 23 + a
  372. )
  373. ]], 6, "arithmetic")
  374. local p = [[
  375. function g() f() end
  376. function f(x) error('a', XX) end
  377. g()
  378. ]]
  379. XX=3;lineerror((p), 3, "a")
  380. XX=0;lineerror((p), false, "a")
  381. XX=1;lineerror((p), 2, "a")
  382. XX=2;lineerror((p), 1, "a")
  383. _G.XX, _G.g, _G.f = nil
  384. lineerror([[
  385. local b = false
  386. if not b then
  387. error 'test'
  388. end]], 3, "test")
  389. lineerror([[
  390. local b = false
  391. if not b then
  392. if not b then
  393. if not b then
  394. error 'test'
  395. end
  396. end
  397. end]], 5, "test")
  398. lineerror([[
  399. _ENV = 1
  400. global function foo ()
  401. local a = 10
  402. return a
  403. end
  404. ]], 2, "index")
  405. -- bug in 5.4.0
  406. lineerror([[
  407. local a = 0
  408. local b = 1
  409. local c = b % a
  410. ]], 3, "perform")
  411. do
  412. -- Force a negative estimate for base line. Error in instruction 2
  413. -- (after VARARGPREP, GETGLOBAL), with first absolute line information
  414. -- (forced by too many lines) in instruction 0.
  415. local s = string.format("%s return __A.x", string.rep("\n", 300))
  416. lineerror(s, 301, "index")
  417. end
  418. local function stxlineerror (s, l, w)
  419. local err,msg = load(s)
  420. local line = tonumber(string.match(msg, ":(%d+):"))
  421. assert((line == l or (not line and not l)) and string.find(msg, w, 1, true))
  422. end
  423. stxlineerror([[
  424. ::L1::
  425. ::L1::
  426. ]], 2, "already defined")
  427. stxlineerror([[
  428. global none
  429. local x = b
  430. ]], 2, "not declared")
  431. stxlineerror([[
  432. local <close> a, b
  433. ]], 1, "multiple")
  434. if not _soft then
  435. -- several tests that exhaust the Lua stack
  436. collectgarbage()
  437. print"testing stack overflow"
  438. local C = 0
  439. -- get line where stack overflow will happen
  440. local l = debug.getinfo(1, "l").currentline + 1
  441. local function auxy () C=C+1; auxy() end -- produce a stack overflow
  442. function YY ()
  443. collectgarbage("stop") -- avoid running finalizers without stack space
  444. auxy()
  445. collectgarbage("restart")
  446. end
  447. local function checkstackmessage (m)
  448. print("(expected stack overflow after " .. C .. " calls)")
  449. C = 0 -- prepare next count
  450. return (string.find(m, "stack overflow"))
  451. end
  452. -- repeated stack overflows (to check stack recovery)
  453. assert(checkstackmessage(doit('YY()')))
  454. assert(checkstackmessage(doit('YY()')))
  455. assert(checkstackmessage(doit('YY()')))
  456. _G.YY = nil
  457. -- error lines in stack overflow
  458. local l1
  459. local function g(x)
  460. l1 = debug.getinfo(x, "l").currentline + 2
  461. collectgarbage("stop") -- avoid running finalizers without stack space
  462. auxy()
  463. collectgarbage("restart")
  464. end
  465. local _, stackmsg = xpcall(g, debug.traceback, 1)
  466. print('+')
  467. local stack = {}
  468. for line in string.gmatch(stackmsg, "[^\n]*") do
  469. local curr = string.match(line, ":(%d+):")
  470. if curr then table.insert(stack, tonumber(curr)) end
  471. end
  472. local i=1
  473. while stack[i] ~= l1 do
  474. assert(stack[i] == l)
  475. i = i+1
  476. end
  477. assert(i > 15)
  478. -- error in error handling
  479. local res, msg = xpcall(error, error)
  480. assert(not res and msg == 'error in error handling')
  481. print('+')
  482. local function f (x)
  483. if x==0 then error('a\n')
  484. else
  485. local aux = function () return f(x-1) end
  486. local a,b = xpcall(aux, aux)
  487. return a,b
  488. end
  489. end
  490. f(3)
  491. local function loop (x,y,z) return 1 + loop(x, y, z) end
  492. local res, msg = xpcall(loop, function (m)
  493. assert(string.find(m, "stack overflow"))
  494. checkerr("error handling", loop)
  495. assert(math.sin(0) == 0)
  496. return 15
  497. end)
  498. assert(msg == 15)
  499. local f = function ()
  500. for i = 999900, 1000000, 1 do table.unpack({}, 1, i) end
  501. end
  502. checkerr("too many results", f)
  503. end
  504. do -- errors in error handle that not necessarily go forever
  505. local function err (n) -- function to be used as message handler
  506. -- generate an error unless n is zero, so that there is a limited
  507. -- loop of errors
  508. if type(n) ~= "number" then -- some other error?
  509. return n -- report it
  510. elseif n == 0 then
  511. return "END" -- that will be the final message
  512. else error(n - 1) -- does the loop
  513. end
  514. end
  515. local res, msg = xpcall(error, err, 170)
  516. assert(not res and msg == "END")
  517. -- too many levels
  518. local res, msg = xpcall(error, err, 300)
  519. assert(not res and msg == "C stack overflow")
  520. end
  521. do
  522. -- non string messages
  523. local t = {}
  524. local res, msg = pcall(function () error(t) end)
  525. assert(not res and msg == t)
  526. res, msg = pcall(function () error(nil) end)
  527. assert(not res and msg == "<no error object>")
  528. local function f() error{msg='x'} end
  529. res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end)
  530. assert(msg.msg == 'xy')
  531. -- 'assert' with extra arguments
  532. res, msg = pcall(assert, false, "X", t)
  533. assert(not res and msg == "X")
  534. -- 'assert' with no message
  535. res, msg = pcall(function () assert(false) end)
  536. local line = string.match(msg, "%w+%.lua:(%d+): assertion failed!$")
  537. assert(tonumber(line) == debug.getinfo(1, "l").currentline - 2)
  538. -- 'assert' with non-string messages
  539. res, msg = pcall(assert, false, t)
  540. assert(not res and msg == t)
  541. res, msg = pcall(assert, nil, nil)
  542. assert(not res and type(msg) == "string")
  543. -- 'assert' without arguments
  544. res, msg = pcall(assert)
  545. assert(not res and string.find(msg, "value expected"))
  546. end
  547. -- xpcall with arguments
  548. local a, b, c = xpcall(string.find, error, "alo", "al")
  549. assert(a and b == 1 and c == 2)
  550. a, b, c = xpcall(string.find, function (x) return {} end, true, "al")
  551. assert(not a and type(b) == "table" and c == nil)
  552. print("testing tokens in error messages")
  553. checksyntax("syntax error", "", "error", 1)
  554. checksyntax("1.000", "", "1.000", 1)
  555. checksyntax("[[a]]", "", "[[a]]", 1)
  556. checksyntax("'aa'", "", "'aa'", 1)
  557. checksyntax("while << do end", "", "<<", 1)
  558. checksyntax("for >> do end", "", ">>", 1)
  559. -- test invalid non-printable char in a chunk
  560. checksyntax("a\1a = 1", "", "<\\1>", 1)
  561. -- test 255 as first char in a chunk
  562. checksyntax("\255a = 1", "", "<\\255>", 1)
  563. doit('I = load("a=9+"); aaa=3')
  564. assert(_G.aaa==3 and not _G.I)
  565. _G.I,_G.aaa = nil
  566. print('+')
  567. local lim = 1000
  568. if _soft then lim = 100 end
  569. for i=1,lim do
  570. doit('a = ')
  571. doit('a = 4+nil')
  572. end
  573. -- testing syntax limits
  574. local function testrep (init, rep, close, repc, finalresult)
  575. local function gencode (n)
  576. return init .. string.rep(rep, n) .. close .. string.rep(repc, n)
  577. end
  578. local res, msg = load(gencode(100)) -- 100 levels is OK
  579. assert(res)
  580. if (finalresult) then
  581. assert(res() == finalresult)
  582. end
  583. local res, msg = load(gencode(500)) -- 500 levels not ok
  584. assert(not res and (string.find(msg, "too many") or
  585. string.find(msg, "overflow")))
  586. end
  587. testrep("local a", ",a", ";", "") -- local variables
  588. testrep("local a", ",a", "= 1", ",1") -- local variables initialized
  589. testrep("local a", ",a", "= f()", "") -- local variables initialized
  590. testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment
  591. testrep("local a; a=", "{", "0", "}") -- constructors
  592. testrep("return ", "(", "2", ")", 2) -- parentheses
  593. -- nested calls (a(a(a(a(...)))))
  594. testrep("local function a (x) return x end; return ", "a(", "2.2", ")", 2.2)
  595. testrep("", "do ", "", " end")
  596. testrep("", "while a do ", "", " end")
  597. testrep("local a; ", "if a then else ", "", " end")
  598. testrep("", "function foo () ", "", " end")
  599. testrep("local a = ''; return ", "a..", "'a'", "", "a")
  600. testrep("local a = 1; return ", "a^", "a", "", 1)
  601. checkmessage("a = f(x" .. string.rep(",x", 260) .. ")", "too many registers")
  602. -- testing other limits
  603. -- upvalues
  604. local lim = 127
  605. local s = "local function fooA ()\n local "
  606. for j = 1,lim do
  607. s = s.."a"..j..", "
  608. end
  609. s = s.."b,c\n"
  610. s = s.."local function fooB ()\n local "
  611. for j = 1,lim do
  612. s = s.."b"..j..", "
  613. end
  614. s = s.."b\n"
  615. s = s.."function fooC () return b+c"
  616. local c = 1+2
  617. for j = 1,lim do
  618. s = s.."+a"..j.."+b"..j
  619. c = c + 2
  620. end
  621. s = s.."\nend end end"
  622. local a,b = load(s)
  623. assert(c > 255 and string.find(b, "too many upvalues") and
  624. string.find(b, "line 5"))
  625. -- local variables
  626. s = "\nfunction foo ()\n local "
  627. for j = 1,200 do
  628. s = s.."a"..j..", "
  629. end
  630. s = s.."b\n"
  631. local a,b = load(s)
  632. assert(string.find(b, "line 2") and string.find(b, "too many local variables"))
  633. mt.__index = oldmm
  634. print('OK')