commit: 9e29df718ac921a2ce9f2666273140f641bad551
parent 33dff25e203d1baddf671308deb24877bd15631b
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Tue, 19 Mar 2024 01:46:27 +0100
Add support for BEAM/PKZIP-based escripts
Diffstat:
6 files changed, 44 insertions(+), 7 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -5,5 +5,7 @@
/test/fixtures/hello
/test/fixtures/hello.a
/test/fixtures/hello.o
+/test/fixtures/hello.beam.escript
+/test/fixtures/hello.erl.escript
/test/check_dir-fixtures/
/test/fixtures/compiled/*.dep
diff --git a/deblob.1 b/deblob.1
@@ -1,6 +1,6 @@
.\" SPDX-FileCopyrightText: 2019 deblob Authors <https://hacktivis.me/projects/deblob>
.\" SPDX-License-Identifier: BSD-3-Clause
-.Dd 2023-09-24
+.Dd 2024-03-19
.Dt DEBLOB 1
.Os
.Sh NAME
@@ -43,7 +43,7 @@ files
.It
x86 IBM PC BIOS Option Rom
.It
-Erlang BEAM files
+Erlang BEAM files and BEAM/PKZIP-based escripts
.It
Java Class files and Archives (JAR)
.It
diff --git a/main.ha b/main.ha
@@ -15,6 +15,7 @@ use strings;
let excludes: []str = [];
let noop: bool = false;
+const beam: []u8 = ['F', 'O', 'R', '1']; // Erlang BEAM
const magic: [_][]u8 = [
[0x7F, 'E', 'L', 'F'], // ELF
['!', '<', 'a', 'r', 'c', 'h', '>', '\n'], // Unix ar(1)
@@ -77,6 +78,7 @@ const pe_magic: []u8 = ['P', 'E', 0x00, 0x00];
const racket: []u8 = ['r', 'a', 'c', 'k', 'e', 't'];
const zip: []u8 = ['P', 'K', 0x03, 0x04];
const jar: []u8 = [0xFE, 0xCA, 0, 0];
+const shebang: []u8 = ['#', '!'];
fn is_blob(filename: str) (bool | fs::error | io::error) = {
static let buffer: [4096]u8 = [0...];
@@ -105,6 +107,29 @@ fn is_blob(filename: str) (bool | fs::error | io::error) = {
};
};
+ // detect binary escripts (PKZIP archive and BEAM supported)
+ if (bytes::hasprefix(buffer, shebang)) {
+ let comment = true;
+ for (let i = 0z; i < 4096; i += 1) {
+ if(comment) {
+ if(buffer[i] == '\n') comment = false;
+
+ continue;
+ };
+
+ if(buffer[i] == '%') {
+ comment = true;
+ } else {
+ // First bytes after comments
+ if(bytes::equal(zip, buffer[i..i+len(zip)])) return true;
+ if(bytes::equal(beam, buffer[i..i+len(beam)])) return true;
+
+ // source code as script
+ break;
+ };
+ };
+ };
+
// Special check to detect racket bytecode
if (bytes::hasprefix(buffer, ['#', '~'])) {
// From src/expander/compile/write-linklet.rkt in racket:
@@ -145,6 +170,7 @@ fn is_blob(filename: str) (bool | fs::error | io::error) = {
(false, "test/fixtures/hello.cs"),
(false, "test/fixtures/hello.el"),
(false, "test/fixtures/hello.erl"),
+ (false, "test/fixtures/hello.erl.escript"),
(false, "test/fixtures/hello.java"),
(false, "test/fixtures/hello.lua"),
(false, "test/fixtures/hello.neko"),
@@ -166,6 +192,7 @@ fn is_blob(filename: str) (bool | fs::error | io::error) = {
(true, "test/fixtures/hello-ocaml.o"),
(true, "test/fixtures/hello.a"),
(true, "test/fixtures/hello.beam"),
+ (true, "test/fixtures/hello.beam.escript"),
(true, "test/fixtures/hello.class"),
(true, "test/fixtures/hello.cnut"),
(true, "test/fixtures/hello.elc"),
@@ -280,7 +307,7 @@ fn check_dir(dirname: str) (void | errors::invalid) = {
case let e: fs::error =>
fmt::fatalf("os::readdir({}): {}", dirname, fs::strerror(e));
};
- assert(len(files_before) == 55);
+ assert(len(files_before) == 57);
const ret = check_dir(dirname);
assert(ret is void);
@@ -291,7 +318,7 @@ fn check_dir(dirname: str) (void | errors::invalid) = {
case let e: fs::error =>
fmt::fatalf("os::readdir({}): {}", dirname, fs::strerror(e));
};
- assert(len(files_after) == 28);
+ assert(len(files_after) == 29);
};
export fn main() void = {
diff --git a/test/fixtures/Makefile b/test/fixtures/Makefile
@@ -18,7 +18,7 @@ OCAMLOPT ?= ocamlopt
EMACS ?= emacs
SQUIRREL ?= squirrel3
-NONBUNDLED_BLOBS = hello hello.a hello.o
+NONBUNDLED_BLOBS = hello hello.a hello.o hello.erl.escript hello.beam.escript
TEST_BLOBS = $(NONBUNDLED_BLOBS) hello.exe hello.luac53 hello.luac54 hello.wasm hello.class hello.jar hello.nqp.moarvm hello.pir.pbc perl_storage.pst hello.beam empty.dtb hello-chez.so hello.n hello-ocaml.cmo hello-ocaml.cma hello-ocaml.cmx hello-ocaml.cmxa compiled/hello-racket_rkt.zo hello.elc hello.cnut
base: $(NONBUNDLED_BLOBS)
@@ -69,9 +69,17 @@ hello.pir.pbc: hello.pir
perl_storage.pst: perl_storage.pm
$(PERL) perl_storage.pm
+hello.erl.escript: hello.erl
+ echo '#!/usr/bin/env escript' | cat - hello.erl >|$@
+ chmod +x $@
+
hello.beam: hello.erl
$(ERLC) +deterministic hello.erl
+hello.beam.escript: hello.beam
+ echo '#!/usr/bin/env escript' | cat - hello.beam >|$@
+ chmod +x $@
+
empty.dtb: empty.dts
$(DTC) -o $@ -O dtb empty.dts
diff --git a/test/fixtures/hello.beam b/test/fixtures/hello.beam
Binary files differ.
diff --git a/test/fixtures/hello.erl b/test/fixtures/hello.erl
@@ -1,7 +1,7 @@
% SPDX-FileCopyrightText: 2019 deblob Authors <https://hacktivis.me/projects/deblob>
% SPDX-License-Identifier: BSD-3-Clause
-module(hello).
--export([main/0]).
+-export([main/1]).
-main() ->
+main(_) ->
io:fwrite("Hello, World!\n").