diff options
Diffstat (limited to 'lib/erl_interface/src/decode')
-rw-r--r-- | lib/erl_interface/src/decode/decode_atom.c | 161 | ||||
-rw-r--r-- | lib/erl_interface/src/decode/decode_boolean.c | 38 | ||||
-rw-r--r-- | lib/erl_interface/src/decode/decode_fun.c | 39 | ||||
-rw-r--r-- | lib/erl_interface/src/decode/decode_pid.c | 24 | ||||
-rw-r--r-- | lib/erl_interface/src/decode/decode_port.c | 23 | ||||
-rw-r--r-- | lib/erl_interface/src/decode/decode_ref.c | 47 | ||||
-rw-r--r-- | lib/erl_interface/src/decode/decode_skip.c | 5 | ||||
-rw-r--r-- | lib/erl_interface/src/decode/decode_trace.c | 30 |
8 files changed, 240 insertions, 127 deletions
diff --git a/lib/erl_interface/src/decode/decode_atom.c b/lib/erl_interface/src/decode/decode_atom.c index c2e6a0426e..44fd4df12c 100644 --- a/lib/erl_interface/src/decode/decode_atom.c +++ b/lib/erl_interface/src/decode/decode_atom.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2011. All Rights Reserved. + * Copyright Ericsson AB 1998-2013. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -21,24 +21,155 @@ #include "eiext.h" #include "putget.h" + int ei_decode_atom(const char *buf, int *index, char *p) { - const char *s = buf + *index; - const char *s0 = s; - int len; + return ei_decode_atom_as(buf, index, p, MAXATOMLEN, ERLANG_LATIN1, NULL, NULL); +} + +int ei_decode_atom_as(const char *buf, int *index, char* p, int destlen, + erlang_char_encoding want_enc, + erlang_char_encoding* was_encp, + erlang_char_encoding* res_encp) +{ + const char *s = buf + *index; + const char *s0 = s; + int len; + erlang_char_encoding got_enc; + + switch (get8(s)) { + case ERL_ATOM_EXT: + len = get16be(s); + got_enc = ERLANG_LATIN1; + break; + case ERL_SMALL_ATOM_EXT: + len = get8(s); + got_enc = ERLANG_LATIN1; + break; + case ERL_ATOM_UTF8_EXT: + len = get16be(s); + got_enc = ERLANG_UTF8; + break; + case ERL_SMALL_ATOM_UTF8_EXT: + len = get8(s); + got_enc = ERLANG_UTF8; + break; + default: + return -1; + } + + if ((want_enc & got_enc) || want_enc == ERLANG_ASCII) { + int i, found_non_ascii = 0; + if (len >= destlen) + return -1; + for (i=0; i<len; i++) { + if (s[i] & 0x80) found_non_ascii = 1; + if (p) p[i] = s[i]; + } + if (p) p[len] = 0; + if (want_enc == ERLANG_ASCII && found_non_ascii) { + return -1; + } + if (res_encp) { + *res_encp = found_non_ascii ? got_enc : ERLANG_ASCII; + } + } + else { + int plen = (got_enc == ERLANG_LATIN1) ? + latin1_to_utf8(p, s, len, destlen-1, res_encp) : + utf8_to_latin1(p, s, len, destlen-1, res_encp); + if (plen < 0) return -1; + if (p) p[plen] = 0; + } + if (was_encp) { + *was_encp = got_enc; + } + + s += len; + *index += s-s0; + return 0; +} - if (get8(s) != ERL_ATOM_EXT) return -1; - len = get16be(s); +int utf8_to_latin1(char* dst, const char* src, int slen, int destlen, + erlang_char_encoding* res_encp) +{ + const char* const dst_start = dst; + const char* const dst_end = dst + destlen; + int found_non_ascii = 0; + + while (slen > 0) { + if (dst >= dst_end) return -1; + if ((src[0] & 0x80) == 0) { + if (dst_start) { + *dst = *src; + } + ++dst; + ++src; + --slen; + } + else if (slen > 1 && + (src[0] & 0xFE) == 0xC2 && + (src[1] & 0xC0) == 0x80) { + if (dst_start) { + *dst = (char) ((src[0] << 6) | (src[1] & 0x3F)); + } + ++dst; + src += 2; + slen -= 2; + found_non_ascii = 1; + } + else return -1; + } + if (res_encp) { + *res_encp = found_non_ascii ? ERLANG_LATIN1 : ERLANG_ASCII; + } + return dst - dst_start; +} - if (len > MAXATOMLEN) return -1; +int latin1_to_utf8(char* dst, const char* src, int slen, int destlen, + erlang_char_encoding* res_encp) +{ + const char* const src_end = src + slen; + const char* const dst_start = dst; + const char* const dst_end = dst + destlen; + int found_non_ascii = 0; - if (p) { - memmove(p,s,len); - p[len] = (char)0; - } - s += len; - *index += s-s0; - - return 0; + while (src < src_end) { + if (dst >= dst_end) return -1; + if ((src[0] & 0x80) == 0) { + if (dst_start) { + *dst = *src; + } + ++dst; + } + else { + if (dst_start) { + unsigned char ch = *src; + dst[0] = 0xC0 | (ch >> 6); + dst[1] = 0x80 | (ch & 0x3F); + } + dst += 2; + found_non_ascii = 1; + } + ++src; + } + if (res_encp) { + *res_encp = found_non_ascii ? ERLANG_UTF8 : ERLANG_ASCII; + } + return dst - dst_start; } + + + +int ei_internal_get_atom(const char** bufp, char* p, + erlang_char_encoding* was_encp) +{ + int ix = 0; + if (ei_decode_atom_as(*bufp, &ix, p, MAXATOMLEN_UTF8, ERLANG_UTF8, was_encp, NULL) < 0) + return -1; + *bufp += ix; + return 0; +} + + diff --git a/lib/erl_interface/src/decode/decode_boolean.c b/lib/erl_interface/src/decode/decode_boolean.c index 9fd09c63f1..8c44a1ccfc 100644 --- a/lib/erl_interface/src/decode/decode_boolean.c +++ b/lib/erl_interface/src/decode/decode_boolean.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * Copyright Ericsson AB 1998-2013. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -24,34 +24,20 @@ /* c non-zero -> erlang "true" atom, otherwise "false" */ int ei_decode_boolean(const char *buf, int *index, int *p) { - const char *s = buf + *index; - const char *s0 = s; - int len; + char tbuf[6]; int t; - if (get8(s) != ERL_ATOM_EXT) return -1; + if (ei_decode_atom_as(buf, index, tbuf, sizeof(tbuf), ERLANG_ASCII, NULL, NULL) < 0) + return -1; - len = get16be(s); - - switch (len) { - case 4: - /* typecast makes ansi happy */ - if (strncmp((char*)s,"true",4)) return -1; - t = 1; - break; - - case 5: - if (strncmp((char*)s,"false",5)) return -1; - t = 0; - break; - - default: - return -1; - } - - s += len; + if (memcmp(tbuf, "true", 5) == 0) + t = 1; + else if (memcmp(tbuf, "false", 6) == 0) + t = 0; + else + return -1; + if (p) *p = t; - *index += s-s0; - return 0; } + diff --git a/lib/erl_interface/src/decode/decode_fun.c b/lib/erl_interface/src/decode/decode_fun.c index 64fb9e86d8..0857874c89 100644 --- a/lib/erl_interface/src/decode/decode_fun.c +++ b/lib/erl_interface/src/decode/decode_fun.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * Copyright Ericsson AB 2001-2013. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -30,6 +30,25 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p) const char *s = buf + *index; const char *s0 = s; int i, ix, ix0, n; + erlang_pid* p_pid; + char* p_module; + erlang_char_encoding* p_module_org_enc; + long* p_index; + long* p_uniq; + long* p_old_index; + + if (p != NULL) { + p_pid = &p->pid; + p_module = &p->module[0]; + p_module_org_enc = &p->module_org_enc; + p_index = &p->index; + p_uniq = &p->uniq; + p_old_index = &p->old_index; + } + else { + p_pid = NULL; p_module = NULL; p_module_org_enc = NULL; + p_index = NULL; p_uniq = NULL; p_old_index = NULL; + } switch (get8(s)) { case ERL_FUN_EXT: @@ -39,16 +58,17 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p) n = get32be(s); /* then the pid */ ix = 0; - if (ei_decode_pid(s, &ix, (p == NULL ? (erlang_pid*)NULL : &p->pid)) < 0) + if (ei_decode_pid(s, &ix, p_pid) < 0) return -1; /* then the module (atom) */ - if (ei_decode_atom(s, &ix, (p == NULL ? (char*)NULL : p->module)) < 0) + if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8, + p_module_org_enc, NULL) < 0) return -1; /* then the index */ - if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->index)) < 0) + if (ei_decode_long(s, &ix, p_index) < 0) return -1; /* then the uniq */ - if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->uniq)) < 0) + if (ei_decode_long(s, &ix, p_uniq) < 0) return -1; /* finally the free vars */ ix0 = ix; @@ -84,16 +104,17 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p) if (p != NULL) p->n_free_vars = i; /* then the module (atom) */ ix = 0; - if (ei_decode_atom(s, &ix, (p == NULL ? (char*)NULL : p->module)) < 0) + if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8, + p_module_org_enc, NULL) < 0) return -1; /* then the old_index */ - if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->old_index)) < 0) + if (ei_decode_long(s, &ix, p_old_index) < 0) return -1; /* then the old_uniq */ - if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->uniq)) < 0) + if (ei_decode_long(s, &ix, p_uniq) < 0) return -1; /* the the pid */ - if (ei_decode_pid(s, &ix, (p == NULL ? (erlang_pid*)NULL : &p->pid)) < 0) + if (ei_decode_pid(s, &ix, p_pid) < 0) return -1; /* finally the free vars */ s += ix; diff --git a/lib/erl_interface/src/decode/decode_pid.c b/lib/erl_interface/src/decode/decode_pid.c index 9ed1c36db6..cd5ae2ab20 100644 --- a/lib/erl_interface/src/decode/decode_pid.c +++ b/lib/erl_interface/src/decode/decode_pid.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2011. All Rights Reserved. + * Copyright Ericsson AB 1998-2013. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -21,34 +21,24 @@ #include "eiext.h" #include "putget.h" + int ei_decode_pid(const char *buf, int *index, erlang_pid *p) { const char *s = buf + *index; const char *s0 = s; - int len; if (get8(s) != ERL_PID_EXT) return -1; - /* first the nodename */ - if (get8(s) != ERL_ATOM_EXT) return -1; - - len = get16be(s); - - if (len > MAXATOMLEN) return -1; - - if (p) { - memmove(p->node, s, len); - p->node[len] = (char)0; - } - s += len; - - /* now the numbers: num (4), serial (4), creation (1) */ if (p) { + if (get_atom(&s, p->node, NULL) < 0) return -1; p->num = get32be(s) & 0x7fff; /* 15 bits */ p->serial = get32be(s) & 0x1fff; /* 13 bits */ p->creation = get8(s) & 0x03; /* 2 bits */ } - else s+= 9; + else { + if (get_atom(&s, NULL, NULL) < 0) return -1; + s+= 9; + } *index += s-s0; diff --git a/lib/erl_interface/src/decode/decode_port.c b/lib/erl_interface/src/decode/decode_port.c index 28abed801a..8fbdc5f3d3 100644 --- a/lib/erl_interface/src/decode/decode_port.c +++ b/lib/erl_interface/src/decode/decode_port.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2011. All Rights Reserved. + * Copyright Ericsson AB 1998-2013. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -25,29 +25,18 @@ int ei_decode_port(const char *buf, int *index, erlang_port *p) { const char *s = buf + *index; const char *s0 = s; - int len; if (get8(s) != ERL_PORT_EXT) return -1; - /* first the nodename */ - if (get8(s) != ERL_ATOM_EXT) return -1; - - len = get16be(s); - - if (len > MAXATOMLEN) return -1; - - if (p) { - memmove(p->node, s, len); - p->node[len] = (char)0; - } - s += len; - - /* now the numbers: num (4), creation (1) */ if (p) { + if (get_atom(&s, p->node, NULL) < 0) return -1; p->id = get32be(s) & 0x0fffffff /* 28 bits */; p->creation = get8(s) & 0x03; } - else s += 5; + else { + if (get_atom(&s, NULL, NULL) < 0) return -1; + s += 5; + } *index += s-s0; diff --git a/lib/erl_interface/src/decode/decode_ref.c b/lib/erl_interface/src/decode/decode_ref.c index 7b15808bc5..78db118172 100644 --- a/lib/erl_interface/src/decode/decode_ref.c +++ b/lib/erl_interface/src/decode/decode_ref.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2011. All Rights Reserved. + * Copyright Ericsson AB 1998-2013. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -21,35 +21,25 @@ #include "eiext.h" #include "putget.h" + int ei_decode_ref(const char *buf, int *index, erlang_ref *p) { const char *s = buf + *index; const char *s0 = s; - int count, len, i; + int count, i; switch (get8(s)) { case ERL_REFERENCE_EXT: - - /* first the nodename */ - if (get8(s) != ERL_ATOM_EXT) return -1; - - len = get16be(s); - - if (len > MAXATOMLEN) return -1; - - if (p) { - memmove(p->node, s, len); - p->node[len] = (char)0; - } - s += len; - - /* now the numbers: num (4), creation (1) */ if (p) { + if (get_atom(&s, p->node, NULL) < 0) return -1; p->n[0] = get32be(s); p->len = 1; p->creation = get8(s) & 0x03; } - else s += 5; + else { + if (get_atom(&s, NULL, NULL) < 0) return -1; + s += 5; + } *index += s-s0; @@ -59,24 +49,16 @@ int ei_decode_ref(const char *buf, int *index, erlang_ref *p) case ERL_NEW_REFERENCE_EXT: /* first the integer count */ count = get16be(s); - if (p) p->len = count; - - /* then the nodename */ - if (get8(s) != ERL_ATOM_EXT) return -1; - len = get16be(s); - if (len > MAXATOMLEN) return -1; if (p) { - memmove(p->node, s, len); - p->node[len] = (char)0; - } - s += len; - - /* creation */ - if (p) { + p->len = count; + if (get_atom(&s, p->node, NULL) < 0) return -1; p->creation = get8(s) & 0x03; } - else s += 1; + else { + if (get_atom(&s, NULL, NULL) < 0) return -1; + s += 1; + } /* finally the id integers */ if (p) { @@ -95,3 +77,4 @@ int ei_decode_ref(const char *buf, int *index, erlang_ref *p) return -1; } } + diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c index f6c5d861ab..553266471c 100644 --- a/lib/erl_interface/src/decode/decode_skip.c +++ b/lib/erl_interface/src/decode/decode_skip.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2002-2010. All Rights Reserved. + * Copyright Ericsson AB 2002-2013. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -30,7 +30,8 @@ int ei_skip_term(const char* buf, int* index) switch (ty) { case ERL_ATOM_EXT: /* FIXME: what if some weird locale is in use? */ - if (ei_decode_atom(buf, index, NULL) < 0) return -1; + if (ei_decode_atom_as(buf, index, NULL, MAXATOMLEN_UTF8, (ERLANG_LATIN1|ERLANG_UTF8), + NULL, NULL) < 0) return -1; break; case ERL_PID_EXT: if (ei_decode_pid(buf, index, NULL) < 0) return -1; diff --git a/lib/erl_interface/src/decode/decode_trace.c b/lib/erl_interface/src/decode/decode_trace.c index ebaa78e29e..d192c7f8b1 100644 --- a/lib/erl_interface/src/decode/decode_trace.c +++ b/lib/erl_interface/src/decode/decode_trace.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * Copyright Ericsson AB 1998-2013. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -22,18 +22,30 @@ int ei_decode_trace(const char *buf, int *index, erlang_trace *p) { int arity = 0; - int tindex = *index; - - /* use a temporary index if any function should fail */ + int tindex = *index; /* use a temporary index if any function should fail */ + long *p_flags, *p_label, *p_serial, *p_prev; + erlang_pid *p_from; + + if (p != NULL) { + p_flags = &p->flags; + p_label = &p->label; + p_serial = &p->serial; + p_prev = &p->prev; + p_from = &p->from; + } + else { + p_flags = p_label = p_serial = p_prev = NULL; + p_from = NULL; + } /* { Flags, Label, Serial, FromPid, Prev } */ if (ei_decode_tuple_header(buf, &tindex, &arity) || (arity != 5) - || ei_decode_long(buf, &tindex, &p->flags) - || ei_decode_long(buf, &tindex, &p->label) - || ei_decode_long(buf, &tindex, &p->serial) - || ei_decode_pid( buf, &tindex, &p->from) - || ei_decode_long(buf, &tindex, &p->prev)) return -1; + || ei_decode_long(buf, &tindex, p_flags) + || ei_decode_long(buf, &tindex, p_label) + || ei_decode_long(buf, &tindex, p_serial) + || ei_decode_pid( buf, &tindex, p_from) + || ei_decode_long(buf, &tindex, p_prev)) return -1; /* index is updated by the functions we called */ |