You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by mt...@apache.org on 2010/05/14 12:20:41 UTC

svn commit: r944192 - in /trafficserver/traffic/trunk/libinktomi++: ink_file.cc ink_file.h

Author: mturk
Date: Fri May 14 10:20:41 2010
New Revision: 944192

URL: http://svn.apache.org/viewvc?rev=944192&view=rev
Log:
Port APR's apr_filepath_merge. Returned errors need to be reviewed. However in most cases we'll be only interested in != 0

Modified:
    trafficserver/traffic/trunk/libinktomi++/ink_file.cc
    trafficserver/traffic/trunk/libinktomi++/ink_file.h

Modified: trafficserver/traffic/trunk/libinktomi++/ink_file.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/libinktomi%2B%2B/ink_file.cc?rev=944192&r1=944191&r2=944192&view=diff
==============================================================================
--- trafficserver/traffic/trunk/libinktomi++/ink_file.cc (original)
+++ trafficserver/traffic/trunk/libinktomi++/ink_file.cc Fri May 14 10:20:41 2010
@@ -312,3 +312,199 @@ ink_file_fd_writestring(int fd, const ch
 
   return i;                     /* return chars written */
 }                               /* End ink_file_fd_writestring */
+
+int
+ink_filepath_merge(char *path, int pathsz, const char *rootpath,
+                   const char *addpath, int flags)
+{
+  size_t rootlen; // is the length of the src rootpath
+  size_t maxlen;  // maximum total path length
+  size_t keptlen; // is the length of the retained rootpath
+  size_t pathlen; // is the length of the result path
+  size_t seglen;  // is the end of the current segment
+  char curdir[PATH_MAX];
+
+  /* Treat null as an empty path.
+  */
+  if (!addpath)
+    addpath = "";
+
+  if (addpath[0] == '/') {
+    // If addpath is rooted, then rootpath is unused.
+    // Ths violates any INK_FILEPATH_SECUREROOTTEST and
+    // INK_FILEPATH_NOTABSOLUTE flags specified.
+    //
+    if (flags & INK_FILEPATH_SECUREROOTTEST)
+      return EACCES; // APR_EABOVEROOT;
+    if (flags & INK_FILEPATH_NOTABSOLUTE)
+      return EISDIR; // APR_EABSOLUTE;
+
+    // If INK_FILEPATH_NOTABOVEROOT wasn't specified,
+    // we won't test the root again, it's ignored.
+    // Waste no CPU retrieving the working path.
+    //
+    if (!rootpath && !(flags & INK_FILEPATH_NOTABOVEROOT))
+      rootpath = "";
+  }
+  else {
+    // If INK_FILEPATH_NOTABSOLUTE is specified, the caller
+    // requires a relative result.  If the rootpath is
+    // ommitted, we do not retrieve the working path,
+    // if rootpath was supplied as absolute then fail.
+    //
+    if (flags & INK_FILEPATH_NOTABSOLUTE) {
+      if (!rootpath)
+        rootpath = "";
+      else if (rootpath[0] == '/')
+        return EISDIR; //APR_EABSOLUTE;
+    }
+  }
+  if (!rootpath) {
+    // Start with the current working path.  This is bass akwards,
+    // but required since the compiler (at least vc) doesn't like
+    // passing the address of a char const* for a char** arg.
+    //
+    if (!getcwd(curdir, sizeof(curdir))) {
+      return errno;
+    }
+    rootpath = curdir;
+  }
+  rootlen = strlen(rootpath);
+  maxlen = rootlen + strlen(addpath) + 4; // 4 for slashes at start, after
+                                          // root, and at end, plus trailing
+                                          // null
+  if (maxlen > (size_t)pathsz) {
+    return E2BIG; //APR_ENAMETOOLONG;
+  }
+  if (addpath[0] == '/') {
+    // Ignore the given root path, strip off leading
+    // '/'s to a single leading '/' from the addpath,
+    // and leave addpath at the first non-'/' character.
+    //
+    keptlen = 0;
+    while (addpath[0] == '/')
+      ++addpath;
+    path[0] = '/';
+    pathlen = 1;
+  }
+  else {
+    // If both paths are relative, fail early
+    //
+    if (rootpath[0] != '/' && (flags & INK_FILEPATH_NOTRELATIVE))
+      return EBADF; //APR_ERELATIVE;
+
+    // Base the result path on the rootpath
+    //
+    keptlen = rootlen;
+    memcpy(path, rootpath, rootlen);
+
+    // Always '/' terminate the given root path
+    //
+    if (keptlen && path[keptlen - 1] != '/') {
+      path[keptlen++] = '/';
+    }
+    pathlen = keptlen;
+  }
+
+  while (*addpath) {
+    // Parse each segment, find the closing '/'
+    //
+    const char *next = addpath;
+    while (*next && (*next != '/')) {
+      ++next;
+    }
+    seglen = next - addpath;
+
+    if (seglen == 0 || (seglen == 1 && addpath[0] == '.')) {
+      // noop segment (/ or ./) so skip it
+      //
+    }
+    else if (seglen == 2 && addpath[0] == '.' && addpath[1] == '.') {
+      // backpath (../)
+      if (pathlen == 1 && path[0] == '/') {
+        // Attempt to move above root.  Always die if the
+        // INK_FILEPATH_SECUREROOTTEST flag is specified.
+        //
+        if (flags & INK_FILEPATH_SECUREROOTTEST) {
+          return EACCES; //APR_EABOVEROOT;
+        }
+
+        // Otherwise this is simply a noop, above root is root.
+        // Flag that rootpath was entirely replaced.
+        //
+        keptlen = 0;
+      }
+      else if (pathlen == 0
+               || (pathlen == 3
+               && !memcmp(path + pathlen - 3, "../", 3))
+               || (pathlen  > 3
+               && !memcmp(path + pathlen - 4, "/../", 4))) {
+        // Path is already backpathed or empty, if the
+        // INK_FILEPATH_SECUREROOTTEST.was given die now.
+        //
+        if (flags & INK_FILEPATH_SECUREROOTTEST) {
+          return EACCES; //APR_EABOVEROOT;
+        }
+
+        // Otherwise append another backpath, including
+        // trailing slash if present.
+        //
+        memcpy(path + pathlen, "../", *next ? 3 : 2);
+        pathlen += *next ? 3 : 2;
+      }
+      else {
+        // otherwise crop the prior segment
+        //
+        do {
+            --pathlen;
+        } while (pathlen && path[pathlen - 1] != '/');
+      }
+
+      // Now test if we are above where we started and back up
+      // the keptlen offset to reflect the added/altered path.
+      //
+      if (pathlen < keptlen) {
+        if (flags & INK_FILEPATH_SECUREROOTTEST) {
+          return EACCES; //APR_EABOVEROOT;
+        }
+        keptlen = pathlen;
+      }
+    }
+    else {
+        // An actual segment, append it to the destination path
+        //
+      if (*next) {
+        seglen++;
+      }
+      memcpy(path + pathlen, addpath, seglen);
+      pathlen += seglen;
+    }
+
+    // Skip over trailing slash to the next segment
+    //
+    if (*next) {
+      ++next;
+    }
+
+    addpath = next;
+  }
+  path[pathlen] = '\0';
+
+  // keptlen will be the rootlen unless the addpath contained
+  // backpath elements.  If so, and INK_FILEPATH_NOTABOVEROOT
+  // is specified (INK_FILEPATH_SECUREROOTTEST was caught above),
+  // compare the original root to assure the result path is
+  // still within given root path.
+  //
+  if ((flags & INK_FILEPATH_NOTABOVEROOT) && keptlen < rootlen) {
+    if (strncmp(rootpath, path, rootlen)) {
+      return EACCES; //APR_EABOVEROOT;
+    }
+    if (rootpath[rootlen - 1] != '/'
+        && path[rootlen] && path[rootlen] != '/') {
+      return EACCES; //APR_EABOVEROOT;
+    }
+  }
+
+  return 0;
+}

Modified: trafficserver/traffic/trunk/libinktomi++/ink_file.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/libinktomi%2B%2B/ink_file.h?rev=944192&r1=944191&r2=944192&view=diff
==============================================================================
--- trafficserver/traffic/trunk/libinktomi++/ink_file.h (original)
+++ trafficserver/traffic/trunk/libinktomi++/ink_file.h Fri May 14 10:20:41 2010
@@ -43,6 +43,28 @@
 
 #include <dirent.h>
 
+// Cause ink_filepath_merge to fail if addpath is above rootpath
+//
+#define INK_FILEPATH_NOTABOVEROOT   0x01
+// internal: Only meaningful with INK_FILEPATH_NOTABOVEROOT
+#define INK_FILEPATH_SECUREROOTTEST 0x02
+// Cause ink_filepath_merge to fail if addpath is above rootpath,
+// even given a rootpath /foo/bar and an addpath ../bar/bash
+//
+#define INK_FILEPATH_SECUREROOT     0x03
+// Fail ink_filepath_merge if the merged path is relative
+#define INK_FILEPATH_NOTRELATIVE    0x04
+// Fail ink_filepath_merge if the merged path is absolute
+#define INK_FILEPATH_NOTABSOLUTE    0x08
+// Return the file system's native path format (e.g. path delimiters
+// of ':' on MacOS9, '\' on Win32, etc.)
+#define INK_FILEPATH_NATIVE         0x10
+// Resolve the true case of existing directories and file elements
+// of addpath, (resolving any aliases on Win32) and append a proper
+// trailing slash if a directory
+//
+#define INK_FILEPATH_TRUENAME       0x20
+
 int ink_access_extension(char *base, char *ext, int amode);
 int ink_readdir_r(DIR * dirp, struct dirent *entry, struct dirent **pentry);
 DIR *ink_opendir(const char *path);
@@ -70,5 +92,7 @@ int ink_file_trylock(int fd, int type);
 
 int ink_file_fd_readline(int fd, int bufsz, char *buf);
 int ink_file_fd_writestring(int fd, const char *buf);
+int ink_filepath_merge(char *buf, int bufsz, const char *rootpath,
+                       const char *addpath, int flags);
 
 #endif // _ink_file_h_