From d4170d92cca6256b8390222f09101e1c121becf9 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 24 Jan 2013 16:14:04 +0100 Subject: Validate UTF8/ASCII when buf is NULL --- lib/erl_interface/src/encode/encode_atom.c | 33 +++++++++++++++--------------- lib/erl_interface/src/misc/ei_x_encode.c | 3 ++- 2 files changed, 19 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/src/encode/encode_atom.c b/lib/erl_interface/src/encode/encode_atom.c index 044f17cb60..26e485518d 100644 --- a/lib/erl_interface/src/encode/encode_atom.c +++ b/lib/erl_interface/src/encode/encode_atom.c @@ -23,8 +23,8 @@ #include "putget.h" -static int copy_ascii_atom(char* dst, const char* src, int slen); -static int copy_utf8_atom(char* dst, const char* src, int slen); +static int verify_ascii_atom(const char* src, int slen); +static int verify_utf8_atom(const char* src, int slen); int ei_encode_atom(char *buf, int *index, const char *p) @@ -73,7 +73,8 @@ int ei_encode_atom_len_as(char *buf, int *index, const char *p, int len, if (len < 0) return -1; break; case ERLANG_ASCII: - if (copy_ascii_atom(s+2, p, len) < 0) return -1; + if (verify_ascii_atom(p, len) < 0) return -1; + memcpy(s+2, p, len); break; case ERLANG_LATIN1: memcpy(s+2, p, len); @@ -88,7 +89,8 @@ int ei_encode_atom_len_as(char *buf, int *index, const char *p, int len, if (from_enc == ERLANG_UTF8) { len = utf8_to_latin1(NULL, p, len, MAXATOMLEN-1, NULL); if (len < 0) return -1; - } + } else if (from_enc == ERLANG_ASCII) + if (verify_ascii_atom(p, len) < 0) return -1; } break; @@ -100,11 +102,13 @@ int ei_encode_atom_len_as(char *buf, int *index, const char *p, int len, len = latin1_to_utf8((buf ? s+offs : NULL), p, len, MAXATOMLEN_UTF8-1, NULL); break; case ERLANG_ASCII: - if (buf && copy_ascii_atom(s+offs, p, len) < 0) return -1; + if (verify_ascii_atom(p, len) < 0) return -1; + if (buf) memcpy(s+offs,p,len); break; case ERLANG_UTF8: if (len >= 256) offs++; - if (buf && copy_utf8_atom(s+offs, p, len) < 0) return -1; + if (verify_utf8_atom(p, len) < 0) return -1; + if (buf) memcpy(s+offs,p,len); break; default: return -1; @@ -144,17 +148,17 @@ ei_internal_put_atom(char** bufp, const char* p, int slen, } -int copy_ascii_atom(char* dst, const char* src, int slen) +int verify_ascii_atom(const char* src, int slen) { while (slen > 0) { if ((src[0] & 0x80) != 0) return -1; - *dst++ = *src++; + src++; slen--; } return 0; } -int copy_utf8_atom(char* dst, const char* src, int slen) +int verify_utf8_atom(const char* src, int slen) { int num_chars = 0; @@ -163,25 +167,22 @@ int copy_utf8_atom(char* dst, const char* src, int slen) if ((src[0] & 0x80) != 0) { if ((src[0] & 0xE0) == 0xC0) { if (slen < 2 || (src[1] & 0xC0) != 0x80) return -1; - *dst++ = *src++; + src++; slen--; } else if ((src[0] & 0xF0) == 0xE0) { if (slen < 3 || (src[1] & 0xC0) != 0x80 || (src[2] & 0xC0) != 0x80) return -1; - *dst++ = *src++; - *dst++ = *src++; + src += 2; slen -= 2; } else if ((src[0] & 0xF8) == 0xF0) { if (slen < 4 || (src[1] & 0xC0) != 0x80 || (src[2] & 0xC0) != 0x80 || (src[3] & 0xC0) != 0x80) return -1; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; + src += 3; slen -= 3; } else return -1; } - *dst++ = *src++; + src++; slen--; } return 0; diff --git a/lib/erl_interface/src/misc/ei_x_encode.c b/lib/erl_interface/src/misc/ei_x_encode.c index 44dcff7664..f46118830e 100644 --- a/lib/erl_interface/src/misc/ei_x_encode.c +++ b/lib/erl_interface/src/misc/ei_x_encode.c @@ -217,7 +217,8 @@ int ei_x_encode_atom_len_as(ei_x_buff* x, const char* s, int len, enum erlang_char_encoding to_enc) { int i = x->index; - ei_encode_atom_len_as(NULL, &i, s, len, from_enc, to_enc); + if (ei_encode_atom_len_as(NULL, &i, s, len, from_enc, to_enc) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_atom_len_as(x->buff, &x->index, s, len, from_enc, to_enc); -- cgit v1.2.3 From aab6011691ece92f9b5307162bd1a8bd1abdb9c2 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 23 Jan 2013 12:35:19 +0100 Subject: Add utf8 atom encode and decode testcases --- lib/erl_interface/test/all_SUITE_data/init_tc.erl | 2 +- lib/erl_interface/test/ei_decode_SUITE.erl | 78 ++++++- .../test/ei_decode_SUITE_data/ei_decode_test.c | 154 ++++++++++++- lib/erl_interface/test/ei_encode_SUITE.erl | 39 +++- .../test/ei_encode_SUITE_data/ei_encode_test.c | 244 +++++++++++++++++++++ 5 files changed, 500 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/test/all_SUITE_data/init_tc.erl b/lib/erl_interface/test/all_SUITE_data/init_tc.erl index 7e370c566a..0f2ac215f9 100644 --- a/lib/erl_interface/test/all_SUITE_data/init_tc.erl +++ b/lib/erl_interface/test/all_SUITE_data/init_tc.erl @@ -40,7 +40,7 @@ run([]) -> run1(Name) -> CFile = Name ++ ".c", {ok, Bin} = file:read_file(CFile), - RE = "\nTESTCASE\\(([_a-zA-Z]*)\\)", + RE = "\nTESTCASE\\(([_a-zA-Z0-9]*)\\)", {match, Cases0} = re:run(Bin, RE, [{capture,all_but_first,list},global]), Cases = lists:concat(Cases0), generate(Name, Cases). diff --git a/lib/erl_interface/test/ei_decode_SUITE.erl b/lib/erl_interface/test/ei_decode_SUITE.erl index 2c4b6e5541..5a94994912 100644 --- a/lib/erl_interface/test/ei_decode_SUITE.erl +++ b/lib/erl_interface/test/ei_decode_SUITE.erl @@ -27,14 +27,16 @@ -export( [ all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, + init_per_group/2,end_per_group/2, init_per_testcase/2, + end_per_testcase/2, test_ei_decode_long/1, test_ei_decode_ulong/1, test_ei_decode_longlong/1, test_ei_decode_ulonglong/1, test_ei_decode_char/1, test_ei_decode_nonoptimal/1, - test_ei_decode_misc/1 + test_ei_decode_misc/1, + test_ei_decode_utf8_atom/1 ]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -43,7 +45,7 @@ all() -> [test_ei_decode_long, test_ei_decode_ulong, test_ei_decode_longlong, test_ei_decode_ulonglong, test_ei_decode_char, test_ei_decode_nonoptimal, - test_ei_decode_misc]. + test_ei_decode_misc, test_ei_decode_utf8_atom]. groups() -> []. @@ -60,6 +62,11 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +init_per_testcase(_TC, Config) -> + Config. + +end_per_testcase(_RC, Config) -> + Config. %% --------------------------------------------------------------------------- @@ -221,6 +228,29 @@ test_ei_decode_misc(Config) when is_list(Config) -> ?line runner:recv_eot(P), ok. +%% ######################################################################## %% + +test_ei_decode_utf8_atom(Config) -> + ?line P = runner:start(?test_ei_decode_utf8_atom), + + send_utf8_atom_as_binary(P,"Ã¥"), + send_utf8_atom_as_binary(P,"ä"), + send_term_as_binary(P,'ö'), + send_term_as_binary(P,'õ'), + + ?line send_utf8_atom_as_binary(P,[1758]), + ?line send_utf8_atom_as_binary(P,[1758,1758]), + ?line send_utf8_atom_as_binary(P,[1758,1758,1758]), + ?line send_utf8_atom_as_binary(P,[1758,1758,1758,1758]), + + send_utf8_atom_as_binary(P,"a"), + send_utf8_atom_as_binary(P,"b"), + send_term_as_binary(P,'c'), + send_term_as_binary(P,'d'), + + ?line runner:recv_eot(P), + ok. + %% ######################################################################## %% @@ -230,6 +260,8 @@ send_term_as_binary(Port, Term) when is_port(Port) -> send_raw(Port, Bin) when is_port(Port) -> Port ! {self(), {command, Bin}}. +send_utf8_atom_as_binary(Port, String) -> + Port ! {self(), {command, term_to_binary(uc_atup(String))}}. send_integers(P) -> ?line send_term_as_binary(P,0), % SMALL_INTEGER_EXT smallest @@ -304,3 +336,43 @@ send_integers2(P) -> ?line send_term_as_binary(P, 16#ffffffffffffffff), % largest u64 ?line send_term_as_binary(P, []), % illegal type ok. + +uc_atup(ATxt) -> + string_to_atom(ATxt). + +string_to_atom(String) -> + Utf8List = string_to_utf8_list(String), + Len = length(Utf8List), + TagLen = case Len < 256 of + true -> [119, Len]; + false -> [118, Len bsr 8, Len band 16#ff] + end, + binary_to_term(list_to_binary([131, TagLen, Utf8List])). + +string_to_utf8_list([]) -> + []; +string_to_utf8_list([CP|CPs]) when is_integer(CP), + 0 =< CP, + CP =< 16#7F -> + [CP | string_to_utf8_list(CPs)]; +string_to_utf8_list([CP|CPs]) when is_integer(CP), + 16#80 =< CP, + CP =< 16#7FF -> + [16#C0 bor (CP bsr 6), + 16#80 bor (16#3F band CP) + | string_to_utf8_list(CPs)]; +string_to_utf8_list([CP|CPs]) when is_integer(CP), + 16#800 =< CP, + CP =< 16#FFFF -> + [16#E0 bor (CP bsr 12), + 16#80 bor (16#3F band (CP bsr 6)), + 16#80 bor (16#3F band CP) + | string_to_utf8_list(CPs)]; +string_to_utf8_list([CP|CPs]) when is_integer(CP), + 16#10000 =< CP, + CP =< 16#10FFFF -> + [16#F0 bor (CP bsr 18), + 16#80 bor (16#3F band (CP bsr 12)), + 16#80 bor (16#3F band (CP bsr 6)), + 16#80 bor (16#3F band CP) + | string_to_utf8_list(CPs)]. diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c index b349138ae9..6db04aa676 100644 --- a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c +++ b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c @@ -17,6 +17,8 @@ * %CopyrightEnd% */ +#include + #ifdef VXWORKS #include "reclaim.h" #endif @@ -38,6 +40,22 @@ err, size1, SIZE, (EI_LONGLONG)p); #endif +struct my_atom { + enum erlang_char_encoding from; + enum erlang_char_encoding was_check; + enum erlang_char_encoding result_check; +}; + +/* Allow arrays constants to be part of macro arguments */ +#define P99(...) __VA_ARGS__ + +int ei_decode_my_atom_as(const char *buf, int *index, char *to, + struct my_atom *atom); +int ei_decode_my_atom(const char *buf, int *index, char *to, + struct my_atom *atom); +int ei_decode_my_string(const char *buf, int *index, char *to, + struct my_atom *atom); + #define EI_DECODE_2(FUNC,SIZE,TYPE,VAL) \ { \ TYPE p; \ @@ -129,17 +147,26 @@ } \ } \ -#define EI_DECODE_STRING(FUNC,SIZE,VAL) \ +#define dump(arr, num) { \ + int i; \ + message("Dumping " #arr ": "); \ + for (i = 0; i < num; i++) message("%u, ",(unsigned char)arr[i]); \ + message("\n"); \ + } + +#define EI_DECODE_STRING_4(FUNC,SIZE,VAL,ATOM) \ { \ char p[1024]; \ char *buf; \ + unsigned char val[] = VAL; \ int size1 = 0; \ int size2 = 0; \ int err; \ - message("ei_" #FUNC " should be " #VAL); \ + struct my_atom atom = ATOM; \ + message("ei_" #FUNC " should be " #VAL "\n"); \ buf = read_packet(NULL); \ \ - err = ei_ ## FUNC(buf+1, &size1, NULL); \ + err = ei_ ## FUNC(buf+1, &size1, NULL, &atom); \ message("err = %d, size = %d, expected size = %d\n",err,size1,SIZE); \ if (err != 0) { \ if (err != -1) { \ @@ -150,7 +177,7 @@ return; \ } \ \ - err = ei_ ## FUNC(buf+1, &size2, p); \ + err = ei_ ## FUNC(buf+1, &size2, p, &atom); \ message("err = %d, size = %d, expected size = %d\n",err,size2,SIZE); \ if (err != 0) { \ if (err != -1) { \ @@ -161,7 +188,7 @@ return; \ } \ \ - if (strcmp(p,VAL) != 0) { \ + if (strcmp(p,val) != 0) { \ fail("value is not correct"); \ return; \ } \ @@ -177,6 +204,51 @@ } \ } \ +#define EI_DECODE_STRING(FUNC,SIZE,VAL) \ + EI_DECODE_STRING_4(FUNC,SIZE,VAL, \ + P99({ERLANG_ANY,ERLANG_ANY,ERLANG_ANY})) + +#define EI_DECODE_STRING_FAIL(FUNC,ATOM) \ + { \ + char p[1024]; \ + char *buf; \ + int size1 = 0; \ + int size2 = 0; \ + int err; \ + struct my_atom atom = ATOM;\ + message("ei_" #FUNC " should fail\n"); \ + p[0] = 0; \ + message("p[0] is %d\n",p[0]); \ + buf = read_packet(NULL); \ +\ + err = ei_ ## FUNC(buf+1, &size1, NULL, &atom); \ + if (err != -1) { \ + fail("should return -1 if NULL pointer"); \ + return; \ + } \ +\ + err = ei_ ## FUNC(buf+1, &size2, p, &atom); \ + if (err != -1) { \ + fail("should return -1"); \ + return; \ + } \ + if (p[0] != 0) { \ + message("p[0] argument was modified to %u\n",(unsigned char)p[0]); \ + } \ +\ + if (size1 != 0) { \ + fail("size of encoded data should be 0 if NULL"); \ + return; \ + } \ +\ + if (size2 != 0) { \ + fail("size of encoded data should be 0"); \ + return; \ + } \ + } \ + +//#define EI_DECODE_UTF8_STRING(FUNC,SIZE,VAL) + #define EI_DECODE_BIN(FUNC,SIZE,VAL,LEN) \ { \ char p[1024]; \ @@ -536,13 +608,13 @@ TESTCASE(test_ei_decode_misc) EI_DECODE_2(decode_boolean, 8, int, 0); EI_DECODE_2(decode_boolean, 7, int, 1); - EI_DECODE_STRING(decode_atom, 6, "foo"); - EI_DECODE_STRING(decode_atom, 3, ""); - EI_DECODE_STRING(decode_atom, 9, "ÅÄÖåäö"); + EI_DECODE_STRING(decode_my_atom, 6, "foo"); + EI_DECODE_STRING(decode_my_atom, 3, ""); + EI_DECODE_STRING(decode_my_atom, 9, "ÅÄÖåäö"); - EI_DECODE_STRING(decode_string, 6, "foo"); - EI_DECODE_STRING(decode_string, 1, ""); - EI_DECODE_STRING(decode_string, 9, "ÅÄÖåäö"); + EI_DECODE_STRING(decode_my_string, 6, "foo"); + EI_DECODE_STRING(decode_my_string, 1, ""); + EI_DECODE_STRING(decode_my_string, 9, "ÅÄÖåäö"); EI_DECODE_BIN(decode_binary, 8, "foo", 3); EI_DECODE_BIN(decode_binary, 5, "", 0); @@ -559,3 +631,63 @@ TESTCASE(test_ei_decode_misc) /* ******************************************************************** */ +TESTCASE(test_ei_decode_utf8_atom) +{ + + EI_DECODE_STRING_4(decode_my_atom_as, 4, P99({229,0}), /* LATIN1 "å" */ + P99({ERLANG_ANY,ERLANG_LATIN1,ERLANG_LATIN1})); + EI_DECODE_STRING_4(decode_my_atom_as, 4, P99({195,164,0}), /* UTF8 "ä" */ + P99({ERLANG_UTF8,ERLANG_LATIN1,ERLANG_UTF8})); + EI_DECODE_STRING_4(decode_my_atom_as, 4, P99({246,0}), /* LATIN1 "ö" */ + P99({ERLANG_LATIN1,ERLANG_LATIN1,ERLANG_LATIN1})); + EI_DECODE_STRING_FAIL(decode_my_atom_as, + P99({ERLANG_ASCII,ERLANG_ANY,ERLANG_ANY})); + + EI_DECODE_STRING_4(decode_my_atom_as, 4, P99({219,158,0}), + P99({ERLANG_ANY,ERLANG_UTF8,ERLANG_UTF8})); + EI_DECODE_STRING_4(decode_my_atom_as, 6, P99({219,158,219,158,0}), + P99({ERLANG_UTF8,ERLANG_UTF8,ERLANG_UTF8})); + EI_DECODE_STRING_FAIL(decode_my_atom_as, + P99({ERLANG_LATIN1,ERLANG_ANY,ERLANG_ANY})); + EI_DECODE_STRING_FAIL(decode_my_atom_as, + P99({ERLANG_ASCII,ERLANG_ANY,ERLANG_ANY})); + + EI_DECODE_STRING_4(decode_my_atom_as, 4, "a", + P99({ERLANG_ANY,ERLANG_LATIN1,ERLANG_ASCII})); + EI_DECODE_STRING_4(decode_my_atom_as, 4, "b", + P99({ERLANG_UTF8,ERLANG_LATIN1,ERLANG_ASCII})); + EI_DECODE_STRING_4(decode_my_atom_as, 4, "c", + P99({ERLANG_LATIN1,ERLANG_LATIN1,ERLANG_ASCII})); + EI_DECODE_STRING_4(decode_my_atom_as, 4, "d", + P99({ERLANG_ASCII,ERLANG_LATIN1,ERLANG_ASCII})); + + report(1); +} + +/* ******************************************************************** */ + +int ei_decode_my_atom_as(const char *buf, int *index, char *to, + struct my_atom *atom) { + enum erlang_char_encoding was,result; + int res = ei_decode_atom_as(buf,index,to,1024,atom->from,&was,&result); + if (res != 0) + return res; + if (!(was & atom->was_check)) { + message("Original encoding was %d not %d\n",was,atom->was_check); + return -1; + } else if (!(result & atom->result_check)) { + message("Result encoding was %d not %d\n",result,atom->result_check); + return -1; + } + return res; +} + +int ei_decode_my_atom(const char *buf, int *index, char *to, + struct my_atom *atom) { + return ei_decode_atom(buf, index, to); +} + +int ei_decode_my_string(const char *buf, int *index, char *to, + struct my_atom *atom) { + return ei_decode_string(buf, index, to); +} diff --git a/lib/erl_interface/test/ei_encode_SUITE.erl b/lib/erl_interface/test/ei_encode_SUITE.erl index 537e9cb01c..e0ac4c0637 100644 --- a/lib/erl_interface/test/ei_encode_SUITE.erl +++ b/lib/erl_interface/test/ei_encode_SUITE.erl @@ -34,7 +34,9 @@ test_ei_encode_ulonglong/1, test_ei_encode_char/1, test_ei_encode_misc/1, - test_ei_encode_fails/1 + test_ei_encode_fails/1, + test_ei_encode_utf8_atom/1, + test_ei_encode_utf8_atom_len/1 ]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -43,7 +45,8 @@ all() -> [test_ei_encode_long, test_ei_encode_ulong, test_ei_encode_longlong, test_ei_encode_ulonglong, test_ei_encode_char, test_ei_encode_misc, - test_ei_encode_fails]. + test_ei_encode_fails, test_ei_encode_utf8_atom, + test_ei_encode_utf8_atom_len]. groups() -> []. @@ -257,6 +260,38 @@ test_ei_encode_fails(Config) when is_list(Config) -> %% ######################################################################## %% +test_ei_encode_utf8_atom(Config) -> + ?line P = runner:start(?test_ei_encode_utf8_atom), + + ?line {<<119,2,195,133>>,'Ã…'} = get_buf_and_term(P), + ?line {<<100,0,1,197>>,'Ã…'} = get_buf_and_term(P), + ?line {<<100,0,1,197>>,'Ã…'} = get_buf_and_term(P), + ?line {<<119,2,195,133>>,'Ã…'} = get_buf_and_term(P), + + ?line {<<119,1,$A>>,'A'} = get_buf_and_term(P), + ?line {<<100,0,1,$A>>,'A'} = get_buf_and_term(P), + + ?line runner:recv_eot(P), + ok. + +%% ######################################################################## %% +test_ei_encode_utf8_atom_len(Config) -> + ?line P = runner:start(?test_ei_encode_utf8_atom_len), + + ?line {<<119,2,195,133>>,'Ã…'} = get_buf_and_term(P), + ?line {<<100,0,2,197,196>>,'ÅÄ'} = get_buf_and_term(P), + ?line {<<100,0,1,197>>,'Ã…'} = get_buf_and_term(P), + ?line {<<119,4,195,133,195,132>>,'ÅÄ'} = get_buf_and_term(P), + + ?line {<<119,1,$A>>,'A'} = get_buf_and_term(P), + ?line {<<100,0,2,$A,$B>>,'AB'} = get_buf_and_term(P), + ?line {<<100,0,255,_:(255*8)>>,_} = get_buf_and_term(P), + + ?line runner:recv_eot(P), + ok. + +%% ######################################################################## %% + % We read two packets for each test, the ei_encode and ei_x_encode version.... get_buf_and_term(P) -> diff --git a/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c b/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c index c373658152..e904375e9e 100644 --- a/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c +++ b/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c @@ -208,6 +208,196 @@ ei_x_free(&arg); \ } +#define EI_ENCODE_3(FUNC,ARG1,ARG2,ARG3) \ + { \ + char buf[1024]; \ + int size1 = 0; \ + int size2 = 0; \ + int err; \ + message("ei_" #FUNC " " #ARG1 " " #ARG2 " " #ARG3 " encoded as "); \ + err = ei_ ## FUNC(NULL, &size1, ARG1, ARG2, ARG3); \ + if (err != 0) { \ + if (err != -1) { \ + fail("size calculation returned non zero but not -1"); \ + return; \ + } else { \ + fail("size calculation returned non zero"); \ + return; \ + } \ + } \ + err = ei_ ## FUNC(buf, &size2, ARG1, ARG2, ARG3); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + return; \ + } \ + if (size1 != size2) { \ + fail("size differs when arg is NULL or buf"); \ + return; \ + } \ + if (size1 < 1) { \ + fail("size is < 1"); \ + return; \ + } \ + send_buffer(buf, size1); \ + } \ + { \ + ei_x_buff arg; \ + int err; \ + message("ei_x_" #FUNC " " #ARG1 " " #ARG2 " " #ARG3 " encoded as "); \ + ei_x_new(&arg); \ + err = ei_x_ ## FUNC(&arg, ARG1, ARG2, ARG3); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + ei_x_free(&arg); \ + return; \ + } \ + if (arg.index < 1) { \ + fail("size is < 1"); \ + ei_x_free(&arg); \ + return; \ + } \ + send_buffer(arg.buff, arg.index); \ + ei_x_free(&arg); \ + } + +#define EI_ENCODE_3_FAIL(FUNC,ARG1,ARG2,ARG3) \ + { \ + char buf[1024]; \ + int size1 = 0; \ + int size2 = 0; \ + int err; \ + message("ei_" #FUNC " " #ARG1 " " #ARG2 " " #ARG3 " encoded as "); \ + err = ei_ ## FUNC(NULL, &size1, ARG1, ARG2, ARG3); \ + if (err != -1) { \ + fail("size calculation returned non -1"); \ + return; \ + } \ + err = ei_ ## FUNC(buf, &size2, ARG1, ARG2, ARG3); \ + if (err != -1) { \ + fail("returned non -1"); \ + } \ + if (size1 != size2) { \ + fail("size differs when arg is NULL or buf"); \ + return; \ + } \ + } \ + { \ + ei_x_buff arg; \ + int err; \ + message("ei_x_" #FUNC " " #ARG1 " " #ARG2 " " #ARG3 " encoded as "); \ + ei_x_new(&arg); \ + err = ei_x_ ## FUNC(&arg, ARG1, ARG2, ARG3); \ + if (err != -1) { \ + fail("returned non -1"); \ + ei_x_free(&arg); \ + return; \ + } \ + ei_x_free(&arg); \ + } + +#define EI_ENCODE_4(FUNC,ARG1,ARG2,ARG3,ARG4) \ + { \ + char buf[1024]; \ + int size1 = 0; \ + int size2 = 0; \ + int err; \ + message("ei_" #FUNC " " #ARG1 " " #ARG2 " " #ARG3 " " #ARG4 " encoded as "); \ + err = ei_ ## FUNC(NULL, &size1, ARG1, ARG2, ARG3, ARG4); \ + if (err != 0) { \ + if (err != -1) { \ + fail("size calculation returned non zero but not -1"); \ + return; \ + } else { \ + fail("size calculation returned non zero"); \ + return; \ + } \ + } \ + err = ei_ ## FUNC(buf, &size2, ARG1, ARG2, ARG3, ARG4); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + return; \ + } \ + if (size1 != size2) { \ + fail("size differs when arg is NULL or buf"); \ + return; \ + } \ + if (size1 < 1) { \ + fail("size is < 1"); \ + return; \ + } \ + send_buffer(buf, size1); \ + } \ + { \ + ei_x_buff arg; \ + int err; \ + message("ei_x_" #FUNC " " #ARG1 " " #ARG2 " " #ARG3 " " #ARG4 " encoded as "); \ + ei_x_new(&arg); \ + err = ei_x_ ## FUNC(&arg, ARG1, ARG2, ARG3, ARG4); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + ei_x_free(&arg); \ + return; \ + } \ + if (arg.index < 1) { \ + fail("size is < 1"); \ + ei_x_free(&arg); \ + return; \ + } \ + send_buffer(arg.buff, arg.index); \ + ei_x_free(&arg); \ + } + +#define EI_ENCODE_4_FAIL(FUNC,ARG1,ARG2,ARG3,ARG4) \ + { \ + char buf[1024]; \ + int size1 = 0; \ + int size2 = 0; \ + int err; \ + message("ei_" #FUNC " " #ARG1 " " #ARG2 " " #ARG3 " " #ARG4 " encoded as "); \ + err = ei_ ## FUNC(NULL, &size1, ARG1, ARG2, ARG3, ARG4); \ + if (err != -1) { \ + fail("size calculation returned non -1"); \ + return; \ + } \ + err = ei_ ## FUNC(buf, &size2, ARG1, ARG2, ARG3, ARG4); \ + if (err != -1) { \ + fail("returned non -1"); \ + } \ + if (size1 != size2) { \ + fail("size differs when arg is NULL or buf"); \ + return; \ + } \ + } \ + { \ + ei_x_buff arg; \ + int err; \ + message("ei_x_" #FUNC " " #ARG1 " " #ARG2 " " #ARG3 " " #ARG4 " encoded as "); \ + ei_x_new(&arg); \ + err = ei_x_ ## FUNC(&arg, ARG1, ARG2, ARG3, ARG4); \ + if (err != -1) { \ + fail("returned non -1"); \ + ei_x_free(&arg); \ + return; \ + } \ + ei_x_free(&arg); \ + } + /* ******************************************************************** */ TESTCASE(test_ei_encode_long) @@ -464,3 +654,57 @@ TESTCASE(test_ei_encode_fails) report(1); } + +/* ******************************************************************** */ + +TESTCASE(test_ei_encode_utf8_atom) +{ + + EI_ENCODE_3(encode_atom_as, "Å", ERLANG_LATIN1, ERLANG_UTF8); + EI_ENCODE_3(encode_atom_as, "Å", ERLANG_LATIN1, ERLANG_LATIN1); + EI_ENCODE_3(encode_atom_as, "\303\205", + ERLANG_UTF8, ERLANG_LATIN1); + EI_ENCODE_3(encode_atom_as, "\303\205", + ERLANG_UTF8, ERLANG_UTF8); + + EI_ENCODE_3(encode_atom_as, "A", ERLANG_ASCII, ERLANG_UTF8); + EI_ENCODE_3(encode_atom_as, "A", ERLANG_ASCII, ERLANG_LATIN1); + + EI_ENCODE_3_FAIL(encode_atom_as, "Å", ERLANG_UTF8, ERLANG_UTF8); + EI_ENCODE_3_FAIL(encode_atom_as, "Å", ERLANG_UTF8, ERLANG_LATIN1); + EI_ENCODE_3_FAIL(encode_atom_as, "Å", ERLANG_ASCII, ERLANG_UTF8); + EI_ENCODE_3_FAIL(encode_atom_as, "Å", ERLANG_ASCII, ERLANG_LATIN1); + + EI_ENCODE_3_FAIL(encode_atom_as, "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", ERLANG_ASCII, ERLANG_LATIN1); + EI_ENCODE_3_FAIL(encode_atom_as, "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", ERLANG_LATIN1, ERLANG_LATIN1); + + EI_ENCODE_3_FAIL(encode_atom_as, "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", ERLANG_UTF8, ERLANG_LATIN1); + + report(1); +} + +TESTCASE(test_ei_encode_utf8_atom_len) +{ + + EI_ENCODE_4(encode_atom_len_as, "ÅÄÖ", 1, ERLANG_LATIN1, ERLANG_UTF8); + EI_ENCODE_4(encode_atom_len_as, "ÅÄÖ", 2, ERLANG_LATIN1, ERLANG_LATIN1); + EI_ENCODE_4(encode_atom_len_as, "\303\205\303\204\303\226", 2, + ERLANG_UTF8, ERLANG_LATIN1); + EI_ENCODE_4(encode_atom_len_as, "\303\205\303\204\303\226", 4, + ERLANG_UTF8, ERLANG_UTF8); + + EI_ENCODE_4(encode_atom_len_as, "ABC", 1, ERLANG_ASCII, ERLANG_UTF8); + EI_ENCODE_4(encode_atom_len_as, "ABC", 2, ERLANG_ASCII, ERLANG_LATIN1); + + EI_ENCODE_4_FAIL(encode_atom_len_as, "ÅÄÖ", 1, ERLANG_UTF8, ERLANG_UTF8); + EI_ENCODE_4_FAIL(encode_atom_len_as, "ÅÄÖ", 2, ERLANG_UTF8, ERLANG_LATIN1); + EI_ENCODE_4_FAIL(encode_atom_len_as, "ÅÄÖ", 3, ERLANG_ASCII, ERLANG_UTF8); + EI_ENCODE_4_FAIL(encode_atom_len_as, "ÅÄÖ", 4, ERLANG_ASCII, ERLANG_LATIN1); + + EI_ENCODE_4(encode_atom_len_as, "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", 255, ERLANG_ASCII, ERLANG_LATIN1); + + EI_ENCODE_4_FAIL(encode_atom_len_as, "\303\205\303\204\303\226", 1, + ERLANG_UTF8, ERLANG_LATIN1); + + report(1); +} -- cgit v1.2.3 From 6058758c7b81cf458b1498bef76d672a207df4e8 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 24 Jan 2013 17:46:06 +0100 Subject: Return if size test fails This is needed in order to avoid potential buffer overruns in the encode functions --- lib/erl_interface/src/misc/ei_x_encode.c | 48 +++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/src/misc/ei_x_encode.c b/lib/erl_interface/src/misc/ei_x_encode.c index f46118830e..b08d87a95f 100644 --- a/lib/erl_interface/src/misc/ei_x_encode.c +++ b/lib/erl_interface/src/misc/ei_x_encode.c @@ -99,7 +99,8 @@ int ei_x_encode_string(ei_x_buff* x, const char* s) int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len) { int i = x->index; - ei_encode_string_len(NULL, &i, s, len); + if (ei_encode_string_len(NULL, &i, s, len) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_string_len(x->buff, &x->index, s, len); @@ -108,7 +109,8 @@ int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len) int ei_x_encode_binary(ei_x_buff* x, const void* p, int len) { int i = x->index; - ei_encode_binary(NULL, &i, p, len); + if (ei_encode_binary(NULL, &i, p, len) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_binary(x->buff, &x->index, p, len); @@ -117,7 +119,8 @@ int ei_x_encode_binary(ei_x_buff* x, const void* p, int len) int ei_x_encode_long(ei_x_buff* x, long n) { int i = x->index; - ei_encode_long(NULL, &i, n); + if (ei_encode_long(NULL, &i, n) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_long(x->buff, &x->index, n); @@ -126,7 +129,8 @@ int ei_x_encode_long(ei_x_buff* x, long n) int ei_x_encode_ulong(ei_x_buff* x, unsigned long n) { int i = x->index; - ei_encode_ulong(NULL, &i, n); + if (ei_encode_ulong(NULL, &i, n) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_ulong(x->buff, &x->index, n); @@ -135,7 +139,8 @@ int ei_x_encode_ulong(ei_x_buff* x, unsigned long n) int ei_x_encode_char(ei_x_buff* x, char p) { int i = x->index; - ei_encode_char(NULL, &i, p); + if (ei_encode_char(NULL, &i, p) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_char(x->buff, &x->index, p); @@ -144,7 +149,8 @@ int ei_x_encode_char(ei_x_buff* x, char p) int ei_x_encode_boolean(ei_x_buff* x, int p) { int i = x->index; - ei_encode_boolean(NULL, &i, p); + if (ei_encode_boolean(NULL, &i, p) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_boolean(x->buff, &x->index, p); @@ -153,7 +159,8 @@ int ei_x_encode_boolean(ei_x_buff* x, int p) int ei_x_encode_double(ei_x_buff* x, double dbl) { int i = x->index; - ei_encode_double(NULL, &i, dbl); + if (ei_encode_double(NULL, &i, dbl) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_double(x->buff, &x->index, dbl); @@ -162,7 +169,8 @@ int ei_x_encode_double(ei_x_buff* x, double dbl) int ei_x_encode_list_header(ei_x_buff* x, long n) { int i = x->index; - ei_encode_list_header(NULL, &i, n); + if (ei_encode_list_header(NULL, &i, n) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_list_header(x->buff, &x->index, n); @@ -171,7 +179,8 @@ int ei_x_encode_list_header(ei_x_buff* x, long n) int ei_x_encode_empty_list(ei_x_buff* x) { int i = x->index; - ei_encode_empty_list(NULL, &i); + if (ei_encode_empty_list(NULL, &i) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_empty_list(x->buff, &x->index); @@ -180,7 +189,8 @@ int ei_x_encode_empty_list(ei_x_buff* x) int ei_x_encode_version(ei_x_buff* x) { int i = x->index; - ei_encode_version(NULL, &i); + if (ei_encode_version(NULL, &i) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_version(x->buff, &x->index); @@ -189,7 +199,8 @@ int ei_x_encode_version(ei_x_buff* x) int ei_x_encode_tuple_header(ei_x_buff* x, long n) { int i = x->index; - ei_encode_tuple_header(NULL, &i, n); + if (ei_encode_tuple_header(NULL, &i, n) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_tuple_header(x->buff, &x->index, n); @@ -228,7 +239,8 @@ int ei_x_encode_atom_len_as(ei_x_buff* x, const char* s, int len, int ei_x_encode_pid(ei_x_buff* x, const erlang_pid* pid) { int i = x->index; - ei_encode_pid(NULL, &i, pid); + if (ei_encode_pid(NULL, &i, pid) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_pid(x->buff, &x->index, pid); @@ -237,7 +249,8 @@ int ei_x_encode_pid(ei_x_buff* x, const erlang_pid* pid) int ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun) { int i = x->index; - ei_encode_fun(NULL, &i, fun); + if (ei_encode_fun(NULL, &i, fun) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_fun(x->buff, &x->index, fun); @@ -246,7 +259,8 @@ int ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun) int ei_x_encode_ref(ei_x_buff* x, const erlang_ref* ref) { int i = x->index; - ei_encode_ref(NULL, &i, ref); + if (ei_encode_ref(NULL, &i, ref) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_ref(x->buff, &x->index, ref); @@ -255,7 +269,8 @@ int ei_x_encode_ref(ei_x_buff* x, const erlang_ref* ref) int ei_x_encode_port(ei_x_buff* x, const erlang_port* port) { int i = x->index; - ei_encode_port(NULL, &i, port); + if (ei_encode_port(NULL, &i, port) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_port(x->buff, &x->index, port); @@ -264,7 +279,8 @@ int ei_x_encode_port(ei_x_buff* x, const erlang_port* port) int ei_x_encode_trace(ei_x_buff* x, const erlang_trace* trace) { int i = x->index; - ei_encode_trace(NULL, &i, trace); + if (ei_encode_trace(NULL, &i, trace) == -1) + return -1; if (!x_fix_buff(x, i)) return -1; return ei_encode_trace(x->buff, &x->index, trace); -- cgit v1.2.3