I spotted a filename encoding error when using "delete on pool cleanup"
with svn_io_open_unique_file3().  I have not tested this, but I believe
this bug would fail to clean up the temp file if the UTF-8 encoding of
the directory path differs from its APR encoding.

How can I easily test this in my Ubuntu UTF-8 environment?

- Julian

Fix a filename encoding error when using "delete on pool cleanup" with
svn_io_open_unique_file3().  I have not tested this, but I believe this bug
would fail to clean up the temp file if the UTF-8 encoding of the directory
path differs from its APR encoding.

Also update doc strings and parameter names to identify the encoding more
clearly.

* subversion/libsvn_subr/io.c
  (file_open): Rename the 'fname' parameter to 'fname_apr' and mention it in
    the doc string.
  (temp_file_cleanup_s): Rename the 'name' member to 'fname_apr' and
    document it.
  (temp_file_plain_cleanup_handler, svn_io_open_uniquely_named): Adjust.
  (file_perms_set, svn_io_file_name_get): Mention that filename parameters
    are in UTF-8, as these are otherwise basically wrappers around APR.
  (svn_io_open_unique_file3): Convert the filename to APR encoding before
    storing it in the pool-cleanup baton.
--This line, and those below, will be ignored--

Index: subversion/libsvn_subr/io.c
===================================================================
--- subversion/libsvn_subr/io.c	(revision 955599)
+++ subversion/libsvn_subr/io.c	(working copy)
@@ -243,20 +243,20 @@ io_check_path(const char *path,
 }
 
 
-/* Wrapper for apr_file_open(). */
+/* Wrapper for apr_file_open(), taking an APR-encoded filename. */
 static apr_status_t
 file_open(apr_file_t **f,
-          const char *fname,
+          const char *fname_apr,
           apr_int32_t flag,
           apr_fileperms_t perm,
           svn_boolean_t retry_on_failure,
           apr_pool_t *pool)
 {
-  apr_status_t status = apr_file_open(f, fname, flag, perm, pool);
+  apr_status_t status = apr_file_open(f, fname_apr, flag, perm, pool);
 
   if (retry_on_failure)
     {
-      WIN32_RETRY_LOOP(status, apr_file_open(f, fname, flag, perm, pool));
+      WIN32_RETRY_LOOP(status, apr_file_open(f, fname_apr, flag, perm, pool));
     }
   return status;
 }
@@ -292,7 +292,9 @@ svn_io_check_special_path(const char *pa
 struct temp_file_cleanup_s
 {
   apr_pool_t *pool;
-  const char *name;
+  /* The (APR-encoded) full path of the file to be removed, or NULL if
+   * nothing to do. */
+  const char *fname_apr;
 };
 
 
@@ -302,10 +304,10 @@ temp_file_plain_cleanup_handler(void *ba
   struct  temp_file_cleanup_s *b = baton;
   apr_status_t apr_err = APR_SUCCESS;
 
-  if (b->name)
+  if (b->fname_apr)
     {
-      apr_err = apr_file_remove(b->name, b->pool);
-      WIN32_RETRY_LOOP(apr_err, apr_file_remove(b->name, b->pool));
+      apr_err = apr_file_remove(b->fname_apr, b->pool);
+      WIN32_RETRY_LOOP(apr_err, apr_file_remove(b->fname_apr, b->pool));
     }
 
   return apr_err;
@@ -354,7 +356,7 @@ svn_io_open_uniquely_named(apr_file_t **
       baton = apr_palloc(result_pool, sizeof(*baton));
 
       baton->pool = result_pool;
-      baton->name = NULL;
+      baton->fname_apr = NULL;
 
       /* Because cleanups are run LIFO, we need to make sure to register
          our cleanup before the apr_file_close cleanup:
@@ -447,7 +449,7 @@ svn_io_open_uniquely_named(apr_file_t **
       else
         {
           if (delete_when == svn_io_file_del_on_pool_cleanup)
-            baton->name = apr_pstrdup(result_pool, unique_name_apr);
+            baton->fname_apr = apr_pstrdup(result_pool, unique_name_apr);
 
           if (file)
             *file = try_file;
@@ -786,7 +788,7 @@ svn_io_copy_file(const char *src,
   return svn_error_return(svn_io_file_rename(dst_tmp, dst, pool));
 }
 
-/* Wrapper for apr_file_perms_set(). */
+/* Wrapper for apr_file_perms_set(), taking a UTF8-encoded filename. */
 static svn_error_t *
 file_perms_set(const char *fname, apr_fileperms_t perms,
                apr_pool_t *pool)
@@ -3665,7 +3667,7 @@ temp_file_create(apr_file_t **new_file,
 #endif
 }
 
-/* Wrapper for apr_file_name_get(). */
+/* Wrapper for apr_file_name_get(), passing out a UTF8-encoded filename. */
 svn_error_t *
 svn_io_file_name_get(const char **filename,
                      apr_file_t *file,
@@ -3718,7 +3720,7 @@ svn_io_open_unique_file3(apr_file_t **fi
       case svn_io_file_del_on_pool_cleanup:
         baton = apr_palloc(result_pool, sizeof(*baton));
         baton->pool = result_pool;
-        baton->name = NULL;
+        baton->fname_apr = NULL;
 
         /* Because cleanups are run LIFO, we need to make sure to register
            our cleanup before the apr_file_close cleanup:
@@ -3763,12 +3765,7 @@ svn_io_open_unique_file3(apr_file_t **fi
     *unique_path = tempname; /* Was allocated in result_pool */
 
   if (baton)
-    {
-      if (unique_path)
-        baton->name = *unique_path;
-      else
-        baton->name = tempname; /* Was allocated in result_pool */
-    }
+    SVN_ERR(cstring_from_utf8(&baton->fname_apr, tempname, result_pool));
 
   return SVN_NO_ERROR;
 }

Reply via email to