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

Re: ra-serf bug

From: Karl Fogel <kfogel_at_red-bean.com>
Date: Fri, 09 May 2008 02:04:51 -0400

Eric Gillespie <epg_at_pretzelnet.org> writes:
> Got another one for you: svn_ra_stat is supposed to return NULL
> for the dirent for paths that do not exist; local/svn/neon do,
> but serf just returns a bogus one:

Just looking into this briefly between beer and bed (no, really):

Would a non-existent path be indicated by a particular value in
prop_ctx->status_code after svn_ra_serf__wait_for_props() is done? I'm
talking about in serf.c:fetch_path_props(). The call to that function
in svn_ra_serf__stat() seems like the only chance we'd have to discover
the path does not exist.

Also, by the by: very few calls to svn_ra_serf__deliver_props() wrap it
in an SVN_ERR() check (though two calls do, oddly enough). It's just a
style issue right now, as that function in practice only returns
SVN_NO_ERROR anyway, but it does seem like the error checks ought to be
there, in case the function ever gets more sophisticated.

-Karl

> 0 svn% ./serfbug2 svn://svn/r 84
> dirent NULL
> # neon
> 0 svn% ./serfbug2 https://svn/r 84
> dirent NULL
> # serf
> 0 svn% ./serfbug2 https://svn/r 84
> dirent not NULL:
> kind 0
> size 0
> has_props 0
> created_rev 0
> time 0
> last_author (null)
> *** glibc detected *** double free or corruption (!prev):
> 0x08098f18 ***
> zsh: abort (core dumped) ./serfbug2 https://svn/r 84
>
>
> #include <errno.h>
> #include <stdio.h>
> #include <stdlib.h>
>
> /* for svn initialization */
> #include <apr_errno.h>
> #include <apr_general.h>
> #include <apr_hash.h>
> #include <apr_strings.h>
> #include <svn_auth.h>
> #include <svn_cmdline.h>
> #include <svn_config.h>
> #include <svn_dso.h>
> #include <svn_nls.h>
> #include <svn_pools.h>
> /* for svn_ra_stat */
> #include <svn_error.h>
> #include <svn_io.h>
> #include <svn_path.h>
> #include <svn_ra.h>
> #include <svn_types.h>
>
> static svn_error_t *
> open_tmp_file(apr_file_t **fp, void *baton, apr_pool_t *pool)
> {
> const char *base_fn, *base_path, *fn;
> SVN_ERR(svn_io_temp_dir(&base_fn, pool));
> base_path = svn_path_join(base_fn, "foo", pool);
> return svn_io_open_unique_file2(fp, &fn, base_path, ".tmp",
> svn_io_file_del_on_close, pool);
> }
>
> #define ERR(expr) \
> do { \
> svn_error_t *err = (expr); \
> if (err) { \
> fprintf(stderr, "%s:%ld: (apr_err=%d)\nfoo: %s\n", \
> err->file, err->line, err->apr_err, \
> err->message); \
> return 1; \
> } \
> } while (0)
>
> int
> main(int argc, char *argv[])
> {
> apr_pool_t *pool;
> apr_hash_t *cfg_hash;
> long revision;
> svn_ra_callbacks2_t *callbacks;
>
> if (argc < 3 || (argv[1] && argv[1][0] == '-')) {
> fputs("usage: foo URL REVISION\n", stderr);
> if (argv[1] && argv[1][0] == '-') {
> return 0;
> }
> return 2;
> }
>
> errno = 0;
> revision = strtol(argv[2], NULL, 10);
> if (errno != 0) {
> fprintf(stderr, "foo: strtol(%s): ", argv[2]);
> perror("");
> return 3;
> }
>
> /* Initialize svn. */
> {
> apr_status_t apr_status;
> char buf[1024];
>
> if ((apr_status = apr_initialize()) != APR_SUCCESS) {
> apr_strerror(apr_status, buf, sizeof(buf) - 1);
> fprintf(stderr, "foo: cannot initialize APR: %s\n", buf);
> return 1;
> }
>
> svn_dso_initialize();
>
> if (atexit(apr_terminate) != 0) {
> fputs("atexit registration failed\n", stderr);
> return 1;
> }
>
> pool = svn_pool_create(NULL);
> svn_utf_initialize(pool);
> ERR(svn_nls_init());
>
> ERR(svn_config_get_config(&cfg_hash, NULL, pool));
>
> ERR(svn_ra_initialize(pool));
>
> ERR(svn_ra_create_callbacks(&callbacks, pool));
> callbacks->open_tmp_file = open_tmp_file;
> ERR(svn_cmdline_setup_auth_baton(&(callbacks->auth_baton),
> TRUE, /* non_interactive */
> NULL, /* username */
> NULL, /* password */
> NULL, /* config_dir */
> FALSE, /* no_auth_cache */
> apr_hash_get(cfg_hash,
> SVN_CONFIG_CATEGORY_CONFIG,
> APR_HASH_KEY_STRING),
> NULL, /* cancel_func */
> NULL, /* cancel_baton */
> pool));
> }
>
> /* Try something simple enough. */
> {
> svn_ra_session_t *ra;
> svn_revnum_t head;
> svn_dirent_t *dirent;
> ERR(svn_ra_open2(&ra, argv[1], callbacks, NULL, cfg_hash, pool));
> ERR(svn_ra_get_latest_revnum(ra, &head, pool));
> ERR(svn_ra_stat(ra, "notexist", head, &dirent, pool));
> if (dirent == NULL)
> puts("dirent NULL");
> else
> {
> printf("dirent not NULL:\n"
> " kind %d\n"
> " size %lld\n"
> " has_props %d\n"
> " created_rev %lld\n"
> " time %lld\n"
> " last_author %s\n",
> dirent->kind, (long long)dirent->size, dirent->has_props,
> (long long)dirent->created_rev, (long long)dirent->time,
> dirent->last_author);
> }
> }
>
> return 0;
> }
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_subversion.tigris.org
> For additional commands, e-mail: dev-help_at_subversion.tigris.org

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe_at_subversion.tigris.org
For additional commands, e-mail: dev-help_at_subversion.tigris.org
Received on 2008-05-09 08:05:08 CEST

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