You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by генерал Пурпоз <kb...@gmail.com> on 2007/02/04 00:56:30 UTC

Porting APR to QNX4: file path management.

Hello William,

Wednesday, January 31, 2007, 7:46:57 AM, you wrote:

> We presume rootpath **was** normalized previously. We presume
> addpath is untrusted user data. Now come up with a path that isn't
> insecure per the flags the developer passed.
I did my best to not ruin your code.
This is what I came up with, it passes all the tests I could think of:

--- filepath.c.orig     2006-09-21 11:43:54.000000000 +0400
+++ filepath.c  2007-02-04 02:28:26.000000000 +0300
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+#ifdef __QNX__
+#include <string.h>
+#include <sys/prfx.h>
+#endif
 #include "apr.h"
 #include "apr_private.h"
 #include "apr_arch_file_io.h"
@@ -66,11 +70,36 @@
                                             apr_int32_t flags,
                                             apr_pool_t *p)
 {
+       int prefix_present = 0; /* a "//number/" is in inpath */
+
     if (**inpath == '/') {
+#ifdef __QNX__
+/* Are we presented with a wellformed QNX4 full path: "//number/foo" ?   */
+/* A "/8/foo"-like string does NOT qualify as one. Such a string is just */
+/* an abbreviation of a "//number/8/foo"-like on-the-current-node path.  */
+               if(    strlen(*inpath)   >= 2   && \
+                                   *(*inpath+1) == '/' && \
+                       isdigit(*(*inpath+2))          ) prefix_present = 1;
+#else
         *rootpath = apr_pstrdup(p, "/");
+#endif
         do {
             ++(*inpath);
         } while (**inpath == '/');
+#ifdef __QNX__
+               if( !prefix_present ) /* construct the rootpath anew */
+                       *rootpath = apr_pstrdup(p, qnx_prefix_getroot() );
+               else { /* inpath has had a valid prefix, move in to rootpath */
+                       *rootpath = apr_pstrdup(p, "//");
+                       while ( isdigit(**inpath) ) {
+                               strncat( *rootpath, *inpath, 1 );
+                               ++(*inpath);
+            } /* move all the decimal digits representing the node ID */
+               }
+               strncat( *rootpath, "/", 1); /* now complete rootpath properly */
+               if( 0 != strlen(*inpath) && 1 == prefix_present )
+                       ++(*inpath); /* deal with the post-node-number slash */
+#endif
 
         return APR_SUCCESS;
     }
@@ -91,6 +120,9 @@
     apr_size_t pathlen; /* is the length of the result path */
     apr_size_t seglen;  /* is the end of the current segment */
     apr_status_t rv;
+#ifdef __QNX__
+       int prefix_present = 0; /* a "//number/" is in addpath */
+#endif
 
     /* Treat null as an empty path.
      */
@@ -99,7 +131,7 @@
 
     if (addpath[0] == '/') {
         /* If addpath is rooted, then rootpath is unused.
-         * Ths violates any APR_FILEPATH_SECUREROOTTEST and
+         * This violates any APR_FILEPATH_SECUREROOTTEST and
          * APR_FILEPATH_NOTABSOLUTE flags specified.
          */
         if (flags & APR_FILEPATH_SECUREROOTTEST)
@@ -160,11 +192,41 @@
          * '/'s to a single leading '/' from the addpath,
          * and leave addpath at the first non-'/' character.
          */
+#ifdef __QNX__
+        keptlen = 0;
+
+/* As with apr_filepath_root() we want to know if we deal with a wellformed */
+/* QNX4-style full path: "//number/foo" ?                                   */
+
+               if(  strlen(addpath)   >= 2   && \
+                                   addpath[1] == '/' && \
+                       isdigit(addpath[2])          ) prefix_present = 1;
+        while ( addpath[0] == '/' )
+                       ++addpath; /* do your usual slash-stripping at the front end */
+
+               if( !prefix_present ) {
+                       strncpy( path,qnx_prefix_getroot(),strlen(qnx_prefix_getroot()) );
+                       pathlen = strlen( path );
+               } else {
+                       strncpy( path, "//", 2 );
+                       pathlen = strlen(path);
+                       while ( isdigit( addpath[0] ) ) {
+                               path[pathlen] = addpath[0];
+                               ++pathlen;
+                               ++addpath;
+            }
+               }
+               path[pathlen] = '/';
+               ++pathlen;
+               if( 0 != strlen(addpath) && 1 == prefix_present )
+                       ++addpath; /* deal with the post-node-number slash */
+#else
         keptlen = 0;
         while (addpath[0] == '/')
             ++addpath;
         path[0] = '/';
         pathlen = 1;
+#endif
     }
     else {
         /* If both paths are relative, fail early



Please comment if it is a complete lunacy... :)

By the way, on my toolchain the "ABTS_STR_EQUAL(tc, "", path);"
construct needs this hacking:
"ABTS_STR_EQUAL(tc, "\0", path);"
Unless I do this the check fails no matter that the "path" string is
empty. The report complains it extected <some_string> but saw <>.
"some_string" most often is shown as "//2/". I wonder why...

-- 
Best regards,
 Anthony                      mailto:kb2wjw@gmail.com