Some bugfixes in ei_x_format in R13B02-1

View: New views
2 Messages — Rating Filter:   Alert me  

Some bugfixes in ei_x_format in R13B02-1

by Christopher Faulet :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi all,

the attached patch fixes some bugs in functions that build terms from
strings, called by ei_x_format and ei_x_format_wo_ver. It improves the
parsing of lists, tuples, strings, atoms and digits. The file test_ei.c
in attachement shows examples that ei_x_format doesn't parse correctly.

In addition, I added support of hexadecimal representations of digit.

This patch also fixes a bug in erl_call. When we use the option "-a 'Mod
Fun Args'", the module and function are extracted and the remainings are
passed to ei_x_format_wo_ver in order to build arguments before calling
the function ei_rpc. The problem is that this function tries to replace
all ~a,~s,~i... But in this context, it's a mistake. To avoid this
behaviour, I added a new function, ei_x_parse, that transforms a string
in erlang term without any replacement. Here is an example:

  * the following command returns an error instead of ["test"]:
      erl_call -sname bug_ei -s -a 'io_lib format ["~p", [test]]'

I only tested this patch on linux but I hope that it works on other OS.

Best regards,
--
Christopher Faulet <christopher.faulet@...>

--- lib/erl_interface/include/ei.h.orig 2009-10-06 21:45:09.000000000 +0200
+++ lib/erl_interface/include/ei.h 2009-10-06 21:46:22.000000000 +0200
@@ -500,6 +500,7 @@
 
 int ei_x_format(ei_x_buff* x, const char* fmt, ...);
 int ei_x_format_wo_ver(ei_x_buff* x, const char *fmt, ...);
+int ei_x_parse(ei_x_buff *x, const char* str);
 
 int ei_x_new(ei_x_buff* x);
 int ei_x_new_with_version(ei_x_buff* x);
--- lib/erl_interface/src/prog/erl_call.c.orig 2009-10-06 21:46:10.000000000 +0200
+++ lib/erl_interface/src/prog/erl_call.c 2009-10-07 23:00:11.000000000 +0200
@@ -562,7 +562,7 @@
 
       ei_x_new(&e); /* No version to ei_rpc() */
       
-      if (ei_x_format_wo_ver(&e, args) < 0) {
+      if (ei_x_parse(&e, args) < 0) {
   /* FIXME no error message and why -1 ? */
   exit(-1);
       }
--- lib/erl_interface/src/encode/encode_atom.c.orig 2009-10-06 21:45:46.000000000 +0200
+++ lib/erl_interface/src/encode/encode_atom.c 2009-10-07 22:59:50.000000000 +0200
@@ -28,6 +28,7 @@
 
 int ei_encode_atom_len(char *buf, int *index, const char *p, int len)
 {
+  int i;
   char *s = buf + *index;
   char *s0 = s;
 
@@ -35,14 +36,18 @@
   if (len > MAXATOMLEN)
     len = MAXATOMLEN;
 
-  if (!buf) s += 3;
+  if (!buf) s += 3 + len;
   else {
     put8(s,ERL_ATOM_EXT);
     put16be(s,len);
 
-    memmove(s,p,len); /* unterminated string */
+    for (i = 0; i < len; ++i) {
+      if (p[i] != '\\' || p[i-1] == '\\')
+ put8(s, p[i]);
+      else
+ ++len;
+    }
   }
-  s += len;
 
   *index += s-s0;
 
--- lib/erl_interface/src/encode/encode_string.c.orig 2009-10-06 21:45:58.000000000 +0200
+++ lib/erl_interface/src/encode/encode_string.c 2009-10-07 22:59:42.000000000 +0200
@@ -44,14 +44,18 @@
     } else if (len <= 0xffff) {
 
       if (!buf) {
- s += 3;
+ s += 3 + len;
       } else {
  put8(s,ERL_STRING_EXT);
  put16be(s,len);
- memmove(s,p,len); /* unterminated string */
-      }
-      s += len;
 
+ for (i = 0; i < len; ++i) {
+  if (p[i] != '\\' || p[i-1] == '\\')
+    put8(s, p[i]);
+  else
+    ++len;
+ }
+      }
     } else {
 
       if (!buf) {
@@ -62,8 +66,12 @@
  put32be(s,len);
 
  for (i=0; i<len; i++) {
-  put8(s,ERL_SMALL_INTEGER_EXT);
-  put8(s,p[i]);
+  if (p[i] != '\\' || p[i-1] == '\\') {
+    put8(s,ERL_SMALL_INTEGER_EXT);
+    put8(s,p[i]);
+  }
+  else
+    ++len;
  }
  put8(s,ERL_NIL_EXT);
       }
--- lib/erl_interface/src/misc/ei_x_encode.c.orig 2009-10-06 21:45:34.000000000 +0200
+++ lib/erl_interface/src/misc/ei_x_encode.c 2009-10-07 22:59:22.000000000 +0200
@@ -93,7 +93,13 @@
 
 int ei_x_encode_string(ei_x_buff* x, const char* s)
 {
-    return ei_x_encode_string_len(x, s, strlen(s));
+    int len, i;
+    
+    for (i = 0, len = 0; s[i] != 0; ++i) {
+        if (s[i] != '\\' || s[i-1] == '\\')
+    ++len;
+    }
+    return ei_x_encode_string_len(x, s, len);
 }
 
 int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len)
@@ -197,7 +203,13 @@
 
 int ei_x_encode_atom(ei_x_buff* x, const char* s)
 {
-    return ei_x_encode_atom_len(x, s, strlen(s));
+    int len, i;
+
+    for (i = 0, len = 0; s[i] != 0; ++i) {
+        if (s[i] != '\\' || s[i-1] == '\\')
+    ++len;
+    }
+    return ei_x_encode_atom_len(x, s, len);
 }
 
 int ei_x_encode_atom_len(ei_x_buff* x, const char* s, int len)
--- lib/erl_interface/src/misc/ei_format.c.orig 2009-10-06 21:45:20.000000000 +0200
+++ lib/erl_interface/src/misc/ei_format.c 2009-10-07 22:58:54.000000000 +0200
@@ -71,29 +71,29 @@
     int res;
     ei_x_buff x2;
 
-    while (isspace((int)*p))
- ++p;
+    for (; isspace((int)*p); ++p);
+
     switch (*p) {
     case '~':
  res = pformat(&p, args, x);
  break;
     case '[':
  res = ei_x_new(&x2);
- if (res >= 0)
+ if (res != -1)
     res = plist(&p, args, &x2, 0);
  if (res > 0)
     res = ei_x_encode_list_header(x, res);
- if (res >= 0)
+ if (res != -1)
     res = ei_x_append(x, &x2);
  ei_x_free(&x2);
  break;
     case '{':
  res = ei_x_new(&x2);
- if (res >= 0)
+ if (res != -1)
     res = ptuple(&p, args, &x2, 0);
- if (res >= 0)
+ if (res != -1)
     res = ei_x_encode_tuple_header(x, res);
- if (res >= 0)
+ if (res != -1)
     res = ei_x_append(x, &x2);
  ei_x_free(&x2);
  break;
@@ -104,7 +104,7 @@
  res = pquotedatom(&p, x);
  break;
     default:
- if (isdigit((int)*p))
+ if (*p == '-' || *p == '+' || isdigit((int)*p))
     res = pdigit(&p, x);
  else if (islower((int)*p))
     res = patom(&p, x);
@@ -115,6 +115,7 @@
  Variables
  */
     }
+
     *fmt = p;
     return res;
 }
@@ -123,49 +124,58 @@
 {
     const char* start = *fmt;
     char c;
-    int len;
-    
-    for (;;) {
- c = *(*fmt)++;
- if (isalnum((int) c) || (c == '_') || (c == '@'))
-    continue;
- else
+
+    for (;; ++(*fmt)) {
+ c = **fmt;
+ if (!isalnum((int)c) && c != '_' && c != '@')
     break;
     }
-    --(*fmt);
-    len = *fmt - start;
-    /* FIXME why truncate atom name and not fail?! */
-    if (len > MAXATOMLEN)
- len = MAXATOMLEN;
-    return ei_x_encode_atom_len(x, start, len);
+    return ei_x_encode_atom_len(x, start, *fmt - start);
 }
 
 /* Check if integer or float */
 static int pdigit(const char** fmt, ei_x_buff* x)
 {
-    const char* start = *fmt;
-    char c;
-    int len, dotp=0;
+    const char* p = *fmt;
+    char* endp;
+    int is_double, base = 10;
     double d;
     long l;
 
-    for (;;) {
- c = *(*fmt)++;
- if (isdigit((int)c))
-    continue;
- else if (!dotp && (c == '.')) {
-    dotp = 1;
-    continue;
- } else
+    /* skip the sign, if any */
+    if (*p == '-' || *p == '+')
+ ++p;
+
+    /* is double or not ? */
+    for (is_double = 0;; ++p) {
+ if (*p == '.') {
+    is_double = 1;
+    break;
+ }
+ else if (*p == 'x' || *p == 'X')
+    base = 16;
+ else if (base == 10 && !isdigit((int)*p))
+    break;
+ else if (base == 16 && !isxdigit((int)*p))
     break;
-    }
-    --(*fmt);
-    len = *fmt - start;
-    if (dotp) {
- sscanf(start, "%lf", &d);
+    }
+
+    errno = 0;
+
+    /* convert and encode a double value */
+    if (is_double) {
+ d = strtod(*fmt, &endp);
+ if (errno == ERANGE)
+    return -1;
+ *fmt = endp;
  return ei_x_encode_double(x, d);
-    } else {
- sscanf(start, "%ld", &l);
+    }
+    /* convert and encode a long value */
+    else {
+ l = strtol(*fmt, &endp, base);
+ if (errno == ERANGE)
+    return -1;
+ *fmt = endp;
  return ei_x_encode_long(x, l);
     }
 }
@@ -174,22 +184,24 @@
 static int pstring(const char** fmt, ei_x_buff* x)
 {
     const char* start = ++(*fmt); /* skip first quote */
-    char c;
-    int res;
-    
-    for (;;) {
- c = *(*fmt)++;
- if (c == '\0')
+    char c, p;
+    int res, escape;
+
+    /* go to the end of string and count the number of escape chars */
+    for (escape = 0;; ++(*fmt)) {
+ p = *((*fmt)-1);
+ c = **fmt;
+ if (!c)
     return -1;
- if (c == '"') {
-    if (*((*fmt)-1) == '\\')
- continue;
-    else
- break;
- } else
-    continue;
+ else if (c == '\\' && p != '\\')
+    ++escape;
+ else if (c == '"' && p != '\\')
+    break;
     }
-    res = ei_x_encode_string_len(x, start, *fmt - start - 1);
+
+    /* encode the string */
+    res = ei_x_encode_string_len(x, start, *fmt - start - escape);
+    ++(*fmt); /* skip last quote */
     return res;
 }
 
@@ -197,27 +209,29 @@
 static int pquotedatom(const char** fmt, ei_x_buff* x)
 {
     const char* start = ++(*fmt); /* skip first quote */
-    char c;
-    int res;
-    
-    for (;;) {
- c = *(*fmt)++;
- if (c == 0)
+    char c, p;
+    int res, escape;
+
+    /* go to the end of atom and count the number of escape chars */
+    for (escape = 0;; ++(*fmt)) {
+ p = *((*fmt)-1);
+ c = **fmt;
+ if (!c)
     return -1;
- if (c == '\'') {
-    if (*((*fmt)-1) == '\\')
- continue;
-    else
- break;
- } else
-    continue;
-    }
-    res = ei_x_encode_atom_len(x, start, *fmt - start - 1);
+ else if (c == '\'' && p != '\\')
+    break;
+ else if (c == '\\' &&  p != '\\')
+    ++escape;
+    }
+
+    /* encode the string */
+    res = ei_x_encode_atom_len(x, start, *fmt - start - escape);
+    ++(*fmt); /* skip last quote */
     return res;
 }
 
 
- /*
+ /*
   * The format letters are:
   *   a  -  An atom
   *   s  -  A string
@@ -230,76 +244,89 @@
 static int pformat(const char** fmt, union arg** args, ei_x_buff* x)
 {
     int res = 0;
+
+    /* Return an error if there are no args (e.g. for an ei_x_parse call) */
+    if (args == NULL)
+   return -1;
+
     ++(*fmt); /* skip tilde */
-    switch (*(*fmt)++) {
+    switch (**fmt) {
     case 'a':
  res = ei_x_encode_atom(x, (*args)->s);
- (*args)++;
+ ++(*args);
  break;
     case 's':
  res = ei_x_encode_string(x, (*args)->s);
- (*args)++;
+ ++(*args);
  break;
     case 'i':
  res = ei_x_encode_long(x, (*args)->l);
- (*args)++;
+ ++(*args);
  break;
     case 'l':
  res = ei_x_encode_long(x, (*args)->l);
- (*args)++;
+ ++(*args);
  break;
     case 'u':
  res = ei_x_encode_ulong(x, (*args)->u);
- (*args)++;
+ ++(*args);
  break;
     case 'f':     /* float is expanded to double (C calling conventions) */
     case 'd':
  res = ei_x_encode_double(x, (*args)->d);
- (*args)++;
- break;
+ ++(*args);
+ break;
     default:
  res = -1;
  break;
     }
+    ++(*fmt); /* skip char after the tilde */
     return res;
 }
 
 /* encode a tuple */
 static int ptuple(const char** fmt, union arg** args, ei_x_buff* x, int size)
 {
+    const char *p = *fmt;
+    const char delimiter = **fmt;
     int res = 0;
-    const char* p = *fmt;
-    char after = *p++;
-    
-    if (after == '}') {
- *fmt = p;
+
+    if (!(*p))
+        return size;
+
+    /* ending of tuple */
+    if (delimiter == '}')
  return size;
-    }
-    while (isspace((int)*p))
- ++p;
-    switch (*p++) {
-    case '}':
- if (after == ',')
+
+    /* skip white-space chars */
+    for (++p; isspace((int)*p); ++p);
+
+    switch (delimiter) {
+    case '{': /* beginning of tuple */
+ if (*p == ',')
     res = -1;
- else
+ else if (*p == '}')
     res = size;
+ else if ((res = eiformat(&p, args, x)) != -1) {
+    ++size;
+    for (; isspace((int)*p); ++p);
+    res = ptuple(&p, args, x, size);
+ }
+ p = (*p ? p+1 : p); /* skip the '}', if any */
  break;
-    case ',':
- if (after == ',' || after == '{')
+    case ',': /* next term of tuple */
+ if (*p == ',' || *p == '}')
     res = -1;
- else
+ else if ((res = eiformat(&p, args, x)) != -1) {
+    ++size;
+    for (; isspace((int)*p); ++p);
     res = ptuple(&p, args, x, size);
+ }
  break;
-    default:
- --p;
- res = eiformat(&p, args, x);
- if (res >= 0)
-    res = ptuple(&p, args, x, size + 1);
- break;
- /*
- Variables
- */
+    default: /* wrong delimiter */
+ res = -1;
     }
+
     *fmt = p;
     return res;
 }
@@ -307,54 +334,63 @@
 /* encode a list */
 static int plist(const char** fmt, union arg** args, ei_x_buff* x, int size)
 {
+    const char *p = *fmt;
+    const char delimiter = **fmt;
     int res = 0;
-    const char* p = *fmt;
-    char after = *p++;
 
-    if (after == ']')
- --p;
-    while (isspace((int)*p))
- ++p;
-    switch (*p++) {
-    case ']':
- if (after == ',')
+    if (!*p)
+        return size;
+
+    /* end of list */
+    if (delimiter == ']') {
+ ei_x_encode_empty_list(x);
+ return size;
+    }
+
+    /* skip white-space chars */
+    for (++p; isspace((int)*p); ++p);
+
+    switch (delimiter) {
+    case '[': /* beginning of list */
+ if (*p == ',' || *p == '|')
     res = -1;
- else {
-    if (after != '|')
- ei_x_encode_empty_list(x);
-    res = size;
+ else if (*p == ']')
+    res = ei_x_encode_empty_list(x);
+ else if ((res = eiformat(&p, args, x)) != -1) {
+    ++size;
+    for (; isspace((int)*p); ++p);
+    res = plist(&p, args, x, size);
  }
+ p = (*p ? p+1 : p); /* skip the ']', if any */
  break;
-    case '|':
- if (after == '|' || after == ',')
+    case ',': /* next term of list */
+ if (*p == ',' || *p == '|' || *p == ']')
     res = -1;
- else
+ else if ((res = eiformat(&p, args, x)) != -1) {
+    ++size;
+    for (; isspace((int)*p); ++p);
     res = plist(&p, args, x, size);
+ }
  break;
-    case ',':
- if (after == '|' || after == ',')
-    res = -1;
- else
+    case '|': /* last term of list */
+        if (*p == '[') {
     res = plist(&p, args, x, size);
- break;
-    default:
- --p;
- res = eiformat(&p, args, x);
- ++size;
- if (res >= 0) {
-    if (after == '|') {
-        while (isspace((int)*p))
-    ++p;
+    res = ((!res) ? 1 : res); /* if an empty sublist ? */
+ }
+ else {
+    if ((res = eiformat(&p, args, x)) != -1) {
+ for (; isspace((int)*p); ++p);
  if (*p != ']')
     res = -1;
-    } else
- res = plist(&p, args, x, size);
- }
+ else
+    res = plist(&p, args, x, size);
+    }
+  }
  break;
- /*
- Variables
- */
+    default: /* wrong delimiter */
+ res = -1;
     }
+
     *fmt = p;
     return res;
 }
@@ -429,17 +465,21 @@
     int res;
 
     res = ei_x_encode_version(x);
-    if (res < 0) return res;
+    if (res == -1) return res;
 
     va_start(ap, fmt);
     res = read_args(fmt,ap,&args);
     saved_args = args;
     va_end(ap);
-    if (res < 0) {
- return -1;
+    if (res == -1) {
+ return res;
     }
 
     res = eiformat(&fmt, &args, x);
+    /* We must be at the end of string */
+    if (*fmt) {
+      res = -1;
+    }
     ei_free(saved_args);
 
     return res;
@@ -456,11 +496,29 @@
     res = read_args(fmt,ap,&args);
     saved_args = args;
     va_end(ap);
-    if (res < 0) {
- return -1;
+    if (res == -1) {
+ return res;
     }
+
     res = eiformat(&fmt, &args, x);
+    /* We must be at the end of string */
+    if (*fmt) {
+      res = -1;
+    }
     ei_free(saved_args);
 
     return res;
 }
+
+int ei_x_parse(ei_x_buff *x, const char* str)
+{
+  int res;
+
+  res = eiformat(&str, NULL, x);
+
+  /* We must be at the end of string */
+  if (*str) {
+    res = -1;
+  }
+  return res;
+}

/*
  gcc -I/usr/lib/erlang/lib/erl_interface-3.6.3/include \
  -L/usr/lib/erlang/lib/erl_interface-3.6.3/lib \
  test_ei.c -o test_ei_ko -lei_st
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <ei.h>

static unsigned int    success = 0;
static unsigned int    failure = 0;

#define TEST(expected, str, arg)                                    \
  {                                                                 \
    char        *result = NULL;                                     \
    int        res, index = 0;                                      \
    ei_x_buff    x;                                                 \
                                                                    \
                                                                    \
    ei_x_new(&x);                                                   \
    res = ei_x_format(&x, str, arg);                                \
    if (res != -1)                                                  \
      {                                                             \
        ei_decode_version(x.buff, &index, (int[]){0});              \
        ei_s_print_term(&result,  x.buff, &index);                  \
      }                                                             \
    else                                                            \
      result = strdup("error");                                     \
    ei_x_free(&x);                                                  \
                                                                    \
    fprintf(stdout, "%-15s",                                        \
            (!strcmp(result, expected)) ?                           \
            (success++, "[SUCCEEDED]") : (failure++, "[FAILED]"));  \
                                                                    \
    if (arg)                                                        \
      fprintf(stdout, "- Test: %-6s,%-8s", str, arg);               \
    else                                                            \
      fprintf(stdout, "- Test: %-15s", str);                        \
    fprintf(stdout, "- Expected: %-15s", expected);                 \
    fprintf(stdout, "- Result: %-15s\n", result);                   \
    free(result);                                                   \
  }


int
main(int argc, char *argv[])
{
  fprintf(stdout, "\nTUPLE:\n");
  fprintf(stdout, "%s\n","----------------------------------");
  TEST("{a, b}",         "{a,b}",        NULL);
  TEST("{a, b}",         "{a, b}",       NULL);
  TEST("{a, b}",         "{a ,b}",       NULL);
  TEST("{a, b}",         "{a , b}",      NULL);
  TEST("error",          "{a ,}b}",      NULL);
  TEST("error",          "{a ,]b}",      NULL);
  TEST("error",          "{a}b",         NULL);
  TEST("error",          "{a, {b ,}}",   NULL);
  TEST("error",          "{a, {}b}",     NULL);
  TEST("{}",             "{}",           NULL);
  TEST("{{}}",           "{{}}",         NULL);
  TEST("{{a}}",          "{{a}}",        NULL);
  TEST("{{a}, {b}}",     "{{a},{b}}",    NULL);
  TEST("{{a, b}}",       "{{a,b}}",      NULL);

  fprintf(stdout, "\nLIST:\n");
  fprintf(stdout, "%s\n","----------------------------------");
  TEST("error",          "[,]",          NULL);
  TEST("error",          "[ ,]",         NULL);
  TEST("error",          "[, ]",         NULL);
  TEST("error",          "[ , ]",        NULL);
  TEST("error",          "[|]",          NULL);
  TEST("error",          "[ |]",         NULL);
  TEST("error",          "[| ]",         NULL);
  TEST("error",          "[ | ]",        NULL);
  TEST("error",          "[a|]",         NULL);
  TEST("error",          "[,a]",         NULL);
  TEST("error",          "[|a]",         NULL);
  TEST("[a]",            "[a|[]]",       NULL);
  TEST("[[]]",           "[[]|[]]",      NULL);
  TEST("[[a]]",          "[[a]]",        NULL);
  TEST("[[a]]",          "[[a]|[]]",     NULL);
  TEST("[[a], b]",       "[[a]|[b]]",    NULL);
  TEST("[[a], [b]]",     "[[a] ,[b]]",   NULL);
  TEST("[a, b]",         "[a ,b]",       NULL);
  TEST("error",          "[a]b",         NULL);
  TEST("[a | b]",        "[a|b]",        NULL);
  TEST("[[a | b]]",      "[[a|b]]",      NULL);
  TEST("[[a, b]]",       "[[a|[b]]]",    NULL);
  TEST("[[a, b]]",       "[[a,b]]",      NULL);
  TEST("[a, b, c]",      "[a,b|[c]]",    NULL);
  TEST("[a, b | c]",     "[a,b|c]",      NULL);
  TEST("error",          "[a|[b]|[c]]",  NULL);
  TEST("error",          "[a|b|c]",      NULL);



  fprintf(stdout, "\nATOM:\n");
  fprintf(stdout, "%s\n","----------------------------------");
  TEST("error",          "a'any'",       NULL);
  TEST("error",          "a{any}",       NULL);
  TEST("error",          "a\\1",         NULL);
  TEST("a1",             "'a\\1'",       NULL);

  fprintf(stdout, "\nSTRING:\n");
  fprintf(stdout, "%s\n","----------------------------------");
  TEST("error",          "\"str\"any",   NULL);
  TEST("error",          "\"str\"{any}", NULL);
  TEST("\"str1\"",       "\"str\\1\"",   NULL);

  fprintf(stdout, "\nDIGIT:\n");
  fprintf(stdout, "%s\n","----------------------------------");
  TEST("-1",             "-1",           NULL);
  TEST("1",              "+1",           NULL);
  TEST("error",          "1any",         NULL);
  TEST("-1.000000",      "-1.0",         NULL);
  TEST("1.000000",       "+1.0",         NULL);
  TEST("error",          "1.0any",       NULL);
  TEST("100.000000",     "1.0e2",        NULL);

  fprintf(stdout, "\nDIGIT HEXA EXTENSION:\n");
  fprintf(stdout, "%s\n","----------------------------------");
  TEST("error",          "0x",           NULL);
  TEST("10",             "+0xa",         NULL);
  TEST("-10.500000",     "-0Xa.8",       NULL);
  TEST("21.000000",      "0xa.8p1",      NULL);
  TEST("42.000000",      "0xa.8P2",      NULL);

  fprintf(stdout, "\nVARG:\n");
  fprintf(stdout, "%s\n","----------------------------------");
  TEST("error",          "~aany",        "toto");
  TEST("atoma",          "~a",           "toto\\a");
  TEST("'atom\\a'",      "~a",           "toto\\\\a");
  TEST("\"stra\"",       "~s",           "str\\a");
  TEST("\"str\\a\"",     "~s",           "str\\\\a");

  fprintf(stdout, "\n ==> SUCCESS: %-5d FAILURE: %d\n", success, failure);

  return 0;
}


signature.asc (268 bytes) Download Attachment

Re: Some bugfixes in ei_x_format in R13B02-1

by Björn-Egil Dahlberg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Cristopher,

Thank your for pointing out these issues and supplying a patch for it.
I will have a look at it as soon as I can.

Regards,
Björn-Egil
Erlang/OTP

christopher faulet wrote:

> Hi all,
>
> the attached patch fixes some bugs in functions that build terms from
> strings, called by ei_x_format and ei_x_format_wo_ver. It improves the
> parsing of lists, tuples, strings, atoms and digits. The file test_ei.c
> in attachement shows examples that ei_x_format doesn't parse correctly.
>
> In addition, I added support of hexadecimal representations of digit.
>
> This patch also fixes a bug in erl_call. When we use the option "-a 'Mod
> Fun Args'", the module and function are extracted and the remainings are
> passed to ei_x_format_wo_ver in order to build arguments before calling
> the function ei_rpc. The problem is that this function tries to replace
> all ~a,~s,~i... But in this context, it's a mistake. To avoid this
> behaviour, I added a new function, ei_x_parse, that transforms a string
> in erlang term without any replacement. Here is an example:
>
>   * the following command returns an error instead of ["test"]:
>       erl_call -sname bug_ei -s -a 'io_lib format ["~p", [test]]'
>
> I only tested this patch on linux but I hope that it works on other OS.
>
> Best regards,
>



________________________________________________________________
erlang-patches mailing list. See http://www.erlang.org/faq.html
erlang-patches (at) erlang.org