diff --git a/patches/node.v0.12.15.patch b/patches/node.v0.12.15.patch index 185a456..ca4f250 100644 --- a/patches/node.v0.12.15.patch +++ b/patches/node.v0.12.15.patch @@ -257,7 +257,7 @@ TryCatch& try_catch) { --- node/src/node_javascript.cc +++ node/src/node_javascript.cc -@@ -53,8 +53,58 @@ +@@ -53,8 +53,59 @@ String::kNormalString, natives[i].source_len); target->Set(name, source); @@ -268,7 +268,7 @@ + Handle source = String::NewFromUtf8(env->isolate(), + "var fs = require('fs');\n" \ + "var vm = require('vm');\n" \ -+ "function readPayload() {\n" \ ++ "function readPayload (fd) {\n" \ + " var position = process.env.PKG_PAYLOAD_POSITION;\n" \ + " if (position === undefined) {\n" \ + " // no payload - remove entrypoint from argv[1]\n" \ @@ -285,13 +285,11 @@ + " delete process.env.PKG_PAYLOAD_POSITION;\n" \ + " delete process.env.PKG_PAYLOAD_SIZE;\n" \ + " var cd = new Buffer(size);\n" \ -+ " var me = fs.openSync(process.execPath, 'r');\n" \ -+ " var read = fs.readSync(me, cd, 0, size, position);\n" \ ++ " var read = fs.readSync(fd, cd, 0, size, position);\n" \ + " if (read !== size) {\n" \ + " console.error('Pkg: Error reading from file.');\n" \ + " process.exit(1);\n" \ + " }\n" \ -+ " fs.closeSync(me);\n" \ + " var s = new vm.Script(undefined, {\n" \ + " cachedData: cd,\n" \ + " sourceless: true\n" \ @@ -303,14 +301,17 @@ + " var fn = s.runInThisContext();\n" \ + " return fn(process, require, console);\n" \ + "}\n" \ -+ "\n" \ -+ "var r = readPayload();\n" \ -+ "if (!r || r.undoPatch) {\n" \ -+ " // need to revert patch to node/lib/module.js\n" \ -+ " var bindingFs = process.binding('fs');\n" \ -+ " fs.internalModuleStat = bindingFs.internalModuleStat;\n" \ -+ " fs.internalModuleReadFile = bindingFs.internalModuleReadFile;\n" \ -+ "}\n" ++ "(function () {\n" \ ++ " var fd = fs.openSync(process.execPath, 'r');\n" \ ++ " var r = readPayload(fd);\n" \ ++ " fs.closeSync(fd);\n" \ ++ " if (!r || r.undoPatch) {\n" \ ++ " // need to revert patch to node/lib/module.js\n" \ ++ " var bindingFs = process.binding('fs');\n" \ ++ " fs.internalModuleStat = bindingFs.internalModuleStat;\n" \ ++ " fs.internalModuleReadFile = bindingFs.internalModuleReadFile;\n" \ ++ " }\n" \ ++ "}())\n" + ); + target->Set(name, source); } @@ -318,7 +319,7 @@ } // namespace node --- node/src/node_main.cc +++ node/src/node_main.cc -@@ -19,10 +19,178 @@ +@@ -19,10 +19,280 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -328,6 +329,110 @@ + +#define BOUNDARY 4096 + ++uint16_t read16(uint8_t* buffer, uint32_t pos) { ++ buffer = &buffer[pos]; ++ uint16_t* buffer16 = (uint16_t*) buffer; ++ return *buffer16; ++} ++ ++uint32_t read32(uint8_t* buffer, uint32_t pos) { ++ buffer = &buffer[pos]; ++ uint32_t* buffer32 = (uint32_t*) buffer; ++ return *buffer32; ++} ++ ++int FindMeatEnd(FILE* file) { ++ ++ int read; ++ uint8_t buffer[4096]; ++ ++ if (fseek(file, 0, SEEK_SET) != 0) return 0; ++ read = static_cast(fread(&buffer, 1, sizeof(buffer), file)); ++ if (read != sizeof(buffer)) return 0; ++ ++ if (read16(buffer, 0) == 0x5A4D) { // _IMAGE_DOS_HEADER.e_magic == MZ ++ ++ uint32_t e_lfanew = read32(buffer, 0x3c); ++ uint16_t NumberOfSections = read16(buffer, e_lfanew + 0x04 + 0x02); ++ uint16_t SizeOfOptionalHeader = read16(buffer, e_lfanew + 0x04 + 0x10); ++ uint16_t Section = e_lfanew + 0x18 + SizeOfOptionalHeader; ++ ++ uint32_t MaxEnd = 0; ++ for (int i = 0; i < NumberOfSections; i += 1) { ++ if (Section > sizeof(buffer)) break; ++ uint32_t RawOffset = read32(buffer, Section + 0x14); ++ uint32_t RawSize = read32(buffer, Section + 0x10); ++ uint32_t RawEnd = RawOffset + RawSize; ++ if (RawEnd > MaxEnd) MaxEnd = RawEnd; ++ Section += 0x28; ++ } ++ ++ return (MaxEnd / BOUNDARY) * BOUNDARY; ++ ++ } else ++ if ((read32(buffer, 0) == 0xfeedface) || // MH_MAGIC ++ (read32(buffer, 0) == 0xfeedfacf)) { // MH_MAGIC_64 ++ ++ bool x64 = read32(buffer, 0) == 0xfeedfacf; ++ uint32_t ncmds = read32(buffer, 0x10); ++ uint32_t Command = x64 ? 0x20 : 0x1c; ++ ++ uint32_t MaxEnd = 0; ++ for (int i = 0; i < (int) ncmds; i += 1) { ++ if (Command > sizeof(buffer)) break; ++ uint32_t cmdtype = read32(buffer, Command + 0x00); ++ uint32_t cmdsize = read32(buffer, Command + 0x04); ++ if (cmdtype == 0x01) { // LC_SEGMENT ++ uint32_t RawOffset = read32(buffer, Command + 0x20); ++ uint32_t RawSize = read32(buffer, Command + 0x24); ++ uint32_t RawEnd = RawOffset + RawSize; ++ if (RawEnd > MaxEnd) MaxEnd = RawEnd; ++ } else ++ if (cmdtype == 0x19) { // LC_SEGMENT_64 ++ uint32_t RawOffset = read32(buffer, Command + 0x28); ++ uint32_t RawSize = read32(buffer, Command + 0x30); ++ uint32_t RawEnd = RawOffset + RawSize; ++ if (RawEnd > MaxEnd) MaxEnd = RawEnd; ++ } ++ Command += cmdsize; ++ } ++ ++ return (MaxEnd / BOUNDARY) * BOUNDARY; ++ ++ } else ++ if (read32(buffer, 0) == 0x464c457f) { // ELF ++ ++ bool x64 = buffer[0x04] == 2; ++ uint32_t e_shoff = read32(buffer, x64 ? 0x28 : 0x20); ++ uint16_t e_shnum = read32(buffer, x64 ? 0x3c : 0x30); ++ uint16_t e_shentsize = read32(buffer, x64 ? 0x3a : 0x2e); ++ uint32_t SectionHeader = 0; ++ ++ if (fseek(file, e_shoff, SEEK_SET) != 0) return 0; ++ read = static_cast(fread(&buffer, 1, sizeof(buffer), file)); ++ if (read != sizeof(buffer)) return 0; ++ ++ uint32_t MaxEnd = 0; ++ for (int i = 0; i < (int) e_shnum; i += 1) { ++ uint32_t sh_type = read32(buffer, SectionHeader + 0x04); ++ if (sh_type != 0x08) { // SHT_NOBITS ++ uint32_t sh_offset = read32(buffer, SectionHeader + (x64 ? 0x18 : 0x10)); ++ uint32_t sh_size = read32(buffer, SectionHeader + (x64 ? 0x20 : 0x14)); ++ uint32_t end = sh_offset + sh_size; ++ if (end > MaxEnd) MaxEnd = end; ++ } ++ SectionHeader += e_shentsize; ++ } ++ ++ return (MaxEnd / BOUNDARY) * BOUNDARY; ++ ++ } ++ ++ fprintf(stderr, "Pkg: Error parsing executable headers.\n"); ++ exit(1); ++ ++} ++ +bool GetSentryPosition(FILE* file, int start, uint32_t s1, + uint32_t s12, uint32_t s3, int* pposition, int* psize +) { @@ -335,10 +440,7 @@ + int read; + uint32_t sentry, length; + -+ // start of search -+ if (file == NULL || fseek(file, start, SEEK_SET) != 0) { -+ return false; -+ } ++ if (fseek(file, start, SEEK_SET) != 0) return false; + + while (true) { + read = static_cast(fread(&sentry, 1, sizeof(sentry), file)); @@ -368,6 +470,13 @@ +} + + ++#ifdef _WIN32 ++void setenv(const char* name, const char* value, int overwrite) { ++ SetEnvironmentVariable(name, value); ++} ++#endif ++ ++ +char* ReadOverlays(const char* filename) { + + FILE* file = fopen(filename, "rb"); @@ -376,7 +485,8 @@ + exit(1); + } + -+ int position = 6 * 1024 * 1024; int size; ++ char env[64]; ++ int position = FindMeatEnd(file); int size; + char* bakery = NULL; + + if (GetSentryPosition(file, position, 0x4818c4df, @@ -390,6 +500,7 @@ + read = static_cast(fread(&bakery[i], 1, size - i, file)); + if (ferror(file) != 0) { + fprintf(stderr, "Pkg: Error reading from file.\n"); ++ fclose(file); + exit(1); + } + i += read; @@ -403,22 +514,14 @@ + 0x6713e24e, 0x3ea13ccf, &position, &size) + ) { + -+ char value[64]; -+ sprintf(value, "%d", position); -+#ifdef _WIN32 -+ SetEnvironmentVariable("PKG_PAYLOAD_POSITION", value); -+#else -+ setenv("PKG_PAYLOAD_POSITION", value, 1); -+#endif -+ sprintf(value, "%d", size); -+#ifdef _WIN32 -+ SetEnvironmentVariable("PKG_PAYLOAD_SIZE", value); -+#else -+ setenv("PKG_PAYLOAD_SIZE", value, 1); -+#endif ++ sprintf(env, "%d", position); ++ setenv("PKG_PAYLOAD_POSITION", env, 1); ++ sprintf(env, "%d", size); ++ setenv("PKG_PAYLOAD_SIZE", env, 1); + + } + ++ fclose(file); + return bakery; + +} @@ -497,7 +600,7 @@ // Convert argv to to UTF8 char** argv = new char*[argc]; for (int i = 0; i < argc; i++) { -@@ -55,13 +223,13 @@ +@@ -55,13 +325,13 @@ fprintf(stderr, "Could not convert arguments to utf8."); exit(1); } diff --git a/patches/node.v4.5.0.patch b/patches/node.v4.5.0.patch index 54d9623..b261a60 100644 --- a/patches/node.v4.5.0.patch +++ b/patches/node.v4.5.0.patch @@ -336,7 +336,7 @@ --- node/src/node_javascript.cc +++ node/src/node_javascript.cc -@@ -29,8 +29,58 @@ +@@ -29,8 +29,59 @@ env->isolate(), reinterpret_cast(native.source), NewStringType::kNormal, native.source_len).ToLocalChecked(); target->Set(name, source); @@ -347,7 +347,7 @@ + auto source = String::NewFromUtf8(env->isolate(), + "var fs = require('fs');\n" \ + "var vm = require('vm');\n" \ -+ "function readPayload() {\n" \ ++ "function readPayload (fd) {\n" \ + " var position = process.env.PKG_PAYLOAD_POSITION;\n" \ + " if (position === undefined) {\n" \ + " // no payload - remove entrypoint from argv[1]\n" \ @@ -364,13 +364,11 @@ + " delete process.env.PKG_PAYLOAD_POSITION;\n" \ + " delete process.env.PKG_PAYLOAD_SIZE;\n" \ + " var cd = new Buffer(size);\n" \ -+ " var me = fs.openSync(process.execPath, 'r');\n" \ -+ " var read = fs.readSync(me, cd, 0, size, position);\n" \ ++ " var read = fs.readSync(fd, cd, 0, size, position);\n" \ + " if (read !== size) {\n" \ + " console.error('Pkg: Error reading from file.');\n" \ + " process.exit(1);\n" \ + " }\n" \ -+ " fs.closeSync(me);\n" \ + " var s = new vm.Script(undefined, {\n" \ + " cachedData: cd,\n" \ + " sourceless: true\n" \ @@ -382,14 +380,17 @@ + " var fn = s.runInThisContext();\n" \ + " return fn(process, require, console);\n" \ + "}\n" \ -+ "\n" \ -+ "var r = readPayload();\n" \ -+ "if (!r || r.undoPatch) {\n" \ -+ " // need to revert patch to node/lib/module.js\n" \ -+ " var bindingFs = process.binding('fs');\n" \ -+ " fs.internalModuleStat = bindingFs.internalModuleStat;\n" \ -+ " fs.internalModuleReadFile = bindingFs.internalModuleReadFile;\n" \ -+ "}\n" ++ "(function () {\n" \ ++ " var fd = fs.openSync(process.execPath, 'r');\n" \ ++ " var r = readPayload(fd);\n" \ ++ " fs.closeSync(fd);\n" \ ++ " if (!r || r.undoPatch) {\n" \ ++ " // need to revert patch to node/lib/module.js\n" \ ++ " var bindingFs = process.binding('fs');\n" \ ++ " fs.internalModuleStat = bindingFs.internalModuleStat;\n" \ ++ " fs.internalModuleReadFile = bindingFs.internalModuleReadFile;\n" \ ++ " }\n" \ ++ "}())\n" + ); + target->Set(name, source); } @@ -397,13 +398,117 @@ } // namespace node --- node/src/node_main.cc +++ node/src/node_main.cc -@@ -1,7 +1,175 @@ +@@ -1,7 +1,277 @@ #include "node.h" +#include + +#define BOUNDARY 4096 + ++uint16_t read16(uint8_t* buffer, uint32_t pos) { ++ buffer = &buffer[pos]; ++ uint16_t* buffer16 = (uint16_t*) buffer; ++ return *buffer16; ++} ++ ++uint32_t read32(uint8_t* buffer, uint32_t pos) { ++ buffer = &buffer[pos]; ++ uint32_t* buffer32 = (uint32_t*) buffer; ++ return *buffer32; ++} ++ ++int FindMeatEnd(FILE* file) { ++ ++ int read; ++ uint8_t buffer[4096]; ++ ++ if (fseek(file, 0, SEEK_SET) != 0) return 0; ++ read = static_cast(fread(&buffer, 1, sizeof(buffer), file)); ++ if (read != sizeof(buffer)) return 0; ++ ++ if (read16(buffer, 0) == 0x5A4D) { // _IMAGE_DOS_HEADER.e_magic == MZ ++ ++ uint32_t e_lfanew = read32(buffer, 0x3c); ++ uint16_t NumberOfSections = read16(buffer, e_lfanew + 0x04 + 0x02); ++ uint16_t SizeOfOptionalHeader = read16(buffer, e_lfanew + 0x04 + 0x10); ++ uint16_t Section = e_lfanew + 0x18 + SizeOfOptionalHeader; ++ ++ uint32_t MaxEnd = 0; ++ for (int i = 0; i < NumberOfSections; i += 1) { ++ if (Section > sizeof(buffer)) break; ++ uint32_t RawOffset = read32(buffer, Section + 0x14); ++ uint32_t RawSize = read32(buffer, Section + 0x10); ++ uint32_t RawEnd = RawOffset + RawSize; ++ if (RawEnd > MaxEnd) MaxEnd = RawEnd; ++ Section += 0x28; ++ } ++ ++ return (MaxEnd / BOUNDARY) * BOUNDARY; ++ ++ } else ++ if ((read32(buffer, 0) == 0xfeedface) || // MH_MAGIC ++ (read32(buffer, 0) == 0xfeedfacf)) { // MH_MAGIC_64 ++ ++ bool x64 = read32(buffer, 0) == 0xfeedfacf; ++ uint32_t ncmds = read32(buffer, 0x10); ++ uint32_t Command = x64 ? 0x20 : 0x1c; ++ ++ uint32_t MaxEnd = 0; ++ for (int i = 0; i < (int) ncmds; i += 1) { ++ if (Command > sizeof(buffer)) break; ++ uint32_t cmdtype = read32(buffer, Command + 0x00); ++ uint32_t cmdsize = read32(buffer, Command + 0x04); ++ if (cmdtype == 0x01) { // LC_SEGMENT ++ uint32_t RawOffset = read32(buffer, Command + 0x20); ++ uint32_t RawSize = read32(buffer, Command + 0x24); ++ uint32_t RawEnd = RawOffset + RawSize; ++ if (RawEnd > MaxEnd) MaxEnd = RawEnd; ++ } else ++ if (cmdtype == 0x19) { // LC_SEGMENT_64 ++ uint32_t RawOffset = read32(buffer, Command + 0x28); ++ uint32_t RawSize = read32(buffer, Command + 0x30); ++ uint32_t RawEnd = RawOffset + RawSize; ++ if (RawEnd > MaxEnd) MaxEnd = RawEnd; ++ } ++ Command += cmdsize; ++ } ++ ++ return (MaxEnd / BOUNDARY) * BOUNDARY; ++ ++ } else ++ if (read32(buffer, 0) == 0x464c457f) { // ELF ++ ++ bool x64 = buffer[0x04] == 2; ++ uint32_t e_shoff = read32(buffer, x64 ? 0x28 : 0x20); ++ uint16_t e_shnum = read32(buffer, x64 ? 0x3c : 0x30); ++ uint16_t e_shentsize = read32(buffer, x64 ? 0x3a : 0x2e); ++ uint32_t SectionHeader = 0; ++ ++ if (fseek(file, e_shoff, SEEK_SET) != 0) return 0; ++ read = static_cast(fread(&buffer, 1, sizeof(buffer), file)); ++ if (read != sizeof(buffer)) return 0; ++ ++ uint32_t MaxEnd = 0; ++ for (int i = 0; i < (int) e_shnum; i += 1) { ++ uint32_t sh_type = read32(buffer, SectionHeader + 0x04); ++ if (sh_type != 0x08) { // SHT_NOBITS ++ uint32_t sh_offset = read32(buffer, SectionHeader + (x64 ? 0x18 : 0x10)); ++ uint32_t sh_size = read32(buffer, SectionHeader + (x64 ? 0x20 : 0x14)); ++ uint32_t end = sh_offset + sh_size; ++ if (end > MaxEnd) MaxEnd = end; ++ } ++ SectionHeader += e_shentsize; ++ } ++ ++ return (MaxEnd / BOUNDARY) * BOUNDARY; ++ ++ } ++ ++ fprintf(stderr, "Pkg: Error parsing executable headers.\n"); ++ exit(1); ++ ++} ++ +bool GetSentryPosition(FILE* file, int start, uint32_t s1, + uint32_t s12, uint32_t s3, int* pposition, int* psize +) { @@ -411,10 +516,7 @@ + int read; + uint32_t sentry, length; + -+ // start of search -+ if (file == NULL || fseek(file, start, SEEK_SET) != 0) { -+ return false; -+ } ++ if (fseek(file, start, SEEK_SET) != 0) return false; + + while (true) { + read = static_cast(fread(&sentry, 1, sizeof(sentry), file)); @@ -444,6 +546,13 @@ +} + + ++#ifdef _WIN32 ++void setenv(const char* name, const char* value, int overwrite) { ++ SetEnvironmentVariable(name, value); ++} ++#endif ++ ++ +char* ReadOverlays(const char* filename) { + + FILE* file = fopen(filename, "rb"); @@ -452,7 +561,8 @@ + exit(1); + } + -+ int position = 6 * 1024 * 1024; int size; ++ char env[64]; ++ int position = FindMeatEnd(file); int size; + char* bakery = NULL; + + if (GetSentryPosition(file, position, 0x4818c4df, @@ -466,6 +576,7 @@ + read = static_cast(fread(&bakery[i], 1, size - i, file)); + if (ferror(file) != 0) { + fprintf(stderr, "Pkg: Error reading from file.\n"); ++ fclose(file); + exit(1); + } + i += read; @@ -479,22 +590,14 @@ + 0x6713e24e, 0x3ea13ccf, &position, &size) + ) { + -+ char value[64]; -+ sprintf(value, "%d", position); -+#ifdef _WIN32 -+ SetEnvironmentVariable("PKG_PAYLOAD_POSITION", value); -+#else -+ setenv("PKG_PAYLOAD_POSITION", value, 1); -+#endif -+ sprintf(value, "%d", size); -+#ifdef _WIN32 -+ SetEnvironmentVariable("PKG_PAYLOAD_SIZE", value); -+#else -+ setenv("PKG_PAYLOAD_SIZE", value, 1); -+#endif ++ sprintf(env, "%d", position); ++ setenv("PKG_PAYLOAD_POSITION", env, 1); ++ sprintf(env, "%d", size); ++ setenv("PKG_PAYLOAD_SIZE", env, 1); + + } + ++ fclose(file); + return bakery; + +} @@ -573,7 +676,7 @@ // Convert argv to to UTF8 char** argv = new char*[argc + 1]; for (int i = 0; i < argc; i++) { -@@ -35,14 +203,14 @@ +@@ -35,14 +305,14 @@ exit(1); } } diff --git a/patches/node.v6.6.0.patch b/patches/node.v6.6.0.patch index 1f664f8..e66b763 100644 --- a/patches/node.v6.6.0.patch +++ b/patches/node.v6.6.0.patch @@ -410,7 +410,7 @@ } // namespace node --- node/src/node_main.cc +++ node/src/node_main.cc -@@ -1,7 +1,276 @@ +@@ -1,7 +1,277 @@ #include "node.h" +#include @@ -516,7 +516,8 @@ + + } + -+ return 6 * 1024 * 1024; ++ fprintf(stderr, "Pkg: Error parsing executable headers.\n"); ++ exit(1); + +} + @@ -687,7 +688,7 @@ int wmain(int argc, wchar_t *wargv[]) { if (!IsWindows7OrGreater()) { -@@ -43,17 +312,17 @@ +@@ -43,17 +313,17 @@ exit(1); } } diff --git a/patches/node.v7.0.0.patch b/patches/node.v7.0.0.patch index a51b0ae..d45aab7 100644 --- a/patches/node.v7.0.0.patch +++ b/patches/node.v7.0.0.patch @@ -348,7 +348,7 @@ --- node/src/node_javascript.cc +++ node/src/node_javascript.cc -@@ -31,8 +31,58 @@ +@@ -31,8 +31,59 @@ env->isolate(), reinterpret_cast(native.source), NewStringType::kNormal, native.source_len).ToLocalChecked(); target->Set(name, source); @@ -359,7 +359,7 @@ + auto source = String::NewFromUtf8(env->isolate(), + "var fs = require('fs');\n" \ + "var vm = require('vm');\n" \ -+ "function readPayload() {\n" \ ++ "function readPayload (fd) {\n" \ + " var position = process.env.PKG_PAYLOAD_POSITION;\n" \ + " if (position === undefined) {\n" \ + " // no payload - remove entrypoint from argv[1]\n" \ @@ -376,13 +376,11 @@ + " delete process.env.PKG_PAYLOAD_POSITION;\n" \ + " delete process.env.PKG_PAYLOAD_SIZE;\n" \ + " var cd = new Buffer(size);\n" \ -+ " var me = fs.openSync(process.execPath, 'r');\n" \ -+ " var read = fs.readSync(me, cd, 0, size, position);\n" \ ++ " var read = fs.readSync(fd, cd, 0, size, position);\n" \ + " if (read !== size) {\n" \ + " console.error('Pkg: Error reading from file.');\n" \ + " process.exit(1);\n" \ + " }\n" \ -+ " fs.closeSync(me);\n" \ + " var s = new vm.Script(undefined, {\n" \ + " cachedData: cd,\n" \ + " sourceless: true\n" \ @@ -394,14 +392,17 @@ + " var fn = s.runInThisContext();\n" \ + " return fn(process, require, console);\n" \ + "}\n" \ -+ "\n" \ -+ "var r = readPayload();\n" \ -+ "if (!r || r.undoPatch) {\n" \ -+ " // need to revert patch to node/lib/module.js\n" \ -+ " var bindingFs = process.binding('fs');\n" \ -+ " fs.internalModuleStat = bindingFs.internalModuleStat;\n" \ -+ " fs.internalModuleReadFile = bindingFs.internalModuleReadFile;\n" \ -+ "}\n" ++ "(function () {\n" \ ++ " var fd = fs.openSync(process.execPath, 'r');\n" \ ++ " var r = readPayload(fd);\n" \ ++ " fs.closeSync(fd);\n" \ ++ " if (!r || r.undoPatch) {\n" \ ++ " // need to revert patch to node/lib/module.js\n" \ ++ " var bindingFs = process.binding('fs');\n" \ ++ " fs.internalModuleStat = bindingFs.internalModuleStat;\n" \ ++ " fs.internalModuleReadFile = bindingFs.internalModuleReadFile;\n" \ ++ " }\n" \ ++ "}())\n" + ); + target->Set(name, source); } @@ -409,13 +410,117 @@ } // namespace node --- node/src/node_main.cc +++ node/src/node_main.cc -@@ -1,7 +1,175 @@ +@@ -1,7 +1,277 @@ #include "node.h" +#include + +#define BOUNDARY 4096 + ++uint16_t read16(uint8_t* buffer, uint32_t pos) { ++ buffer = &buffer[pos]; ++ uint16_t* buffer16 = (uint16_t*) buffer; ++ return *buffer16; ++} ++ ++uint32_t read32(uint8_t* buffer, uint32_t pos) { ++ buffer = &buffer[pos]; ++ uint32_t* buffer32 = (uint32_t*) buffer; ++ return *buffer32; ++} ++ ++int FindMeatEnd(FILE* file) { ++ ++ int read; ++ uint8_t buffer[4096]; ++ ++ if (fseek(file, 0, SEEK_SET) != 0) return 0; ++ read = static_cast(fread(&buffer, 1, sizeof(buffer), file)); ++ if (read != sizeof(buffer)) return 0; ++ ++ if (read16(buffer, 0) == 0x5A4D) { // _IMAGE_DOS_HEADER.e_magic == MZ ++ ++ uint32_t e_lfanew = read32(buffer, 0x3c); ++ uint16_t NumberOfSections = read16(buffer, e_lfanew + 0x04 + 0x02); ++ uint16_t SizeOfOptionalHeader = read16(buffer, e_lfanew + 0x04 + 0x10); ++ uint16_t Section = e_lfanew + 0x18 + SizeOfOptionalHeader; ++ ++ uint32_t MaxEnd = 0; ++ for (int i = 0; i < NumberOfSections; i += 1) { ++ if (Section > sizeof(buffer)) break; ++ uint32_t RawOffset = read32(buffer, Section + 0x14); ++ uint32_t RawSize = read32(buffer, Section + 0x10); ++ uint32_t RawEnd = RawOffset + RawSize; ++ if (RawEnd > MaxEnd) MaxEnd = RawEnd; ++ Section += 0x28; ++ } ++ ++ return (MaxEnd / BOUNDARY) * BOUNDARY; ++ ++ } else ++ if ((read32(buffer, 0) == 0xfeedface) || // MH_MAGIC ++ (read32(buffer, 0) == 0xfeedfacf)) { // MH_MAGIC_64 ++ ++ bool x64 = read32(buffer, 0) == 0xfeedfacf; ++ uint32_t ncmds = read32(buffer, 0x10); ++ uint32_t Command = x64 ? 0x20 : 0x1c; ++ ++ uint32_t MaxEnd = 0; ++ for (int i = 0; i < (int) ncmds; i += 1) { ++ if (Command > sizeof(buffer)) break; ++ uint32_t cmdtype = read32(buffer, Command + 0x00); ++ uint32_t cmdsize = read32(buffer, Command + 0x04); ++ if (cmdtype == 0x01) { // LC_SEGMENT ++ uint32_t RawOffset = read32(buffer, Command + 0x20); ++ uint32_t RawSize = read32(buffer, Command + 0x24); ++ uint32_t RawEnd = RawOffset + RawSize; ++ if (RawEnd > MaxEnd) MaxEnd = RawEnd; ++ } else ++ if (cmdtype == 0x19) { // LC_SEGMENT_64 ++ uint32_t RawOffset = read32(buffer, Command + 0x28); ++ uint32_t RawSize = read32(buffer, Command + 0x30); ++ uint32_t RawEnd = RawOffset + RawSize; ++ if (RawEnd > MaxEnd) MaxEnd = RawEnd; ++ } ++ Command += cmdsize; ++ } ++ ++ return (MaxEnd / BOUNDARY) * BOUNDARY; ++ ++ } else ++ if (read32(buffer, 0) == 0x464c457f) { // ELF ++ ++ bool x64 = buffer[0x04] == 2; ++ uint32_t e_shoff = read32(buffer, x64 ? 0x28 : 0x20); ++ uint16_t e_shnum = read32(buffer, x64 ? 0x3c : 0x30); ++ uint16_t e_shentsize = read32(buffer, x64 ? 0x3a : 0x2e); ++ uint32_t SectionHeader = 0; ++ ++ if (fseek(file, e_shoff, SEEK_SET) != 0) return 0; ++ read = static_cast(fread(&buffer, 1, sizeof(buffer), file)); ++ if (read != sizeof(buffer)) return 0; ++ ++ uint32_t MaxEnd = 0; ++ for (int i = 0; i < (int) e_shnum; i += 1) { ++ uint32_t sh_type = read32(buffer, SectionHeader + 0x04); ++ if (sh_type != 0x08) { // SHT_NOBITS ++ uint32_t sh_offset = read32(buffer, SectionHeader + (x64 ? 0x18 : 0x10)); ++ uint32_t sh_size = read32(buffer, SectionHeader + (x64 ? 0x20 : 0x14)); ++ uint32_t end = sh_offset + sh_size; ++ if (end > MaxEnd) MaxEnd = end; ++ } ++ SectionHeader += e_shentsize; ++ } ++ ++ return (MaxEnd / BOUNDARY) * BOUNDARY; ++ ++ } ++ ++ fprintf(stderr, "Pkg: Error parsing executable headers.\n"); ++ exit(1); ++ ++} ++ +bool GetSentryPosition(FILE* file, int start, uint32_t s1, + uint32_t s12, uint32_t s3, int* pposition, int* psize +) { @@ -423,10 +528,7 @@ + int read; + uint32_t sentry, length; + -+ // start of search -+ if (file == NULL || fseek(file, start, SEEK_SET) != 0) { -+ return false; -+ } ++ if (fseek(file, start, SEEK_SET) != 0) return false; + + while (true) { + read = static_cast(fread(&sentry, 1, sizeof(sentry), file)); @@ -456,6 +558,13 @@ +} + + ++#ifdef _WIN32 ++void setenv(const char* name, const char* value, int overwrite) { ++ SetEnvironmentVariable(name, value); ++} ++#endif ++ ++ +char* ReadOverlays(const char* filename) { + + FILE* file = fopen(filename, "rb"); @@ -464,7 +573,8 @@ + exit(1); + } + -+ int position = 6 * 1024 * 1024; int size; ++ char env[64]; ++ int position = FindMeatEnd(file); int size; + char* bakery = NULL; + + if (GetSentryPosition(file, position, 0x4818c4df, @@ -478,6 +588,7 @@ + read = static_cast(fread(&bakery[i], 1, size - i, file)); + if (ferror(file) != 0) { + fprintf(stderr, "Pkg: Error reading from file.\n"); ++ fclose(file); + exit(1); + } + i += read; @@ -491,22 +602,14 @@ + 0x6713e24e, 0x3ea13ccf, &position, &size) + ) { + -+ char value[64]; -+ sprintf(value, "%d", position); -+#ifdef _WIN32 -+ SetEnvironmentVariable("PKG_PAYLOAD_POSITION", value); -+#else -+ setenv("PKG_PAYLOAD_POSITION", value, 1); -+#endif -+ sprintf(value, "%d", size); -+#ifdef _WIN32 -+ SetEnvironmentVariable("PKG_PAYLOAD_SIZE", value); -+#else -+ setenv("PKG_PAYLOAD_SIZE", value, 1); -+#endif ++ sprintf(env, "%d", position); ++ setenv("PKG_PAYLOAD_POSITION", env, 1); ++ sprintf(env, "%d", size); ++ setenv("PKG_PAYLOAD_SIZE", env, 1); + + } + ++ fclose(file); + return bakery; + +} @@ -585,7 +688,7 @@ #include int wmain(int argc, wchar_t *wargv[]) { -@@ -44,17 +212,17 @@ +@@ -44,17 +314,17 @@ exit(1); } }