diff options
author | Benoit Giannangeli <giann008@gmail.com> | 2017-05-06 08:11:15 +0200 |
---|---|---|
committer | Benoit Giannangeli <giann008@gmail.com> | 2017-05-06 08:16:58 +0200 |
commit | 693f073be7408e0eb0422b0e93c60e16b6648045 (patch) | |
tree | 7ddcccc9189bd34465fa6b1cbe3ae18fd7209c52 | |
parent | e9db75fac5f5fb4e8a211f69560151fe4415f9d4 (diff) | |
download | fengari-693f073be7408e0eb0422b0e93c60e16b6648045.tar.gz fengari-693f073be7408e0eb0422b0e93c60e16b6648045.tar.bz2 fengari-693f073be7408e0eb0422b0e93c60e16b6648045.zip |
BytecodeParser consumes a MBuffer (== ZIO) instead of a DataView
So we can read binary code with a user reader function
-rw-r--r-- | src/ldo.js | 4 | ||||
-rw-r--r-- | src/llex.js | 14 | ||||
-rw-r--r-- | src/lundump.js | 74 |
3 files changed, 50 insertions, 42 deletions
@@ -574,9 +574,7 @@ const f_parser = function(L, p) { let c = p.z.getc(); /* read first character */ if (c === defs.LUA_SIGNATURE.charCodeAt(0)) { checkmode(L, p.mode, defs.to_luastring("binary", true)); - let buff = p.z.buffer; - if (Array.isArray(buff)) buff = new DataView(new Uint8Array(p.z.buffer).buffer); /* Lua string holding binary (string.dump) */ - cl = new BytecodeParser(L, buff, p.name).luaU_undump(); + cl = new BytecodeParser(L, p.z, p.name).luaU_undump(); } else { checkmode(L, p.mode, defs.to_luastring("text", true)); cl = lparser.luaY_parser(L, p.z, p.buff, p.dyd, p.name, c); diff --git a/src/llex.js b/src/llex.js index 59c9015..5591054 100644 --- a/src/llex.js +++ b/src/llex.js @@ -67,8 +67,6 @@ const luaX_tokens = [ "<number>", "<integer>", "<name>", "<string>" ]; -const NUM_RESERVED = Object.keys(RESERVED).length; - class MBuffer { constructor(L, data, reader) { this.L = L; @@ -102,6 +100,18 @@ class MBuffer { return r; } + read(size) { + let r = []; + + while (size > 0) { + let byte = this.getc(); + if (byte !== -1) r.push(byte); + size--; + } + + return r; + } + fill() { if (this.reader) { this.buffer = this.reader(this.L, this.data); diff --git a/src/lundump.js b/src/lundump.js index 1c0d4c7..9caad90 100644 --- a/src/lundump.js +++ b/src/lundump.js @@ -7,11 +7,12 @@ const defs = require('./defs.js'); const lfunc = require('./lfunc.js'); const lobject = require('./lobject.js'); const lopcodes = require('./lopcodes.js'); +const llex = require('./llex.js'); class BytecodeParser { - constructor(L, dataView, name) { - assert(dataView instanceof DataView, "BytecodeParser only operates on a dataView") + constructor(L, buffer, name) { + assert(buffer instanceof llex.MBuffer, "BytecodeParser only operates on a MBuffer"); this.L = L; this.intSize = 4; @@ -20,56 +21,55 @@ class BytecodeParser { this.integerSize = 4; this.numberSize = 8; - this.dataView = dataView; - this.offset = 0; + // Used to do buffer to number conversions + this.dv = new DataView( + new ArrayBuffer( + Math.max(this.intSize, this.size_tSize, this.instructionSize, this.integerSize, this.numberSize) + ) + ); + + this.buffer = buffer; this.name = name; } - peekByte() { - return this.dataView.getUint8(this.offset, true); + read(size) { + let buffer = this.buffer.read(size); + if (buffer.length < size) this.error("truncated"); + return buffer; } readByte() { - let byte = this.peekByte(); - this.offset++; - return byte; - } - - peekInteger() { - return this.dataView.getInt32(this.offset, true); + return this.read(1)[0]; } readInteger() { - let integer = this.peekInteger(); - this.offset += this.integerSize; + let buffer = this.read(this.integerSize); + for (let i = 0; i < buffer.length; i++) + this.dv.setUint8(i, buffer[i]); - return integer; + return this.dv.getInt32(0, true); } readSize_t() { return this.readInteger(); } - peekInt() { - return this.dataView.getInt32(this.offset, true); - } - readInt() { - let integer = this.peekInt(); - this.offset += 4; + let buffer = this.read(this.intSize); - return integer; - } + for (let i = 0; i < buffer.length; i++) + this.dv.setUint8(i, buffer[i]); - peekNumber() { - return this.dataView.getFloat64(this.offset, true); + return this.dv.getInt32(0, true); } readNumber() { - let number = this.peekNumber(); - this.offset += this.numberSize; + let buffer = this.read(this.numberSize); + + for (let i = 0; i < buffer.length; i++) + this.dv.setUint8(i, buffer[i]); - return number; + return this.dv.getFloat64(0, true); } read8bitString(n) { @@ -182,7 +182,7 @@ class BytecodeParser { f.k.push(this.L.l_G.intern(this.read8bitString())); break; default: - throw new Error(`unrecognized constant '${t}'`); + this.error(`unrecognized constant '${t}'`); } } } @@ -233,17 +233,17 @@ class BytecodeParser { } checkHeader() { - if (this.readString(4) !== defs.LUA_SIGNATURE) - throw new Error("bad LUA_SIGNATURE, expected '<esc>Lua'"); + if (this.readString(3) !== defs.LUA_SIGNATURE.slice(1)) /* 1st char already checked */ + this.error("bad LUA_SIGNATURE, expected '<esc>Lua'"); if (this.readByte() !== 0x53) - throw new Error("bad Lua version, expected 5.3"); + this.error("bad Lua version, expected 5.3"); if (this.readByte() !== 0) - throw new Error("supports only official PUC-Rio implementation"); + this.error("supports only official PUC-Rio implementation"); if (this.readString(6) !== "\x19\x93\r\n\x1a\n") - throw new Error("bytecode corrupted"); + this.error("bytecode corrupted"); this.intSize = this.readByte(); this.size_tSize = this.readByte(); @@ -258,10 +258,10 @@ class BytecodeParser { this.checksize(this.numberSize, 8, "number"); if (this.readInteger() !== 0x5678) - throw new Error("endianness mismatch"); + this.error("endianness mismatch"); if (this.readNumber() !== 370.5) - throw new Error("float format mismatch"); + this.error("float format mismatch"); } |