diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-03-10 15:21:32 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-03-10 15:21:32 -0300 |
| commit | b5b1995f2925b2f9be4a48304ac97a38f8608648 (patch) | |
| tree | 6935ced2337eb900029ccb119636185df5037fd8 | |
| parent | cb88c1cd5d22fe7c56f4f374ded7c16f7cf14bf3 (diff) | |
| download | lua-b5b1995f2925b2f9be4a48304ac97a38f8608648.tar.gz lua-b5b1995f2925b2f9be4a48304ac97a38f8608648.tar.bz2 lua-b5b1995f2925b2f9be4a48304ac97a38f8608648.zip | |
Checks for type 'int' added to binary header
The structure 'AbsLineInfo' is hard-dumped into binary chunks, and
it comprises two 'int' fields.
| -rw-r--r-- | ldump.c | 13 | ||||
| -rw-r--r-- | lundump.c | 38 | ||||
| -rw-r--r-- | lundump.h | 5 | ||||
| -rw-r--r-- | testes/calls.lua | 47 |
4 files changed, 67 insertions, 36 deletions
| @@ -253,16 +253,19 @@ static void dumpFunction (DumpState *D, const Proto *f) { | |||
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | 255 | ||
| 256 | #define dumpNumInfo(D, tvar, value) \ | ||
| 257 | { tvar i = value; dumpByte(D, sizeof(tvar)); dumpVar(D, i); } | ||
| 258 | |||
| 259 | |||
| 256 | static void dumpHeader (DumpState *D) { | 260 | static void dumpHeader (DumpState *D) { |
| 257 | dumpLiteral(D, LUA_SIGNATURE); | 261 | dumpLiteral(D, LUA_SIGNATURE); |
| 258 | dumpByte(D, LUAC_VERSION); | 262 | dumpByte(D, LUAC_VERSION); |
| 259 | dumpByte(D, LUAC_FORMAT); | 263 | dumpByte(D, LUAC_FORMAT); |
| 260 | dumpLiteral(D, LUAC_DATA); | 264 | dumpLiteral(D, LUAC_DATA); |
| 261 | dumpByte(D, sizeof(Instruction)); | 265 | dumpNumInfo(D, int, LUAC_INT); |
| 262 | dumpByte(D, sizeof(lua_Integer)); | 266 | dumpNumInfo(D, Instruction, LUAC_INST); |
| 263 | dumpByte(D, sizeof(lua_Number)); | 267 | dumpNumInfo(D, lua_Integer, LUAC_INT); |
| 264 | dumpInteger(D, LUAC_INT); | 268 | dumpNumInfo(D, lua_Number, LUAC_NUM); |
| 265 | dumpNumber(D, LUAC_NUM); | ||
| 266 | } | 269 | } |
| 267 | 270 | ||
| 268 | 271 | ||
| @@ -345,13 +345,29 @@ static void checkliteral (LoadState *S, const char *s, const char *msg) { | |||
| 345 | } | 345 | } |
| 346 | 346 | ||
| 347 | 347 | ||
| 348 | static void fchecksize (LoadState *S, size_t size, const char *tname) { | 348 | static l_noret numerror (LoadState *S, const char *what, const char *tname) { |
| 349 | if (loadByte(S) != size) | 349 | const char *msg = luaO_pushfstring(S->L, "%s %s mismatch", tname, what); |
| 350 | error(S, luaO_pushfstring(S->L, "%s size mismatch", tname)); | 350 | error(S, msg); |
| 351 | } | 351 | } |
| 352 | 352 | ||
| 353 | 353 | ||
| 354 | #define checksize(S,t) fchecksize(S,sizeof(t),#t) | 354 | static void checknumsize (LoadState *S, int size, const char *tname) { |
| 355 | if (size != loadByte(S)) | ||
| 356 | numerror(S, "size", tname); | ||
| 357 | } | ||
| 358 | |||
| 359 | |||
| 360 | static void checknumformat (LoadState *S, int eq, const char *tname) { | ||
| 361 | if (!eq) | ||
| 362 | numerror(S, "format", tname); | ||
| 363 | } | ||
| 364 | |||
| 365 | |||
| 366 | #define checknum(S,tvar,value,tname) \ | ||
| 367 | { tvar i; checknumsize(S, sizeof(i), tname); \ | ||
| 368 | loadVar(S, i); \ | ||
| 369 | checknumformat(S, i == value, tname); } | ||
| 370 | |||
| 355 | 371 | ||
| 356 | static void checkHeader (LoadState *S) { | 372 | static void checkHeader (LoadState *S) { |
| 357 | /* skip 1st char (already read and checked) */ | 373 | /* skip 1st char (already read and checked) */ |
| @@ -361,13 +377,10 @@ static void checkHeader (LoadState *S) { | |||
| 361 | if (loadByte(S) != LUAC_FORMAT) | 377 | if (loadByte(S) != LUAC_FORMAT) |
| 362 | error(S, "format mismatch"); | 378 | error(S, "format mismatch"); |
| 363 | checkliteral(S, LUAC_DATA, "corrupted chunk"); | 379 | checkliteral(S, LUAC_DATA, "corrupted chunk"); |
| 364 | checksize(S, Instruction); | 380 | checknum(S, int, LUAC_INT, "int"); |
| 365 | checksize(S, lua_Integer); | 381 | checknum(S, Instruction, LUAC_INST, "instruction"); |
| 366 | checksize(S, lua_Number); | 382 | checknum(S, lua_Integer, LUAC_INT, "Lua integer"); |
| 367 | if (loadInteger(S) != LUAC_INT) | 383 | checknum(S, lua_Number, LUAC_NUM, "Lua number"); |
| 368 | error(S, "integer format mismatch"); | ||
| 369 | if (loadNumber(S) != LUAC_NUM) | ||
| 370 | error(S, "float format mismatch"); | ||
| 371 | } | 384 | } |
| 372 | 385 | ||
| 373 | 386 | ||
| @@ -398,7 +411,8 @@ LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) { | |||
| 398 | cl->p = luaF_newproto(L); | 411 | cl->p = luaF_newproto(L); |
| 399 | luaC_objbarrier(L, cl, cl->p); | 412 | luaC_objbarrier(L, cl, cl->p); |
| 400 | loadFunction(&S, cl->p); | 413 | loadFunction(&S, cl->p); |
| 401 | lua_assert(cl->nupvalues == cl->p->sizeupvalues); | 414 | if (cl->nupvalues != cl->p->sizeupvalues) |
| 415 | error(&S, "corrupted chunk"); | ||
| 402 | luai_verifycode(L, cl->p); | 416 | luai_verifycode(L, cl->p); |
| 403 | L->top.p--; /* pop table */ | 417 | L->top.p--; /* pop table */ |
| 404 | return cl; | 418 | return cl; |
| @@ -17,8 +17,9 @@ | |||
| 17 | /* data to catch conversion errors */ | 17 | /* data to catch conversion errors */ |
| 18 | #define LUAC_DATA "\x19\x93\r\n\x1a\n" | 18 | #define LUAC_DATA "\x19\x93\r\n\x1a\n" |
| 19 | 19 | ||
| 20 | #define LUAC_INT 0x5678 | 20 | #define LUAC_INT -0x5678 |
| 21 | #define LUAC_NUM cast_num(370.5) | 21 | #define LUAC_INST 0x12345678 |
| 22 | #define LUAC_NUM cast_num(-370.5) | ||
| 22 | 23 | ||
| 23 | /* | 24 | /* |
| 24 | ** Encode major-minor version in one byte, one nibble for each | 25 | ** Encode major-minor version in one byte, one nibble for each |
diff --git a/testes/calls.lua b/testes/calls.lua index 31028215..8b355957 100644 --- a/testes/calls.lua +++ b/testes/calls.lua | |||
| @@ -480,15 +480,22 @@ assert((function (a) return a end)() == nil) | |||
| 480 | 480 | ||
| 481 | print("testing binary chunks") | 481 | print("testing binary chunks") |
| 482 | do | 482 | do |
| 483 | local header = string.pack("c4BBc6BBB", | 483 | local headformat = "c4BBc6BiBI4BjBn" |
| 484 | "\27Lua", -- signature | 484 | local header = { -- header components |
| 485 | 0x55, -- version 5.5 (0x55) | 485 | "\27Lua", -- signature |
| 486 | 0, -- format | 486 | 0x55, -- version 5.5 (0x55) |
| 487 | "\x19\x93\r\n\x1a\n", -- data | 487 | 0, -- format |
| 488 | 4, -- size of instruction | 488 | "\x19\x93\r\n\x1a\n", -- a binary string |
| 489 | string.packsize("j"), -- sizeof(lua integer) | 489 | string.packsize("i"), -- size of an int |
| 490 | string.packsize("n") -- sizeof(lua number) | 490 | -0x5678, -- an int |
| 491 | ) | 491 | 4, -- size of an instruction |
| 492 | 0x12345678, -- an instruction (4 bytes) | ||
| 493 | string.packsize("j"), -- size of a Lua integer | ||
| 494 | -0x5678, -- a Lua integer | ||
| 495 | string.packsize("n"), -- size of a Lua float | ||
| 496 | -370.5, -- a Lua float | ||
| 497 | } | ||
| 498 | |||
| 492 | local c = string.dump(function () | 499 | local c = string.dump(function () |
| 493 | local a = 1; local b = 3; | 500 | local a = 1; local b = 3; |
| 494 | local f = function () return a + b + _ENV.c; end -- upvalues | 501 | local f = function () return a + b + _ENV.c; end -- upvalues |
| @@ -500,17 +507,23 @@ do | |||
| 500 | assert(assert(load(c))() == 10) | 507 | assert(assert(load(c))() == 10) |
| 501 | 508 | ||
| 502 | -- check header | 509 | -- check header |
| 503 | assert(string.sub(c, 1, #header) == header) | 510 | local t = {string.unpack(headformat, c)} |
| 504 | -- check LUAC_INT and LUAC_NUM | ||
| 505 | local ci, cn = string.unpack("jn", c, #header + 1) | ||
| 506 | assert(ci == 0x5678 and cn == 370.5) | ||
| 507 | |||
| 508 | -- corrupted header | ||
| 509 | for i = 1, #header do | 511 | for i = 1, #header do |
| 512 | assert(t[i] == header[i]) | ||
| 513 | end | ||
| 514 | |||
| 515 | -- Testing corrupted header. | ||
| 516 | -- A single wrong byte in the head invalidates the chunk, | ||
| 517 | -- except for the Lua float check. (If numbers are long double, | ||
| 518 | -- the representation may need padding, and changing that padding | ||
| 519 | -- will not invalidate the chunk.) | ||
| 520 | local headlen = string.packsize(headformat) | ||
| 521 | headlen = headlen - string.packsize("n") -- remove float check | ||
| 522 | for i = 1, headlen do | ||
| 510 | local s = string.sub(c, 1, i - 1) .. | 523 | local s = string.sub(c, 1, i - 1) .. |
| 511 | string.char(string.byte(string.sub(c, i, i)) + 1) .. | 524 | string.char((string.byte(string.sub(c, i, i)) + 1) & 0xFF) .. |
| 512 | string.sub(c, i + 1, -1) | 525 | string.sub(c, i + 1, -1) |
| 513 | assert(#s == #c) | 526 | assert(#s == #c and s ~= c) |
| 514 | assert(not load(s)) | 527 | assert(not load(s)) |
| 515 | end | 528 | end |
| 516 | 529 | ||
