From 8231a315626a2ef0d8dcfecbdc5abb3bea175d4e Mon Sep 17 00:00:00 2001 From: Jordan Bracco Date: Thu, 14 May 2020 00:40:39 +0200 Subject: [PATCH 1/2] Improved Makefile Originally by @Kleidukos on evadne/gen_magic#11 --- Makefile | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 4866a1c..94ecb19 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,14 @@ # Apprentice binary -CC = gcc ERL_EI_INCLUDE:=$(shell erl -eval 'io:format("~s", [code:lib_dir(erl_interface, include)])' -s init stop -noshell | head -1) ERL_EI_LIB:=$(shell erl -eval 'io:format("~s", [code:lib_dir(erl_interface, lib)])' -s init stop -noshell | head -1) -CFLAGS = -std=c99 -g -Wall -Wextra -Werror -I$(ERL_EI_INCLUDE) -LDFLAGS = -L/usr/include/linux/ -L$(ERL_EI_LIB) -lm -lmagic -lei -lpthread -HEADER_FILES = src -C_SOURCE_FILES = src/apprentice.c -OBJECT_FILES = $(C_SOURCE_FILES:.c=.o) -EXECUTABLE_DIRECTORY = priv -EXECUTABLE = $(EXECUTABLE_DIRECTORY)/apprentice +CFLAGS = -std=c99 -g -Wall -Werror +CPPFLAGS = -I$(ERL_EI_INCLUDE) +LDFLAGS = -L$(ERL_EI_LIB) +LDLIBS = -lpthread -lei -lm -lmagic +BEAM_FILES = _build/ +PRIV = priv/ +RM = rm -Rf # Unit test custom magic file @@ -18,20 +17,9 @@ TEST_DIRECTORY = test TARGET_MAGIC = $(TEST_DIRECTORY)/elixir.mgc SOURCE_MAGIC = $(TEST_DIRECTORY)/elixir -# Target - -all: $(EXECUTABLE) $(TARGET_MAGIC) - -# Compile - -$(EXECUTABLE): $(OBJECT_FILES) $(EXECUTABLE_DIRECTORY) - $(CC) $(OBJECT_FILES) -o $@ $(LDFLAGS) - -$(EXECUTABLE_DIRECTORY): - mkdir -p $(EXECUTABLE_DIRECTORY) - -.o: - $(CC) $(CFLAGS) $< -o $@ +priv/apprentice: src/apprentice.c + mkdir -p priv + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ # Test case @@ -39,4 +27,6 @@ $(TARGET_MAGIC): $(SOURCE_MAGIC) cd $(TEST_DIRECTORY); $(MAGIC) -C -m elixir clean: - rm -f $(EXECUTABLE) $(OBJECT_FILES) $(BEAM_FILES) + $(RM) $(PRIV) $(BEAM_FILES) + +.PHONY: clean From 15560bccda3756207e5e0dced9cb14a4fae74cce Mon Sep 17 00:00:00 2001 From: Jordan Bracco Date: Thu, 14 May 2020 14:57:35 +0200 Subject: [PATCH 2/2] apprentice: fix `read_cmd` len read. Apparently the [example on erlang.org](https://erlang.org/doc/tutorial/erl_interface.html) is wrong for specific lengths of packets... --- lib/gen_magic/server.ex | 3 ++- src/apprentice.c | 52 ++++++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/lib/gen_magic/server.ex b/lib/gen_magic/server.ex index 5eaed86..09cdd41 100644 --- a/lib/gen_magic/server.ex +++ b/lib/gen_magic/server.ex @@ -282,7 +282,8 @@ defmodule GenMagic.Server do 21 => :eisdir, 20 => :enotdir, 12 => :enomem, - 24 => :emfile + 24 => :emfile, + 36 => :enametoolong, } @errno Map.keys(@errnos) diff --git a/src/apprentice.c b/src/apprentice.c index b3c578f..33c42b5 100644 --- a/src/apprentice.c +++ b/src/apprentice.c @@ -57,9 +57,6 @@ magic_t magic_setup(int flags); typedef char byte; -int read_cmd(byte *buf); -int write_cmd(byte *buf, int len); - void setup_environment(); void setup_options(int argc, char **argv); void setup_options_file(char *optarg); @@ -69,6 +66,8 @@ int process_command(byte *buf); void process_line(char *line); void process_file(char *path, ei_x_buff *result); void process_bytes(char *bytes, int size, ei_x_buff *result); +size_t read_cmd(byte *buf); +size_t write_cmd(byte *buf, size_t len); void error(ei_x_buff *result, const char *error); void handle_magic_error(magic_t handle, int errn, ei_x_buff *result); @@ -91,17 +90,17 @@ int main(int argc, char **argv) { ei_x_buff ok_buf; if (ei_x_new_with_version(&ok_buf) || ei_x_encode_atom(&ok_buf, "ready")) - return 5; + exit(ERROR_EI); write_cmd(ok_buf.buff, ok_buf.index); if (ei_x_free(&ok_buf) != 0) exit(ERROR_EI); - byte buf[4111]; + byte buf[4112]; while (read_cmd(buf) > 0) { process_command(buf); } - return 0; + return 255; } int process_command(byte *buf) { @@ -110,12 +109,14 @@ int process_command(byte *buf) { int index, version, arity, termtype, termsize; index = 0; - if (ei_decode_version(buf, &index, &version) != 0) + if (ei_decode_version(buf, &index, &version) != 0) { exit(ERROR_BAD_TERM); + } // Initialize result - if (ei_x_new_with_version(&result) || ei_x_encode_tuple_header(&result, 2)) + if (ei_x_new_with_version(&result) || ei_x_encode_tuple_header(&result, 2)) { exit(ERROR_EI); + } if (ei_decode_tuple_header(buf, &index, &arity) != 0) { error(&result, "badarg"); @@ -169,8 +170,9 @@ int process_command(byte *buf) { write_cmd(result.buff, result.index); - if (ei_x_free(&result) != 0) + if (ei_x_free(&result) != 0) { exit(ERROR_EI); + } return 0; } @@ -270,7 +272,8 @@ void process_bytes(char *path, int size, ei_x_buff *result) { return; } - const char *mime_encoding_result = magic_buffer(magic_mime_encoding, path, size); + const char *mime_encoding_result = + magic_buffer(magic_mime_encoding, path, size); int mime_encoding_errno = magic_errno(magic_mime_encoding); if (mime_encoding_errno > 0) { @@ -339,8 +342,11 @@ void process_file(char *path, ei_x_buff *result) { return; } -// From https://erlang.org/doc/tutorial/erl_interface.html -int read_exact(byte *buf, int len) { +// Adapted from https://erlang.org/doc/tutorial/erl_interface.html +// Changed `read_cmd`, the original one was buggy given some length (due to +// endinaness). +// TODO: Check if `write_cmd` exhibits the same issue. +size_t read_exact(byte *buf, size_t len) { int i, got = 0; do { @@ -353,7 +359,7 @@ int read_exact(byte *buf, int len) { return (len); } -int write_exact(byte *buf, int len) { +size_t write_exact(byte *buf, size_t len) { int i, wrote = 0; do { @@ -365,16 +371,20 @@ int write_exact(byte *buf, int len) { return (len); } -int read_cmd(byte *buf) { - int len; - - if (read_exact(buf, 2) != 2) - return (-1); - len = (buf[0] << 8) | buf[1]; - return read_exact(buf, len); +size_t read_cmd(byte *buf) { + int i; + if ((i = read(0, buf, sizeof(uint16_t))) <= 0) { + return (i); + } + uint16_t len16 = *(uint16_t *)buf; + len16 = ntohs(len16); + if (len16 > 4111) { + exit(ERROR_BAD_TERM); + } + return read_exact(buf, len16); } -int write_cmd(byte *buf, int len) { +size_t write_cmd(byte *buf, size_t len) { byte li; li = (len >> 8) & 0xff;