lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi,

I had a problem with the quoted string format producing strings that
were not legal UTF-8 because it was not escaping non-ascii characters,
and then once I fixed that I wasn't able to read the strings back in
to a C program because C uses octal escapes and Lua uses decimal.

This patch ensures all control and non-ascii characters are escaped,
and uses the hexadecimal escape syntax instead of decimal to ensure
compatibility between Lua and C.

Technically it is still not safe to pass the strings as literals
directly into C because in C the hexadecimal production is not
automatically terminated at two characters but I figured this was
outside of the scope of the quoted string format specifier.  I solve
this instead by using `:gsub([[%f[\]\x%x%x]],'%0""')` to terminate the
hexadecimal escapes (triggering C's string literal concatenation
behaviour) at the point of export.

Regards,

Duane.
@@ -912,20 +912,26 @@ static int lua_number2strx (lua_State *L, char *buff, int sz,
 static void addquoted (luaL_Buffer *b, const char *s, size_t len) {
   luaL_addchar(b, '"');
   while (len--) {
-    if (*s == '"' || *s == '\\' || *s == '\n') {
-      luaL_addchar(b, '\\');
-      luaL_addchar(b, *s);
-    }
-    else if (iscntrl(uchar(*s))) {
-      char buff[10];
-      if (!isdigit(uchar(*(s+1))))
-        l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s));
-      else
-        l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s));
+    if (iscntrl(uchar(*s)) || !isascii(uchar(*s))) {
+      char buff[5] = "\\";
+      switch (*s) {
+        case '\a': buff[1] = 'a'; break;
+        case '\b': buff[1] = 'b'; break;
+        case '\f': buff[1] = 'f'; break;
+        case '\n': buff[1] = 'n'; break;
+        case '\r': buff[1] = 'r'; break;
+        case '\t': buff[1] = 't'; break;
+        case '\v': buff[1] = 'v'; break;
+        case '\0': if (!isdigit(uchar(*(s+1)))) { buff[1] = '0'; break; }
+        default: l_sprintf(buff+1, sizeof(buff)-1, "x%02x", (int)uchar(*s));
+      }
       luaL_addstring(b, buff);
     }
-    else
+    else {
+      if (*s == '"' || *s == '\\')
+        luaL_addchar(b, '\\');
       luaL_addchar(b, *s);
+    }
     s++;
   }
   luaL_addchar(b, '"');