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

Re: svn commit: r15205 - in trunk/subversion: libsvn_ra_dav

From: <kfogel_at_collab.net>
Date: 2005-07-01 19:57:40 CEST

cmpilato@tigris.org writes:
> Log:
> Finish issue #2335.
>
> * subversion/libsvn_ra_dav/merge.c
> (svn_ra_dav__assemble_locktoken_body): XML-escape lock paths used in
> MERGE requests.
>
> * subversion/tests/clients/cmdline/lock_tests.py
> (commit_xml_unsafe_file_unlock): New regression test for this defect.
> (test_funcs): Add reference to new test.
>
> --- trunk/subversion/libsvn_ra_dav/merge.c (original)
> +++ trunk/subversion/libsvn_ra_dav/merge.c Thu Jun 30 16:02:32 2005
> @@ -550,39 +550,51 @@
> apr_size_t buf_size;
> const char *closing_tag = "</S:lock-token-list>";
> apr_size_t closing_tag_size = strlen(closing_tag);
> - svn_stringbuf_t *lockbuf =
> - svn_stringbuf_create
> - ("<S:lock-token-list xmlns:S=\"" SVN_XML_NAMESPACE "\">", pool);
> + apr_pool_t *tmppool = svn_pool_create(pool);
> + apr_hash_t *xml_locks = apr_hash_make(tmppool);
> + svn_stringbuf_t *lockbuf = svn_stringbuf_create
> + ("<S:lock-token-list xmlns:S=\"" SVN_XML_NAMESPACE "\">" DEBUG_CR, pool);
>
> buf_size = lockbuf->len;

Hmm, 'tmppool', that's unusual. It doesn't appear to be a standard
sort of loop pool -- is it an exception to our usual pool policy?
(Ah, question answered below, see there.)

> -#define SVN_LOCK "<S:lock>"
> +#define SVN_LOCK "<S:lock>" DEBUG_CR
> #define SVN_LOCK_LEN sizeof(SVN_LOCK)-1
> -#define SVN_LOCK_CLOSE "</S:lock>"
> +#define SVN_LOCK_CLOSE "</S:lock>" DEBUG_CR
> #define SVN_LOCK_CLOSE_LEN sizeof(SVN_LOCK_CLOSE)-1
> #define SVN_LOCK_PATH "<S:lock-path>"
> #define SVN_LOCK_PATH_LEN sizeof(SVN_LOCK_PATH)-1
> -#define SVN_LOCK_PATH_CLOSE "</S:lock-path>"
> +#define SVN_LOCK_PATH_CLOSE "</S:lock-path>" DEBUG_CR
> #define SVN_LOCK_PATH_CLOSE_LEN sizeof(SVN_LOCK_CLOSE)-1
> #define SVN_LOCK_TOKEN "<S:lock-token>"
> #define SVN_LOCK_TOKEN_LEN sizeof(SVN_LOCK_TOKEN)-1
> -#define SVN_LOCK_TOKEN_CLOSE "</S:lock-token>"
> +#define SVN_LOCK_TOKEN_CLOSE "</S:lock-token>" DEBUG_CR
> #define SVN_LOCK_TOKEN_CLOSE_LEN sizeof(SVN_LOCK_TOKEN_CLOSE)-1
>
> /* First, figure out how much string data we're talking about,
> and allocate a stringbuf big enough to hold it all... we *never*
> - want have the stringbuf do an auto-reallocation. */
> + want have the stringbuf do an auto-reallocation. While here,
> + we'll be copying our hash of paths -> tokens into a hash of
> + xml-escaped-paths -> tokens. */

Seems like an overly vehement comment, but that's just a matter of
taste I guess :-). It wouldn't be horrible to do auto-allocation,
though it's even nicer to anticipate the right size in advance.

> for (hi = apr_hash_first(pool, lock_tokens); hi; hi = apr_hash_next(hi))
> {
> const void *key;
> void *val;
> apr_ssize_t klen;
> -
> + svn_string_t lock_path;
> + svn_stringbuf_t *lock_path_xml = NULL;
> +
> apr_hash_this(hi, &key, &klen, &val);
> +
> + /* XML-escape our key and store it in our temporary hash. */
> + lock_path.data = key;
> + lock_path.len = klen;
> + svn_xml_escape_cdata_string(&lock_path_xml, &lock_path, tmppool);
> + apr_hash_set(xml_locks, lock_path_xml->data, lock_path_xml->len, val);
>
> + /* Now, on with the stringbuf calculations. */
> buf_size += SVN_LOCK_LEN;
> buf_size += SVN_LOCK_PATH_LEN;
> - buf_size += klen;
> + buf_size += lock_path_xml->len;
> buf_size += SVN_LOCK_PATH_CLOSE_LEN;
> buf_size += SVN_LOCK_TOKEN_LEN;
> buf_size += strlen(val);
> @@ -594,21 +606,22 @@
>
> svn_stringbuf_ensure(lockbuf, buf_size + 1);
>
> - /* Now append all the hash's keys and values into the stringbuf.
> - This is better than doing apr_pstrcat() in a loop, because
> - (1) there's no need to constantly re-alloc, and (2) the
> + /* Now append all the temporary hash's keys and values into the
> + stringbuf. This is better than doing apr_pstrcat() in a loop,
> + because (1) there's no need to constantly re-alloc, and (2) the
> stringbuf already knows the end of the buffer, so there's no
> seek-time to the end of the string when appending. */
> - for (hi = apr_hash_first(pool, lock_tokens); hi; hi = apr_hash_next(hi))
> + for (hi = apr_hash_first(pool, xml_locks); hi; hi = apr_hash_next(hi))
> {
> const void *key;
> + apr_ssize_t klen;
> void *val;
>
> - apr_hash_this(hi, &key, NULL, &val);
> + apr_hash_this(hi, &key, &klen, &val);
>
> svn_stringbuf_appendcstr(lockbuf, SVN_LOCK);
> svn_stringbuf_appendcstr(lockbuf, SVN_LOCK_PATH);
> - svn_stringbuf_appendcstr(lockbuf, key);
> + svn_stringbuf_appendbytes(lockbuf, key, klen);
> svn_stringbuf_appendcstr(lockbuf, SVN_LOCK_PATH_CLOSE);
> svn_stringbuf_appendcstr(lockbuf, SVN_LOCK_TOKEN);
> svn_stringbuf_appendcstr(lockbuf, val);

Okay, I see what's going on. We can't use a standard loop pool,
because we need all the data for a *second* loop, after the first loop
ends. And the second loop doesn't need a pool, since it just puts
together the stringbuf.

But, as long as you're using tmppool like this, why not use it in the
calls to apr_hash_first() as well? If we're going to clear out the
memory we used, we might as clear as much of it as possible.

> @@ -632,6 +645,8 @@
> #undef SVN_LOCK_TOKEN_CLOSE_LEN
>
> *body = lockbuf;
> +
> + svn_pool_destroy(tmppool);
> return SVN_NO_ERROR;
> }

-Karl

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri Jul 1 20:59:17 2005

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