On 1/17/22 5:10 PM, minf...@apache.org wrote:
> Author: minfrin
> Date: Mon Jan 17 16:10:51 2022
> New Revision: 1897156
> 
> URL: http://svn.apache.org/viewvc?rev=1897156&view=rev
> Log:
> core: Allow an optional expression to be specified for an effective
> path in the DirectoryMatch and LocationMatch directives. This allows
> modules like mod_dav to map URLs to URL spaces or to directories on
> the filesystem.
> 
> Modified:
>     httpd/httpd/trunk/CHANGES
>     httpd/httpd/trunk/docs/log-message-tags/next-number
>     httpd/httpd/trunk/docs/manual/mod/core.xml
>     httpd/httpd/trunk/modules/dav/main/mod_dav.c
>     httpd/httpd/trunk/server/core.c
> 
avior in the filesystem
> 
> Modified: httpd/httpd/trunk/modules/dav/main/mod_dav.c
> URL: 
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/dav/main/mod_dav.c?rev=1897156&r1=1897155&r2=1897156&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/modules/dav/main/mod_dav.c (original)
> +++ httpd/httpd/trunk/modules/dav/main/mod_dav.c Mon Jan 17 16:10:51 2022

>  
> @@ -723,6 +737,57 @@ static int dav_get_overwrite(request_rec
>      return -1;
>  }
>  
> +static int uripath_is_canonical(const char *uripath)

Isn't this a filesystem path we are talking about in the <Directory > case?
How does this function work on Windows when people might use '\' instead of '/'?

> +{
> +    const char *dot_pos, *ptr = uripath;
> +    apr_size_t i, len;
> +    unsigned pattern = 0;
> +
> +    /* URIPATH is canonical if it has:
> +     *  - no '.' segments
> +     *  - no closing '/'
> +     *  - no '//'
> +     */
> +
> +    if (ptr[0] == '.'
> +            && (ptr[1] == '/' || ptr[1] == '\0'
> +                    || (ptr[1] == '.' && (ptr[2] == '/' || ptr[2] == 
> '\0')))) {
> +        return 0;
> +    }
> +
> +    /* valid special cases */
> +    len = strlen(ptr);
> +    if (len < 2) {

Empty pathes ("") are ok?

> +        return 1;
> +    }
> +
> +    /* invalid endings */
> +    if (ptr[len - 1] == '/' || (ptr[len - 1] == '.' && ptr[len - 2] == '/')) 
> {
> +        return 0;
> +    }
> +
> +    /* '.' are rare. So, search for them globally. There will often be no
> +     * more than one hit.  Also note that we already checked for invalid
> +     * starts and endings, i.e. we only need to check for "/./"

Why don't we need to look for /../ segments?

> +     */
> +    for (dot_pos = memchr(ptr, '.', len); dot_pos;
> +            dot_pos = strchr(dot_pos + 1, '.')) {
> +        if (dot_pos > ptr && dot_pos[-1] == '/' && dot_pos[1] == '/') {
> +            return 0;
> +        }
> +    }
> +
> +    /* Now validate the rest of the path. */
> +    for (i = 0; i < len - 1; ++i) {
> +        pattern = ((pattern & 0xff) << 8) + (unsigned char) ptr[i];
> +        if (pattern == 0x101 * (unsigned char) ('/')) {
> +            return 0;
> +        }
> +    }
> +
> +    return 1;
> +}
> +
>  /* resolve a request URI to a resource descriptor.
>   *
>   * If label_allowed != 0, then allow the request target to be altered by

Reply via email to