diff options
Diffstat (limited to 'subversion/libsvn_subr/dirent_uri.c')
-rw-r--r-- | subversion/libsvn_subr/dirent_uri.c | 175 |
1 files changed, 156 insertions, 19 deletions
diff --git a/subversion/libsvn_subr/dirent_uri.c b/subversion/libsvn_subr/dirent_uri.c index b53f3508fd2d..059734c7a1f8 100644 --- a/subversion/libsvn_subr/dirent_uri.c +++ b/subversion/libsvn_subr/dirent_uri.c @@ -37,6 +37,7 @@ #include "svn_ctype.h" #include "dirent_uri.h" +#include "private/svn_dirent_uri_private.h" #include "private/svn_fspath.h" #include "private/svn_cert.h" @@ -292,8 +293,9 @@ uri_previous_segment(const char *uri, /* Return the canonicalized version of PATH, of type TYPE, allocated in * POOL. */ -static const char * -canonicalize(path_type_t type, const char *path, apr_pool_t *pool) +static svn_error_t * +canonicalize(const char **canonical_path, + path_type_t type, const char *path, apr_pool_t *pool) { char *canon, *dst; const char *src; @@ -307,8 +309,12 @@ canonicalize(path_type_t type, const char *path, apr_pool_t *pool) depends on path not being zero-length. */ if (SVN_PATH_IS_EMPTY(path)) { - assert(type != type_uri); - return ""; + *canonical_path = ""; + if (type == type_uri) + return svn_error_create(SVN_ERR_CANONICALIZATION_FAILED, NULL, + _("An empty URI can not be canonicalized")); + else + return SVN_NO_ERROR; } dst = canon = apr_pcalloc(pool, strlen(path) + 1); @@ -319,7 +325,12 @@ canonicalize(path_type_t type, const char *path, apr_pool_t *pool) src = path; if (type == type_uri) { - assert(*src != '/'); + if (*src == '/') + { + *canonical_path = src; + return svn_error_create(SVN_ERR_CANONICALIZATION_FAILED, NULL, + _("A URI can not start with '/'")); + } while (*src && (*src != '/') && (*src != ':')) src++; @@ -546,7 +557,10 @@ canonicalize(path_type_t type, const char *path, apr_pool_t *pool) if ((type == type_dirent) && canon[0] == '/' && canon[1] == '/') { if (canon_segments < 2) - return canon + 1; + { + *canonical_path = canon + 1; + return SVN_NO_ERROR; + } else { /* Now we're sure this is a valid UNC path, convert the server name @@ -654,7 +668,8 @@ canonicalize(path_type_t type, const char *path, apr_pool_t *pool) *dst = '\0'; } - return canon; + *canonical_path = canon; + return SVN_NO_ERROR; } /* Return the string length of the longest common ancestor of PATH1 and PATH2. @@ -883,6 +898,20 @@ svn_dirent_internal_style(const char *dirent, apr_pool_t *pool) return svn_dirent_canonicalize(internal_style(dirent, pool), pool); } +svn_error_t * +svn_dirent_internal_style_safe(const char **internal_style_dirent, + const char **non_canonical_result, + const char *dirent, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + return svn_error_trace( + svn_dirent_canonicalize_safe(internal_style_dirent, + non_canonical_result, + internal_style(dirent, scratch_pool), + result_pool, scratch_pool)); +} + const char * svn_dirent_local_style(const char *dirent, apr_pool_t *pool) { @@ -906,14 +935,18 @@ svn_dirent_local_style(const char *dirent, apr_pool_t *pool) return dirent; } -const char * -svn_relpath__internal_style(const char *relpath, - apr_pool_t *pool) +svn_error_t * +svn_relpath__make_internal(const char **internal_style_relpath, + const char *relpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - return svn_relpath_canonicalize(internal_style(relpath, pool), pool); + return svn_error_trace( + svn_relpath_canonicalize_safe(internal_style_relpath, NULL, + internal_style(relpath, scratch_pool), + result_pool, scratch_pool)); } - /* We decided against using apr_filepath_root here because of the negative performance impact (creating a pool and converting strings ). */ svn_boolean_t @@ -1643,19 +1676,84 @@ svn_dirent_get_absolute(const char **pabsolute, const char * svn_uri_canonicalize(const char *uri, apr_pool_t *pool) { - return canonicalize(type_uri, uri, pool); + const char *result; + svn_error_t *const err = canonicalize(&result, type_uri, uri, pool); + if (err) + { + svn_error_clear(err); + SVN_ERR_ASSERT_NO_RETURN(!"URI canonicalization failed"); + } + return result; +} + +svn_error_t * +svn_uri_canonicalize_safe(const char **canonical_uri, + const char **non_canonical_result, + const char *uri, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *result = NULL; + SVN_ERR(canonicalize(&result, type_uri, uri, result_pool)); + if (!svn_uri_is_canonical(result, scratch_pool)) + { + if (non_canonical_result) + *non_canonical_result = result; + + return svn_error_createf( + SVN_ERR_CANONICALIZATION_FAILED, NULL, + _("Could not canonicalize URI '%s'" + " (the result '%s' is not canonical)"), + uri, result); + } + *canonical_uri = result; + return SVN_NO_ERROR; } const char * svn_relpath_canonicalize(const char *relpath, apr_pool_t *pool) { - return canonicalize(type_relpath, relpath, pool); + const char *result; + svn_error_t *const err = canonicalize(&result, type_relpath, relpath, pool); + if (err) + { + svn_error_clear(err); + SVN_ERR_ASSERT_NO_RETURN(!"relpath canonicalization failed"); + } + return result; } -const char * -svn_dirent_canonicalize(const char *dirent, apr_pool_t *pool) +svn_error_t * +svn_relpath_canonicalize_safe(const char **canonical_relpath, + const char **non_canonical_result, + const char *relpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *result = NULL; + SVN_ERR(canonicalize(&result, type_relpath, relpath, result_pool)); + if (!svn_relpath_is_canonical(result)) + { + if (non_canonical_result) + *non_canonical_result = result; + + return svn_error_createf( + SVN_ERR_CANONICALIZATION_FAILED, NULL, + _("Could not canonicalize relpath '%s'" + " (the result '%s' is not canonical)"), + relpath, result); + } + + SVN_UNUSED(scratch_pool); + *canonical_relpath = result; + return SVN_NO_ERROR; +} + +static svn_error_t * +canonicalize_dirent(const char **result, const char *dirent, apr_pool_t *pool) { - const char *dst = canonicalize(type_dirent, dirent, pool); + const char *dst; + SVN_ERR(canonicalize(&dst, type_dirent, dirent, pool)); #ifdef SVN_USE_DOS_PATHS /* Handle a specific case on Windows where path == "X:/". Here we have to @@ -1671,11 +1769,50 @@ svn_dirent_canonicalize(const char *dirent, apr_pool_t *pool) dst_slash[2] = '/'; dst_slash[3] = '\0'; - return dst_slash; + *result = dst_slash; + return SVN_NO_ERROR; } #endif /* SVN_USE_DOS_PATHS */ - return dst; + *result = dst; + return SVN_NO_ERROR; +} + +const char * +svn_dirent_canonicalize(const char *dirent, apr_pool_t *pool) +{ + const char *result; + svn_error_t *const err = canonicalize_dirent(&result, dirent, pool); + if (err) + { + svn_error_clear(err); + SVN_ERR_ASSERT_NO_RETURN(!"dirent canonicalization failed"); + } + return result; +} + +svn_error_t * +svn_dirent_canonicalize_safe(const char **canonical_dirent, + const char **non_canonical_result, + const char *dirent, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *result = NULL; + SVN_ERR(canonicalize_dirent(&result, dirent, result_pool)); + if (!svn_dirent_is_canonical(result, scratch_pool)) + { + if (non_canonical_result) + *non_canonical_result = result; + + return svn_error_createf( + SVN_ERR_CANONICALIZATION_FAILED, NULL, + _("Could not canonicalize dirent '%s'" + " (the result '%s' is not canonical)"), + dirent, result); + } + *canonical_dirent = result; + return SVN_NO_ERROR; } svn_boolean_t |