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

Re: lock_tests-9 is segfaulting over ra_dav

From: Philip Martin <philip_at_codematters.co.uk>
Date: 2005-04-18 01:11:15 CEST

Philip Martin <philip@codematters.co.uk> writes:

> Jani Averbach <jaa@jaa.iki.fi> writes:
>
>> The lock-test 9 is segfaulting over ra_dav with trunk@14272 (at
>> least). I will slightly modify svntest so I can tell for sure when and
>> with what it is segfaulting after next run of the svntest.
>>
>> svntest $ ~/inst/svn_trunk/bin/svn unlock \
>> --username=jrandom --password=rayjandom \
>> http://localhost:42024/repositories/lock_tests-9/iota
>> Segmentation fault
>
> The first valgrind error is
>
> $ valgrind -q svn "unlock" "--username" "jrandom" "--password" "rayjandom" "http://localhost:8888/repositories/lock_tests-9/iota"
> ==25529== Invalid read of size 4
> ==25529== at 0x1BA1B4C2: create_request_hook (session.c:896)
> ==25529== by 0x1BBF5AA3: ne_request_create (in /usr/lib/libneon.so.24.0.7)
> ==25529== by 0x1BC00C64: ne_unlock (in /usr/lib/libneon.so.24.0.7)
> ==25529== by 0x1BA1BE82: shim_svn_ra_dav__unlock (session.c:1176)
> ==25529== by 0x1BA1C059: svn_ra_dav__unlock (session.c:1241)
> ==25529== by 0x1B96707F: svn_ra_unlock (ra_loader.c:525)
> ==25529== by 0x1B922259: svn_client_unlock (locking_commands.c:422)
> ==25529== by 0x8057BDA: svn_cl__unlock (unlock-cmd.c:56)
> ==25529== by 0x80524FD: main (main.c:1442)
> ==25529== Address 0x1BF77654 is 28 bytes inside a block of size 32 free'd
> ==25529== at 0x1B901AA8: free (vg_replace_malloc.c:152)
> ==25529== by 0x1BB7AEDE: pool_clear_debug (apr_pools.c:1376)
> ==25529== by 0x1BB7B036: apr_pool_destroy_debug (apr_pools.c:1437)
> ==25529== by 0x1B921EC4: fetch_tokens (locking_commands.c:318)
> ==25529== by 0x1B922205: svn_client_unlock (locking_commands.c:415)
> ==25529== by 0x8057BDA: svn_cl__unlock (unlock-cmd.c:56)
> ==25529== by 0x80524FD: main (main.c:1442)

Looking at libsvn_ra_dav/session.c, the functions
shim_svn_ra_dav__lock and shim_svn_ra_dav__unlock both contain the
code:

  /* Clear out the lrb... */
  memset((ras->lrb), 0, sizeof(ras->lrb));

Huh? That ras->lrb is a pointer so that makes little sense, probably
it should be sizeof(*ras->lrb).

The next problem is the lifetime of the neon request hooks. The
function setup_neon_request_hook contains the comment:

  /* We need to set up the lock callback once and only once per neon
     session creation. */

but I see nothing that enforces that. The functions
svn_ra_dav__unlock and svn_ra_dav__lock both call
setup_neon_request_hook and may do so more than once, we need to check
that. Also, the pool passed to setup_neon_request_hook may have a
lifetime shorter than the session so the hooks may last longer than
the allocated memory, I think the session pool should be used.

Finally, the function svn_ra_dav__get_lock sets up a neon request hook
without calling setup_neon_request_hook, and it also uses a pool with
a lifetime shorter than the session, which I believe is causing the
valgrind error above. I think it should be using the
setup_neon_request_hook function.

Something like the following perhaps?

Fix a neon hook lifetime problem.

* subversion/libsvn_ra_dav/session.c
  (setup_neon_request_hook): Use the session pool instead of passing a
    pool argument, don't setup the hook more than once.
  (shim_svn_ra_dav__lock, shim_svn_ra_dav__unlock): memset the
    log_request_baton struct not the pointer.
  (svn_ra_dav__get_lock): Use setup_neon_request_hook to setup the
    hook rather than coding it directly.

Index: subversion/libsvn_ra_dav/session.c
===================================================================
--- subversion/libsvn_ra_dav/session.c (revision 14278)
+++ subversion/libsvn_ra_dav/session.c (working copy)
@@ -959,21 +959,23 @@
 
 
 static void
-setup_neon_request_hook(svn_ra_dav__session_t *ras,
- apr_pool_t *pool)
+setup_neon_request_hook(svn_ra_dav__session_t *ras)
 {
   /* We need to set up the lock callback once and only once per neon
      session creation. */
 
- struct lock_request_baton *lrb;
- /* Build context for neon callbacks and then register them. */
- lrb = apr_pcalloc(pool, sizeof(*lrb));
+ if (! ras->lrb)
+ {
+ struct lock_request_baton *lrb;
+ /* Build context for neon callbacks and then register them. */
+ lrb = apr_pcalloc(ras->pool, sizeof(*lrb));
 
- ne_hook_create_request(ras->sess, create_request_hook, lrb);
- ne_hook_pre_send(ras->sess, pre_send_hook, lrb);
+ ne_hook_create_request(ras->sess, create_request_hook, lrb);
+ ne_hook_pre_send(ras->sess, pre_send_hook, lrb);
 
- lrb->pool = pool;
- ras->lrb = lrb;
+ lrb->pool = ras->pool;
+ ras->lrb = lrb;
+ }
 }
 
 /* ### TODO for 1.3: Send all locks to the server at once. */
@@ -999,7 +1001,7 @@
                                         url, SVN_INVALID_REVNUM, pool));
 
   /* Clear out the lrb... */
- memset((ras->lrb), 0, sizeof(ras->lrb));
+ memset((ras->lrb), 0, sizeof(*ras->lrb));
 
   /* ...and load it up again. */
   ras->lrb->pool = pool;
@@ -1079,7 +1081,7 @@
   apr_hash_index_t *hi;
   apr_pool_t *iterpool = svn_pool_create (pool);
 
- setup_neon_request_hook(session->priv, pool);
+ setup_neon_request_hook(session->priv);
 
   /* ### TODO for 1.3: Send all the locks over the wire at once. This
      loop is just a temporary shim. */
@@ -1166,7 +1168,7 @@
     }
 
   /* Clear out the lrb... */
- memset((ras->lrb), 0, sizeof(ras->lrb));
+ memset((ras->lrb), 0, sizeof(*ras->lrb));
 
   /* ...and load it up again. */
   ras->lrb->pool = pool;
@@ -1215,7 +1217,7 @@
   apr_hash_index_t *hi;
   apr_pool_t *iterpool = svn_pool_create (pool);
 
- setup_neon_request_hook(session->priv, pool);
+ setup_neon_request_hook(session->priv);
 
   /* ### TODO for 1.3: Send all the lock tokens over the wire at once.
         This loop is just a temporary shim. */
@@ -1328,7 +1330,6 @@
   svn_ra_dav__session_t *ras = session->priv;
   int rv;
   const char *url;
- struct lock_request_baton *lrb;
   struct receiver_baton *rb;
   svn_string_t fs_path;
 
@@ -1338,16 +1339,15 @@
                                         url, SVN_INVALID_REVNUM, pool));
 
   /* Build context for neon callbacks and then register them. */
- lrb = apr_pcalloc(pool, sizeof(*lrb));
- lrb->pool = pool;
- ne_hook_create_request(ras->sess, create_request_hook, lrb);
- ne_hook_pre_send(ras->sess, pre_send_hook, lrb);
+ setup_neon_request_hook(ras);
+ memset((ras->lrb), 0, sizeof(*ras->lrb));
+ ras->lrb->pool = pool;
 
   /* Build context for the lock_receiver() callback. */
   rb = apr_pcalloc(pool, sizeof(*rb));
   rb->pool = pool;
   rb->ras = ras;
- rb->lrb = lrb;
+ rb->lrb = ras->lrb;
   rb->fs_path = fs_path.data;
 
   /* Ask neon to "discover" the lock (presumably by doing a PROPFIND
@@ -1355,39 +1355,39 @@
   rv = ne_lock_discover(ras->sess, url, lock_receiver, rb);
 
   /* Did we get a <D:error> response? */
- if (lrb->err)
+ if (ras->lrb->err)
     {
- if (lrb->error_parser)
- ne_xml_destroy(lrb->error_parser);
- return lrb->err;
+ if (ras->lrb->error_parser)
+ ne_xml_destroy(ras->lrb->error_parser);
+ return ras->lrb->err;
     }
 
   /* Did lock_receiver() generate an error? */
   if (rb->err)
     {
- if (lrb->error_parser)
- ne_xml_destroy(lrb->error_parser);
+ if (ras->lrb->error_parser)
+ ne_xml_destroy(ras->lrb->error_parser);
       return rb->err;
     }
 
   /* Did we get some other sort of neon error? */
   if (rv)
     {
- if (lrb->error_parser)
- ne_xml_destroy(lrb->error_parser);
+ if (ras->lrb->error_parser)
+ ne_xml_destroy(ras->lrb->error_parser);
       return svn_ra_dav__convert_error(ras->sess,
                                        _("Failed to fetch lock information"),
                                        rv, pool);
     }
 
   /* Free neon things. */
- if (lrb->error_parser)
- ne_xml_destroy(lrb->error_parser);
+ if (ras->lrb->error_parser)
+ ne_xml_destroy(ras->lrb->error_parser);
 
   /* Check to see if the server sent a custom 'creationdate' header in
      the PROPFIND response. If so, use it. */
- if (lrb->creation_date)
- rb->lock->creation_date = lrb->creation_date;
+ if (ras->lrb->creation_date)
+ rb->lock->creation_date = ras->lrb->creation_date;
   
   *lock = rb->lock;
   return SVN_NO_ERROR;

-- 
Philip Martin
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Mon Apr 18 01:12:06 2005

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