On Mon, 19 Jan 2015 16:28:46 -0600
"William A. Rowe Jr." <[email protected]> wrote:

> On Sun, 18 Jan 2015 23:00:10 -0500
> Eric Covener <[email protected]> wrote:
> 
> > On Thu, Oct 30, 2014 at 4:34 AM,  <[email protected]> wrote:
> > >
> > > +            /* core_dir_config is Directory*, but the requested
> > > file is
> > > +             * not a directory, so although the regexp could
> > > match,
> > > +             * we skip it. */
> > > +            if (entry_core->d_is_directory &&
> > > r->finfo.filetype != APR_DIR) {
> > > +                continue;
> > > +            }
> > > +
> > >              if (ap_regexec(entry_core->r, r->filename, nmatch,
> > > pmatch, 0)) { continue;
> > >              }
> > 
> > I think this is broken.
> 
> You are correct, I don't think it means what the author thought this
> code means.

Indeed, it was nonsense.  The fix begins with some code similar to
[attached] but there are a number of shortcuts in the code that would
need to be accounted for by expanding the dir_len at the appropriate
time.  The patch is also insufficient in that the r->filename buffer
needs to be at least one extra byte to compensate for the 'maybe a
trailing slash, maybe not' on a final directory component in a file
name.

That said, I'm putting this out there to get folks thinking, I can't
spend much more time on it myself, today.

Cheers,

Bill

Index: request.c
===================================================================
--- request.c	(revision 1653666)
+++ request.c	(working copy)
@@ -566,6 +566,8 @@
     walk_cache_t *cache;
     char *entry_dir;
     apr_status_t rv;
+    apr_size_t dir_len;
+    char save_ch;
     int cached;
 
     /* XXX: Better (faster) tests needed!!!
@@ -1169,8 +1170,11 @@
                 return r->status = HTTP_FORBIDDEN;
             }
 
+            /* directory-path string length here for DirectoryMatch */
+            dir_len = strlen(r->filename);
+
             ++seg;
-        } while (thisinfo.filetype == APR_DIR);
+        } while (1);  /* (thisinfo.filetype == APR_DIR) per above logic */
 
         /* If we have _not_ optimized, this is the time to recover
          * the final stat result.
@@ -1191,10 +1195,17 @@
             }
         }
 
-        /*
-         * Now we'll deal with the regexes, note we pick up sec_idx
-         * where we left off (we gave up after we hit entry_core->r)
+        /* Now we'll deal with the DirectoryMatch regex's
+         *
+         * First, shorten r->filename to dir_len, plus the trailing
+         * slash when present
          */
+        save_ch = r->filename[dir_len + 1];
+        r->filename[dir_len + 1] = '\0';
+
+        /* Note we pick up sec_idx where we left off
+         * (we gave up above once we hit entry_core->r)
+         */
         for (; sec_idx < num_sec; ++sec_idx) {
 
             int nmatch = 0;
@@ -1216,6 +1227,8 @@
                 pmatch = apr_palloc(rxpool, nmatch*sizeof(ap_regmatch_t));
             }
 
+            /* r->filename here has been truncated to the directory path
+             * component -including- trailing slash
             if (ap_regexec(entry_core->r, r->filename, nmatch, pmatch, 0)) {
                 continue;
             }
@@ -1268,6 +1281,8 @@
             last_walk->matched = sec_ent[sec_idx];
             last_walk->merged = now_merged;
         }
+        /* Restore filename  now that we have processed DirectoryMatch'es */
+        r->filename[dir_len + 1] = save_ch;
 
         if (rxpool) {
             apr_pool_destroy(rxpool);

Reply via email to