summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Giannangeli <giann008@gmail.com>2017-05-06 08:11:15 +0200
committerBenoit Giannangeli <giann008@gmail.com>2017-05-06 08:16:58 +0200
commit693f073be7408e0eb0422b0e93c60e16b6648045 (patch)
tree7ddcccc9189bd34465fa6b1cbe3ae18fd7209c52
parente9db75fac5f5fb4e8a211f69560151fe4415f9d4 (diff)
downloadfengari-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.js4
-rw-r--r--src/llex.js14
-rw-r--r--src/lundump.js74
3 files changed, 50 insertions, 42 deletions
diff --git a/src/ldo.js b/src/ldo.js
index 13bd15c..5865f96 100644
--- a/src/ldo.js
+++ b/src/ldo.js
@@ -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");
}