The SWI-Prolog GIT repositories

FIXED: Possible buffer overrun in patch canonisation code.
authorJan Wielemaker <J.Wielemaker@cs.vu.nl>
Sun, 16 Dec 2012 17:13:17 +0000 (18:13 +0100)
committerJan Wielemaker <J.Wielemaker@cs.vu.nl>
Sun, 16 Dec 2012 20:59:37 +0000 (21:59 +0100)
Pushes pointers on an automatic array without checking for overflow.
Can be used for DoS attacks.  Will be extremely hard to make it execute
arbitrary code.

src/os/pl-buffer.h
src/os/pl-os.c

index 1e6262a..ba7e63f 100644 (file)
@@ -101,6 +101,8 @@ f__allocFromBuffer(Buffer b, size_t bytes)
                                  sizeof((b)->static_buffer))
 #define emptyBuffer(b)           ((b)->top  = (b)->base)
 #define isEmptyBuffer(b)         ((b)->top == (b)->base)
+#define popBuffer(b,type) \
+       ((b)->top -= sizeof(type), *(type*)(b)->top)
 
 #define discardBuffer(b) \
        do \
index 54affbf..c1f4c77 100644 (file)
@@ -1057,8 +1057,7 @@ cleanupExpand(void)
 char *
 canoniseFileName(char *path)
 { char *out = path, *in = path, *start = path;
-  char *osave[100];
-  int  osavep = 0;
+  tmp_buffer saveb;
 
 #ifdef O_HASDRIVES                     /* C: */
   if ( in[1] == ':' && isLetter(in[0]) )
@@ -1097,7 +1096,8 @@ canoniseFileName(char *path)
     in += 2;
   if ( in[0] == '/' )
     *out++ = '/';
-  osave[osavep++] = out;
+  initBuffer(&saveb);
+  addBuffer(&saveb, out, char*);
 
   while(*in)
   { if (*in == '/')
@@ -1113,15 +1113,15 @@ canoniseFileName(char *path)
          }
          if ( in[2] == EOS )           /* delete trailing /. */
          { *out = EOS;
-           return path;
+           goto out;
          }
          if ( in[2] == '.' && (in[3] == '/' || in[3] == EOS) )
-         { if ( osavep > 0 )           /* delete /foo/../ */
-           { out = osave[--osavep];
+         { if ( !isEmptyBuffer(&saveb) )               /* delete /foo/../ */
+           { out = popBuffer(&saveb, char*);
              in += 3;
              if ( in[0] == EOS && out > start+1 )
              { out[-1] = EOS;          /* delete trailing / */
-               return path;
+               goto out;
              }
              goto again;
            } else if ( start[0] == '/' && out == start+1 )
@@ -1135,12 +1135,15 @@ canoniseFileName(char *path)
        in++;
       if ( out > path && out[-1] != '/' )
        *out++ = '/';
-      osave[osavep++] = out;
+      addBuffer(&saveb, out, char*);
     } else
       *out++ = *in++;
   }
   *out++ = *in++;
 
+out:
+  discardBuffer(&saveb);
+
   return path;
 }
 

Further information about the SWI-Prolog GIT repositories