You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/06/05 14:05:14 UTC

svn commit: r1489828 - /subversion/trunk/subversion/libsvn_subr/dirent_uri.c

Author: stefan2
Date: Wed Jun  5 12:05:14 2013
New Revision: 1489828

URL: http://svn.apache.org/r1489828
Log:
Another go at the relpath_is_canonical check.  As it turns out, it is
much faster to check for "." and "//" elements in seperate runs due to
the simpler patterns that we check for.

* subversion/libsvn_subr/dirent_uri.c
  (relpath_is_canonical): rework the scanner part

Modified:
    subversion/trunk/subversion/libsvn_subr/dirent_uri.c

Modified: subversion/trunk/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/dirent_uri.c?rev=1489828&r1=1489827&r2=1489828&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/trunk/subversion/libsvn_subr/dirent_uri.c Wed Jun  5 12:05:14 2013
@@ -1688,8 +1688,9 @@ svn_dirent_is_canonical(const char *dire
 static svn_boolean_t
 relpath_is_canonical(const char *relpath)
 {
-  const char *ptr = relpath;
+  const char *dot_pos, *ptr = relpath;
   apr_size_t i, len;
+  unsigned pattern = 0;
 
   /* RELPATH is canonical if it has:
    *  - no '.' segments
@@ -1713,16 +1714,23 @@ relpath_is_canonical(const char *relpath
   if (ptr[len-1] == '/' || (ptr[len-1] == '.' && ptr[len-2] == '/'))
     return FALSE;
 
+  /* '.' 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 "/./"
+   */
+  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 FALSE;
+
   /* Now validate the rest of the path. */
   for (i = 0; i < len - 1; ++i)
-    if (ptr[i] == '/' && ptr[i+1] <= '/') /* '.' and '/' have smaller UTF-8
-                                             codes than most other chars */
-      {
-        if (ptr[i+1] == '/')
-          return FALSE;  /*  //   */
-        if (ptr[i+1] == '.' && ptr[i+2] == '/')
-          return FALSE;  /*  /./  */
-      }
+    {
+      pattern = ((pattern & 0xff) << 8) + (unsigned char)ptr[i];
+      if (pattern == 0x101 * (unsigned char)('/'))
+        return FALSE;
+    }
 
   return TRUE;
 }