You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2018/01/19 16:07:16 UTC
svn commit: r1821678 - /subversion/trunk/subversion/libsvn_client/shelve.c
Author: julianfoad
Date: Fri Jan 19 16:07:16 2018
New Revision: 1821678
URL: http://svn.apache.org/viewvc?rev=1821678&view=rev
Log:
Encode the shelf name to ensure a valid filename for the patch file.
* subversion/libsvn_client/shelve.c
(shelf_name_encode,
shelf_name_decode,
shelf_name_from_filename): New.
(get_patch_abspath): Encode.
(svn_client_shelves_list): Decode; ignore unrecognized filenames.
(validate_name): Delete this function and the calls to it.
Modified:
subversion/trunk/subversion/libsvn_client/shelve.c
Modified: subversion/trunk/subversion/libsvn_client/shelve.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/shelve.c?rev=1821678&r1=1821677&r2=1821678&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/shelve.c (original)
+++ subversion/trunk/subversion/libsvn_client/shelve.c Fri Jan 19 16:07:16 2018
@@ -34,6 +34,7 @@
#include "svn_path.h"
#include "svn_hash.h"
#include "svn_utf.h"
+#include "svn_ctype.h"
#include "client.h"
#include "private/svn_client_private.h"
@@ -41,15 +42,66 @@
#include "svn_private_config.h"
-/* Throw an error if NAME does not conform to our naming rules. */
static svn_error_t *
-validate_name(const char *name,
- apr_pool_t *scratch_pool)
+shelf_name_encode(char **encoded_name_p,
+ const char *name,
+ apr_pool_t *result_pool)
{
- if (name[0] == '\0' || strchr(name, '/'))
- return svn_error_createf(SVN_ERR_BAD_CHANGELIST_NAME, NULL,
- _("Shelve: Bad name '%s'"), name);
+ char *encoded_name
+ = apr_palloc(result_pool, strlen(name) * 2 + 1);
+ char *out_pos = encoded_name;
+
+ if (name[0] == '\0')
+ return svn_error_create(SVN_ERR_BAD_CHANGELIST_NAME, NULL,
+ _("Shelf name cannot be the empty string"));
+ while (*name)
+ {
+ apr_snprintf(out_pos, 3, "%02x", *name++);
+ out_pos += 2;
+ }
+ *encoded_name_p = encoded_name;
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+shelf_name_decode(char **decoded_name_p,
+ const char *codename,
+ apr_pool_t *result_pool)
+{
+ svn_stringbuf_t *sb
+ = svn_stringbuf_create_ensure(strlen(codename) / 2, result_pool);
+ const char *input = codename;
+
+ while (*input)
+ {
+ int c;
+ int nchars;
+ int nitems = sscanf(input, "%02x%n", &c, &nchars);
+
+ if (nitems != 1 || nchars != 2)
+ return svn_error_createf(SVN_ERR_BAD_CHANGELIST_NAME, NULL,
+ _("Shelve: Bad encoded name '%s'"), codename);
+ svn_stringbuf_appendbyte(sb, c);
+ input += 2;
+ }
+ *decoded_name_p = sb->data;
+ return SVN_NO_ERROR;
+}
+
+/* Set *NAME to the shelf name from FILENAME. */
+static svn_error_t *
+shelf_name_from_filename(char **name,
+ const char *filename,
+ apr_pool_t *result_pool)
+{
+ size_t len = strlen(filename);
+
+ if (len > 6 && strcmp(filename + len - 6, ".patch") == 0)
+ {
+ char *codename = apr_pstrndup(result_pool, filename, len - 6);
+ SVN_ERR(shelf_name_decode(name, codename, result_pool));
+ }
return SVN_NO_ERROR;
}
@@ -65,11 +117,12 @@ get_patch_abspath(char **patch_abspath,
apr_pool_t *scratch_pool)
{
char *dir;
- const char *filename;
+ char *filename;
SVN_ERR(svn_wc__get_shelves_dir(&dir, ctx->wc_ctx, wc_root_abspath,
scratch_pool, scratch_pool));
- filename = apr_pstrcat(scratch_pool, name, ".patch", SVN_VA_NULL);
+ SVN_ERR(shelf_name_encode(&filename, name, scratch_pool));
+ filename = apr_pstrcat(scratch_pool, filename, ".patch", SVN_VA_NULL);
*patch_abspath = svn_dirent_join(dir, filename, result_pool);
return SVN_NO_ERROR;
}
@@ -240,8 +293,6 @@ svn_client_shelve(const char *name,
const char *message = "";
svn_error_t *err;
- SVN_ERR(validate_name(name, pool));
-
/* ### TODO: check all paths are in same WC; for now use first path */
SVN_ERR(svn_dirent_get_absolute(&local_abspath,
APR_ARRAY_IDX(paths, 0, char *), pool));
@@ -302,8 +353,6 @@ svn_client_unshelve(const char *name,
const char *wc_root_abspath;
svn_error_t *err;
- SVN_ERR(validate_name(name, pool));
-
SVN_ERR(svn_client_get_wc_root(&wc_root_abspath,
local_abspath, ctx, pool, pool));
@@ -339,8 +388,6 @@ svn_client_shelves_delete(const char *na
{
const char *wc_root_abspath;
- SVN_ERR(validate_name(name, pool));
-
SVN_ERR(svn_client_get_wc_root(&wc_root_abspath,
local_abspath, ctx, pool, pool));
@@ -378,8 +425,6 @@ svn_client_shelf_get_paths(apr_hash_t **
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
apr_hash_t *paths = apr_hash_make(result_pool);
- SVN_ERR(validate_name(name, scratch_pool));
-
SVN_ERR(svn_client_get_wc_root(&wc_root_abspath,
local_abspath, ctx, scratch_pool, scratch_pool));
SVN_ERR(get_patch_abspath(&patch_abspath, name, wc_root_abspath,
@@ -469,15 +514,16 @@ svn_client_shelves_list(apr_hash_t **she
for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi))
{
const char *filename = apr_hash_this_key(hi);
- size_t len = strlen(filename);
+ svn_io_dirent2_t *dirent = apr_hash_this_val(hi);
+ char *name = NULL;
- if (len > 6 && strcmp(filename + len - 6, ".patch") == 0)
+ svn_error_clear(shelf_name_from_filename(&name, filename, result_pool));
+ if (name && dirent->kind == svn_node_file)
{
- const char *name = apr_pstrndup(result_pool, filename, len - 6);
svn_client_shelved_patch_info_t *info
= apr_palloc(result_pool, sizeof(*info));
- info->dirent = apr_hash_this_val(hi);
+ info->dirent = dirent;
info->mtime = info->dirent->mtime;
info->patch_path
= svn_dirent_join(shelves_dir, filename, result_pool);