From da08da374cfa652374ddb46846550cc83798c2ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 21 May 2019 10:43:56 +0200 Subject: Correct decoding of external funs --- lib/erl_interface/src/decode/decode_fun.c | 3 +++ lib/erl_interface/src/decode/decode_skip.c | 1 + lib/erl_interface/test/ei_decode_encode_SUITE.erl | 8 +++++--- .../test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/src/decode/decode_fun.c b/lib/erl_interface/src/decode/decode_fun.c index 3a7a2b01c1..70e76e956c 100644 --- a/lib/erl_interface/src/decode/decode_fun.c +++ b/lib/erl_interface/src/decode/decode_fun.c @@ -146,6 +146,7 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p) else { p_arity = NULL; } + ix = 0; if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8, NULL, NULL) < 0) return -1; @@ -171,6 +172,8 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p) } if (ei_decode_long(s, &ix, p_arity) < 0) return -1; + s += ix; + *index += s - s0; return 0; } default: diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c index 736c00e074..0622ce7d59 100644 --- a/lib/erl_interface/src/decode/decode_skip.c +++ b/lib/erl_interface/src/decode/decode_skip.c @@ -97,6 +97,7 @@ int ei_skip_term(const char* buf, int* index) break; case ERL_FUN_EXT: case ERL_NEW_FUN_EXT: + case ERL_EXPORT_EXT: if (ei_decode_fun(buf, index, NULL) < 0) return -1; break; default: diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl index 3451d9f503..0204b4cfd6 100644 --- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl +++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl @@ -48,7 +48,8 @@ init_per_testcase(Case, Config) -> test_ei_decode_encode(Config) when is_list(Config) -> P = runner:start(Config, ?test_ei_decode_encode), - Fun = fun (X) -> {X,true} end, + Fun1 = fun (X) -> {X,true} end, + Fun2 = fun runner:init_per_testcase/3, Pid = self(), Port = case os:type() of {win32,_} -> @@ -70,7 +71,8 @@ test_ei_decode_encode(Config) when is_list(Config) -> BigLargeB = 1 bsl 11112 + BigSmallB, BigLargeC = BigSmallA * BigSmallB * BigSmallC * BigSmallA, - send_rec(P, Fun), + send_rec(P, Fun1), + send_rec(P, Fun2), send_rec(P, Pid), send_rec(P, Port), send_rec(P, Ref), @@ -115,7 +117,7 @@ test_ei_decode_encode(Config) when is_list(Config) -> send_rec(P, {}), send_rec(P, {atom, Pid, Port, Ref}), send_rec(P, [atom, Pid, Port, Ref]), - send_rec(P, [atom | Fun]), + send_rec(P, [atom | Fun1]), send_rec(P, #{}), send_rec(P, #{key => value}), send_rec(P, maps:put(Port, Ref, #{key => value, key2 => Pid})), diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c index 85ca6c56e9..512f9ed0c7 100644 --- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c +++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c @@ -563,6 +563,7 @@ TESTCASE(test_ei_decode_encode) ei_init(); + decode_encode_one(&fun_type); decode_encode_one(&fun_type); decode_encode_one(&pid_type); decode_encode_one(&port_type); -- cgit v1.2.3 From f53097e9f856281e7d8d89dc42716fb77b26e36e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 29 May 2019 16:16:37 +0200 Subject: Correct decoding of old funs (FUN_EXT) If the environment is empty, don't access the free_vars pointer and don't allocate a zero-size buffer. Better safe than sorry. --- lib/erl_interface/src/decode/decode_fun.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/src/decode/decode_fun.c b/lib/erl_interface/src/decode/decode_fun.c index 70e76e956c..db71007505 100644 --- a/lib/erl_interface/src/decode/decode_fun.c +++ b/lib/erl_interface/src/decode/decode_fun.c @@ -77,10 +77,12 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p) } if (p != NULL) { p->u.closure.n_free_vars = n; - p->u.closure.free_var_len = ix - ix0; - p->u.closure.free_vars = ei_malloc(ix - ix0); - if (!(p->u.closure.free_vars)) return -1; - memcpy(p->u.closure.free_vars, s + ix0, ix - ix0); + p->u.closure.free_var_len = ix - ix0; + if (p->u.closure.free_var_len > 0) { + p->u.closure.free_vars = ei_malloc(p->u.closure.free_var_len); + if (!(p->u.closure.free_vars)) return -1; + memcpy(p->u.closure.free_vars, s + ix0, p->u.closure.free_var_len); + } } s += ix; *index += s-s0; -- cgit v1.2.3 From 3d7b35dcc7852ec735f39a66566f80f8dad65701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 14 May 2019 08:15:59 +0200 Subject: Teach ei_print_term() to print maps --- lib/erl_interface/src/misc/ei_printterm.c | 19 +++++- lib/erl_interface/test/ei_print_SUITE.erl | 16 ++++- .../test/ei_print_SUITE_data/ei_print_test.c | 76 +++++++++++++++++----- 3 files changed, 92 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c index 5c40fb7747..52ab8cd504 100644 --- a/lib/erl_interface/src/misc/ei_printterm.c +++ b/lib/erl_interface/src/misc/ei_printterm.c @@ -306,12 +306,29 @@ static int print_term(FILE* fp, ei_x_buff* x, } break; - case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: if (ei_decode_double(buf, index, &d) < 0) goto err; ch_written += xprintf(fp, x, "%f", d); break; + case ERL_MAP_EXT: + if (ei_decode_map_header(buf, &tindex, &n) < 0) goto err; + ch_written += xprintf(fp, x, "#{"); + for (i = 0; i < n; ++i) { + r = print_term(fp, x, buf, &tindex); + if (r < 0) goto err; + ch_written += r; + ch_written += xprintf(fp, x, " => "); + r = print_term(fp, x, buf, &tindex); + if (r < 0) goto err; + ch_written += r; + if (i < n-1) { + xputs(", ", fp, x); ch_written += 2; + } + } + *index = tindex; + xputc('}', fp, x); ch_written++; + break; default: goto err; } diff --git a/lib/erl_interface/test/ei_print_SUITE.erl b/lib/erl_interface/test/ei_print_SUITE.erl index c75ce55a7d..9d88a28102 100644 --- a/lib/erl_interface/test/ei_print_SUITE.erl +++ b/lib/erl_interface/test/ei_print_SUITE.erl @@ -26,7 +26,7 @@ -export([all/0, suite/0, init_per_testcase/2, - atoms/1, tuples/1, lists/1, strings/1]). + atoms/1, tuples/1, lists/1, strings/1, maps/1]). -import(runner, [get_term/1]). @@ -36,8 +36,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> - [atoms, tuples, lists, strings]. +all() -> + [atoms, tuples, lists, strings, maps]. init_per_testcase(Case, Config) -> runner:init_per_testcase(?MODULE, Case, Config). @@ -142,3 +142,13 @@ strings(Config) when is_list(Config) -> runner:recv_eot(P), ok. + +maps(Config) -> + P = runner:start(Config, ?maps), + + {term, "#{}"} = get_term(P), + {term, "#{key => value}"} = get_term(P), + {term, "#{key => value, another_key => {ok, 42}}"} = get_term(P), + + runner:recv_eot(P), + ok. diff --git a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c index 80be3016e6..685596e34a 100644 --- a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c +++ b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c @@ -29,39 +29,54 @@ */ static void -send_printed3(char* format, char* p1, char* p2, int fl) +send_printed_buf(ei_x_buff* x) { char* b = NULL; - char fn[100], * tmp = getenv("temp"); + char fn[256]; + char *tmp = getenv("temp"); FILE* f; int n, index = 0, ver; - ei_x_buff x; - ei_x_new(&x); - if (fl) { - ei_x_format(&x, format, *(float*)p1, *(float*)p2); - } else { - ei_x_format(&x, format, p1, p2); - } #ifdef VXWORKS tmp = "."; #else - if (tmp == NULL) tmp = "/tmp"; + if (tmp == NULL) { + tmp = "/tmp"; + } #endif strcpy(fn, tmp); strcat(fn, "/ei_print_test.txt"); f = fopen(fn, "w+"); - ei_decode_version(x.buff, &index, &ver); - n = ei_print_term(f, x.buff, &index); + ei_decode_version(x->buff, &index, &ver); + n = ei_print_term(f, x->buff, &index); fseek(f, 0, SEEK_SET); b = malloc(n+1); fread(b, 1, n, f); b[n] = '\0'; fclose(f); - x.index = 0; - ei_x_format(&x, "~s", b); - send_bin_term(&x); + x->index = 0; + ei_x_format(x, "~s", b); + send_bin_term(x); free(b); +} + + +static void +send_printed3(char* format, char* p1, char* p2, int fl) +{ + char* b = NULL; + char fn[100], * tmp = getenv("temp"); + FILE* f; + int n, index = 0, ver; + ei_x_buff x; + + ei_x_new(&x); + if (fl) { + ei_x_format(&x, format, *(float*)p1, *(float*)p2); + } else { + ei_x_format(&x, format, p1, p2); + } + send_printed_buf(&x); ei_x_free(&x); } @@ -184,4 +199,35 @@ TESTCASE(strings) report(1); } +TESTCASE(maps) +{ + ei_x_buff x; + + ei_init(); + + ei_x_new_with_version(&x); + ei_x_encode_map_header(&x, 0); + send_printed_buf(&x); + ei_x_free(&x); + + ei_x_new_with_version(&x); + ei_x_encode_map_header(&x, 1); + ei_x_encode_atom(&x, "key"); + ei_x_encode_atom(&x, "value"); + send_printed_buf(&x); + ei_x_free(&x); + + ei_x_new_with_version(&x); + ei_x_encode_map_header(&x, 2); + ei_x_encode_atom(&x, "key"); + ei_x_encode_atom(&x, "value"); + ei_x_encode_atom(&x, "another_key"); + ei_x_encode_tuple_header(&x, 2); + ei_x_encode_atom(&x, "ok"); + ei_x_encode_long(&x, 42L); + send_printed_buf(&x); + ei_x_free(&x); + + report(1); +} -- cgit v1.2.3 From 5fef9df3faf0504c5c281a5720b992c19c94a6c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 21 May 2019 09:02:00 +0200 Subject: Teach ei_print_term() to print funs --- lib/erl_interface/src/misc/ei_printterm.c | 18 ++++++ lib/erl_interface/test/ei_print_SUITE.erl | 15 ++++- .../test/ei_print_SUITE_data/ei_print_test.c | 75 +++++++++++++++++++--- 3 files changed, 97 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c index 52ab8cd504..a94d6e2ad8 100644 --- a/lib/erl_interface/src/misc/ei_printterm.c +++ b/lib/erl_interface/src/misc/ei_printterm.c @@ -121,6 +121,7 @@ static int print_term(FILE* fp, ei_x_buff* x, erlang_pid pid; erlang_port port; erlang_ref ref; + erlang_fun fun; double d; long l; @@ -329,6 +330,23 @@ static int print_term(FILE* fp, ei_x_buff* x, *index = tindex; xputc('}', fp, x); ch_written++; break; + case ERL_FUN_EXT: + case ERL_NEW_FUN_EXT: + case ERL_EXPORT_EXT: + if (ei_decode_fun(buf, &tindex, &fun) < 0) goto err; + if (fun.type == EI_FUN_EXPORT) { + ch_written += xprintf(fp, x, "fun %s:%s/%ld", + fun.module, + fun.u.exprt.func, + fun.arity); + } else { + ch_written += xprintf(fp, x, "#Fun{%s.%ld.%lu}", + fun.module, + fun.u.closure.index, + fun.u.closure.uniq); + } + *index = tindex; + break; default: goto err; } diff --git a/lib/erl_interface/test/ei_print_SUITE.erl b/lib/erl_interface/test/ei_print_SUITE.erl index 9d88a28102..f2a2548183 100644 --- a/lib/erl_interface/test/ei_print_SUITE.erl +++ b/lib/erl_interface/test/ei_print_SUITE.erl @@ -26,7 +26,8 @@ -export([all/0, suite/0, init_per_testcase/2, - atoms/1, tuples/1, lists/1, strings/1, maps/1]). + atoms/1, tuples/1, lists/1, strings/1, + maps/1, funs/1]). -import(runner, [get_term/1]). @@ -37,7 +38,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [atoms, tuples, lists, strings, maps]. + [atoms, tuples, lists, strings, maps, funs]. init_per_testcase(Case, Config) -> runner:init_per_testcase(?MODULE, Case, Config). @@ -152,3 +153,13 @@ maps(Config) -> runner:recv_eot(P), ok. + +funs(Config) -> + P = runner:start(Config, ?funs), + + {term, "#Fun{some_module.42.3735928559}"} = get_term(P), + {term, "#Fun{some_module.37.195935983}"} = get_term(P), + {term, "fun erlang:abs/1"} = get_term(P), + + runner:recv_eot(P), + ok. diff --git a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c index 685596e34a..0e2b24e45a 100644 --- a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c +++ b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c @@ -49,15 +49,22 @@ send_printed_buf(ei_x_buff* x) f = fopen(fn, "w+"); ei_decode_version(x->buff, &index, &ver); n = ei_print_term(f, x->buff, &index); - fseek(f, 0, SEEK_SET); - b = malloc(n+1); - fread(b, 1, n, f); - b[n] = '\0'; - fclose(f); - x->index = 0; - ei_x_format(x, "~s", b); - send_bin_term(x); - free(b); + if (n < 0) { + fclose(f); + x->index = 0; + ei_x_format(x, "~s", "ERROR: term decoding failed"); + send_bin_term(x); + } else { + fseek(f, 0, SEEK_SET); + b = malloc(n+1); + fread(b, 1, n, f); + b[n] = '\0'; + fclose(f); + x->index = 0; + ei_x_format(x, "~s", b); + send_bin_term(x); + free(b); + } } @@ -231,3 +238,53 @@ TESTCASE(maps) report(1); } +TESTCASE(funs) +{ + ei_x_buff x; + erlang_pid self; + erlang_fun fun; + + strcpy(self.node, "node@host"); + self.num = 9; + self.serial = 99; + self.creation = 1; + + ei_init(); + + ei_x_new_with_version(&x); + fun.arity = -1; /* Will encode as FUN_EXT */ + strcpy(fun.module, "some_module"); + fun.type = EI_FUN_CLOSURE; + fun.u.closure.pid = self; + fun.u.closure.index = fun.u.closure.old_index = 42; + fun.u.closure.uniq = 0xDEADBEEF; + fun.u.closure.n_free_vars = 0; + fun.u.closure.free_var_len = 0; + ei_x_encode_fun(&x, &fun); + send_printed_buf(&x); + ei_x_free(&x); + + ei_x_new_with_version(&x); + fun.arity = 0; /* Will encode as NEW_FUN_EXT */ + strcpy(fun.module, "some_module"); + fun.type = EI_FUN_CLOSURE; + fun.u.closure.pid = self; + fun.u.closure.index = fun.u.closure.old_index = 37; + fun.u.closure.uniq = 0xBADBEEF; + fun.u.closure.n_free_vars = 0; + fun.u.closure.free_var_len = 0; + ei_x_encode_fun(&x, &fun); + send_printed_buf(&x); + ei_x_free(&x); + + ei_x_new_with_version(&x); + fun.arity = 1; + strcpy(fun.module, "erlang"); + fun.type = EI_FUN_EXPORT; + fun.u.exprt.func = "abs"; + ei_x_encode_fun(&x, &fun); + send_printed_buf(&x); + ei_x_free(&x); + + report(1); +} -- cgit v1.2.3