[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Access Violation with 'svn status -u'

From: Philip Martin <philip_at_codematters.co.uk>
Date: Tue, 10 Jan 2012 17:23:42 +0000

Philip Martin <philip.martin_at_wandisco.com> writes:

> Philip Martin <philip.martin_at_wandisco.com> writes:
>
>> svnadmin create repo
>> svn import -mm repo/format file://$PWD/repo/A/f
>> svn co -r0 file://$PWD/repo wc
>> svn mkdir wc/A
>> svn st -u wc
>>
>> That's obviously a bug. It's crashing in make_file_baton:
>>
>> f->repos_relpath = svn_relpath_join(find_dir_repos_relpath(pb, pool),
>> f->name, pool);
>>
>> when find_dir_repos_relpath returns NULL. We could set f->repos_relpath
>> to NULL, which matched what happens for the directory baton for A, but
>> is that correct? find_dir_repos_relpath is returning NULL because the
>> "obstructing" A is not versioned, although there is an A in the
>> repository. I'm not sure what repos_relpath is supposed to represent
>> here. Is it the repository path associated with the name in the
>> repository, or the repository path associated with the node in wc.db?
>
> There is a commment in find_dir_repos_relpath:
>
> /* Note that status->repos_relpath could be NULL in the case of a missing
> * directory, which means we need to recurse up another level to get
> * a useful relpath. */
> if (status)
> return status->repos_relpath;
>
>
> but the code doesn't recurse. Should that if be changed to
>
> if (status && status->repos_relpath)
> return status->repos_relpath;
>
> If we do that does that mean that find_dir_repos_relpath can never
> return NULL as it always recurses up to some non-NULL path? Should we
> remove the "return NULL?

I don't know whether repos_relpath should be allowed to be NULL or not.
I can fix it either way and all the regression tests, including the
javahl tests, pass.

I could fix it like this, allowing repos_relpath to be NULL:

Index: subversion/tests/cmdline/stat_tests.py
===================================================================
--- subversion/tests/cmdline/stat_tests.py (revision 1229514)
+++ subversion/tests/cmdline/stat_tests.py (working copy)
@@ -117,6 +117,12 @@ def status_update_with_nested_adds(sbox):
   svntest.actions.run_and_verify_unquiet_status(wc_backup,
                                                 expected_status)
 
+ # At one time an obstructing 'newdir' caused a SEGV on 'newdir/newfile'
+ os.makedirs(os.path.join(wc_backup, 'newdir'))
+ expected_status.tweak('newdir', status='? ')
+ svntest.actions.run_and_verify_unquiet_status(wc_backup,
+ expected_status)
+
 #----------------------------------------------------------------------
 
 # svn status -vN should include all entries in a directory
Index: subversion/libsvn_wc/status.c
===================================================================
--- subversion/libsvn_wc/status.c (revision 1229514)
+++ subversion/libsvn_wc/status.c (working copy)
@@ -1795,6 +1795,7 @@ make_file_baton(struct dir_baton *parent_dir_baton
   struct dir_baton *pb = parent_dir_baton;
   struct edit_baton *eb = pb->edit_baton;
   struct file_baton *f = apr_pcalloc(pool, sizeof(*f));
+ const char *dir_repos_relpath = find_dir_repos_relpath(pb, pool);
 
   /* Finish populating the baton members. */
   f->local_abspath = svn_dirent_join(eb->anchor_abspath, path, pool);
@@ -1804,8 +1805,9 @@ make_file_baton(struct dir_baton *parent_dir_baton
   f->edit_baton = eb;
   f->ood_changed_rev = SVN_INVALID_REVNUM;
   f->ood_changed_date = 0;
- f->repos_relpath = svn_relpath_join(find_dir_repos_relpath(pb, pool),
- f->name, pool);
+ f->repos_relpath = (dir_repos_relpath
+ ? svn_relpath_join(dir_repos_relpath, f->name, pool)
+ : NULL);
   f->ood_kind = svn_node_file;
   f->ood_changed_author = NULL;
   return f;

or I could fix it like this, with repos_relpath never NULL:

 # svn status -vN should include all entries in a directory
Index: subversion/libsvn_wc/status.c
===================================================================
--- subversion/libsvn_wc/status.c (revision 1229514)
+++ subversion/libsvn_wc/status.c (working copy)
@@ -1649,7 +1649,7 @@ tweak_statushash(void *baton,
   return SVN_NO_ERROR;
 }
 
-/* Returns the URL for DB, or NULL: */
+/* Returns the URL for DB */
 static const char *
 find_dir_repos_relpath(const struct dir_baton *db, apr_pool_t *pool)
 {
@@ -1666,14 +1666,11 @@ find_dir_repos_relpath(const struct dir_baton *db,
       /* Note that status->repos_relpath could be NULL in the case of a missing
        * directory, which means we need to recurse up another level to get
        * a useful relpath. */
- if (status)
+ if (status && status->repos_relpath)
         return status->repos_relpath;
 
       repos_relpath = find_dir_repos_relpath(pb, pool);
- if (repos_relpath)
- return svn_relpath_join(repos_relpath, db->name, pool);
- else
- return NULL;
+ return svn_relpath_join(repos_relpath, db->name, pool);
     }
 }
 
@@ -2369,19 +2366,15 @@ close_file(void *file_baton,
           const char *dir_repos_relpath = find_dir_repos_relpath(fb->dir_baton,
                                                                  pool);
 
- if (dir_repos_relpath)
- {
- /* repos_lock still uses the deprecated filesystem absolute path
- format */
+ /* repos_lock still uses the deprecated filesystem absolute path
+ format */
+ const char *repos_relpath = svn_relpath_join(dir_repos_relpath,
+ fb->name, pool);
 
- const char *repos_relpath = svn_relpath_join(dir_repos_relpath,
- fb->name, pool);
-
- repos_lock = apr_hash_get(fb->edit_baton->wb.repos_locks,
- svn_fspath__join("/", repos_relpath,
- pool),
- APR_HASH_KEY_STRING);
- }
+ repos_lock = apr_hash_get(fb->edit_baton->wb.repos_locks,
+ svn_fspath__join("/", repos_relpath,
+ pool),
+ APR_HASH_KEY_STRING);
         }
     }
   else

-- 
Philip
Received on 2012-01-10 18:24:22 CET

This is an archived mail posted to the Subversion Dev mailing list.