Browse Source

bug: "format" does not check size of format item (such as "%00000...00000d").

Roberto Ierusalimschy 26 years ago
parent
commit
b94110a68f
2 changed files with 36 additions and 39 deletions
  1. 3 0
      bugs
  2. 33 39
      lstrlib.c

+ 3 - 0
bugs

@@ -58,3 +58,6 @@ Fri Dec 18 11:22:55 EDT 1998
 >> "tonumber" goes crazy with negative numbers in other bases (not 10),
 because "strtol" returns long, not unsigned long.
 
+** lstrlib.c
+Mon Jan  4 10:41:40 EDT 1999
+>> "format" does not check size of format item (such as "%00000...00000d").

+ 33 - 39
lstrlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstrlib.c,v 1.21 1998/12/01 18:41:25 roberto Exp roberto $
+** $Id: lstrlib.c,v 1.22 1998/12/28 13:44:54 roberto Exp $
 ** Standard library for strings and pattern-matching
 ** See Copyright Notice in lua.h
 */
@@ -67,8 +67,7 @@ static void str_lower (void) {
 }
 
 
-static void str_upper (void)
-{
+static void str_upper (void) {
   long l;
   int i;
   char *s = luaL_check_lstr(1, &l);
@@ -90,8 +89,7 @@ static void str_rep (void)
 }
 
 
-static void str_byte (void)
-{
+static void str_byte (void) {
   long l;
   char *s = luaL_check_lstr(1, &l);
   long pos = posrelat(luaL_opt_long(2, 1), l);
@@ -99,6 +97,7 @@ static void str_byte (void)
   lua_pushnumber((unsigned char)s[pos-1]);
 }
 
+
 static void str_char (void) {
   int i = 0;
   luaL_resetbuffer();
@@ -111,8 +110,9 @@ static void str_char (void) {
 }
 
 
+
 /*
-** =======================================================
+** {======================================================
 ** PATTERN MATCHING
 ** =======================================================
 */
@@ -120,8 +120,8 @@ static void str_char (void) {
 #define MAX_CAPT 9
 
 struct Capture {
-  int level;  /* total number of captures (finished or unfinished) */
   char *src_end;  /* end ('\0') of source string */
+  int level;  /* total number of captures (finished or unfinished) */
   struct {
     char *init;
     int len;  /* -1 signals unfinished capture */
@@ -133,8 +133,7 @@ struct Capture {
 #define SPECIALS  "^$*?.([%-"
 
 
-static void push_captures (struct Capture *cap)
-{
+static void push_captures (struct Capture *cap) {
   int i;
   for (i=0; i<cap->level; i++) {
     int l = cap->capture[i].len;
@@ -144,8 +143,7 @@ static void push_captures (struct Capture *cap)
 }
 
 
-static int check_cap (int l, struct Capture *cap)
-{
+static int check_cap (int l, struct Capture *cap) {
   l -= '1';
   if (!(0 <= l && l < cap->level && cap->capture[l].len != -1))
     lua_error("invalid capture index");
@@ -153,8 +151,7 @@ static int check_cap (int l, struct Capture *cap)
 }
 
 
-static int capture_to_close (struct Capture *cap)
-{
+static int capture_to_close (struct Capture *cap) {
   int level = cap->level;
   for (level--; level>=0; level--)
     if (cap->capture[level].len == -1) return level;
@@ -163,14 +160,12 @@ static int capture_to_close (struct Capture *cap)
 }
 
 
-static char *bracket_end (char *p)
-{
+static char *bracket_end (char *p) {
   return (*p == 0) ? NULL : strchr((*p=='^') ? p+2 : p+1, ']');
 }
 
 
-static int matchclass (int c, int cl)
-{
+static int matchclass (int c, int cl) {
   int res;
   switch (tolower(cl)) {
     case 'a' : res = isalpha(c); break;
@@ -181,15 +176,15 @@ static int matchclass (int c, int cl)
     case 's' : res = isspace(c); break;
     case 'u' : res = isupper(c); break;
     case 'w' : res = isalnum(c); break;
+    case 'x' : res = isxdigit(c); break;
     case 'z' : res = (c == '\0'); break;
     default: return (cl == c);
   }
-  return (islower((unsigned char)cl) ? res : !res);
+  return (islower(cl) ? res : !res);
 }
 
 
-int luaI_singlematch (int c, char *p, char **ep)
-{
+int luaI_singlematch (int c, char *p, char **ep) {
   switch (*p) {
     case '.':  /* matches any char */
       *ep = p+1;
@@ -228,8 +223,7 @@ int luaI_singlematch (int c, char *p, char **ep)
 }
 
 
-static char *matchbalance (char *s, int b, int e, struct Capture *cap)
-{
+static char *matchbalance (char *s, int b, int e, struct Capture *cap) {
   if (*s != b) return NULL;
   else {
     int cont = 1;
@@ -244,8 +238,7 @@ static char *matchbalance (char *s, int b, int e, struct Capture *cap)
 }
 
 
-static char *matchitem (char *s, char *p, struct Capture *cap, char **ep)
-{
+static char *matchitem (char *s, char *p, struct Capture *cap, char **ep) {
   if (*p == ESC) {
     p++;
     if (isdigit((unsigned char)*p)) {  /* capture */
@@ -265,14 +258,13 @@ static char *matchitem (char *s, char *p, struct Capture *cap, char **ep)
     }
     else p--;  /* and go through */
   }
-  /* "luaI_singlematch" sets "ep" (so must be called even when *s == 0) */
+  /* "luaI_singlematch" sets "ep" (so must be called even at the end of "s" */
   return (luaI_singlematch((unsigned char)*s, p, ep) && s<cap->src_end) ?
                     s+1 : NULL;
 }
 
 
-static char *match (char *s, char *p, struct Capture *cap)
-{
+static char *match (char *s, char *p, struct Capture *cap) {
   init: /* using goto's to optimize tail recursion */
   switch (*p) {
     case '(': {  /* start capture */
@@ -298,7 +290,7 @@ static char *match (char *s, char *p, struct Capture *cap)
         return s;
       /* else go through */
     default: {  /* it is a pattern item */
-      char *ep;  /* get what is next */
+      char *ep;  /* will point to what is next */
       char *s1 = matchitem(s, p, cap, &ep);
       switch (*ep) {
         case '*': {  /* repetition */
@@ -333,8 +325,7 @@ static char *match (char *s, char *p, struct Capture *cap)
 }
 
 
-static void str_find (void)
-{
+static void str_find (void) {
   long l;
   char *s = luaL_check_lstr(1, &l);
   char *p = luaL_check_string(2);
@@ -369,8 +360,7 @@ static void str_find (void)
 }
 
 
-static void add_s (lua_Object newp, struct Capture *cap)
-{
+static void add_s (lua_Object newp, struct Capture *cap) {
   if (lua_isstring(newp)) {
     char *news = lua_getstring(newp);
     int l = lua_strlen(newp);
@@ -412,8 +402,7 @@ static void add_s (lua_Object newp, struct Capture *cap)
 }
 
 
-static void str_gsub (void)
-{
+static void str_gsub (void) {
   long srcl;
   char *src = luaL_check_lstr(1, &srcl);
   char *p = luaL_check_string(2);
@@ -446,6 +435,8 @@ static void str_gsub (void)
   lua_pushnumber(n);  /* number of substitutions */
 }
 
+/* }====================================================== */
+
 
 static void luaI_addquoted (int arg) {
   long l;
@@ -465,10 +456,10 @@ static void luaI_addquoted (int arg) {
   luaL_addchar('"');
 }
 
-#define MAX_FORMAT 200
+/* maximum size of each format specification (such as '%-099.99d') */
+#define MAX_FORMAT 20
 
-static void str_format (void)
-{
+static void str_format (void) {
   int arg = 1;
   char *strfrmt = luaL_check_string(arg);
   struct Capture cap;
@@ -491,11 +482,14 @@ static void str_format (void)
       }
       arg++;
       strfrmt = match(initf, "[-+ #0]*(%d*)%.?(%d*)", &cap);
-      if (cap.capture[0].len > 2 || cap.capture[1].len > 2)  /* < 100? */
+      if (cap.capture[0].len > 2 || cap.capture[1].len > 2 ||  /* < 100? */
+          strfrmt-initf > MAX_FORMAT-2)
         lua_error("invalid format (width or precision too long)");
       strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */
       form[strfrmt-initf+2] = 0;
-      buff = luaL_openspace(1000);  /* to store the formatted value */
+      /* to store the formatted value
+         (450 > size of format('%99.99f', -1e308) */
+      buff = luaL_openspace(450);
       switch (*strfrmt++) {
         case 'q':
           luaI_addquoted(arg);