[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: Eric Gillespie <epg_at_pretzelnet.org>
Date: Thu, 08 May 2008 22:29:37 -0700

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:

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
Received on 2008-05-09 07:29:51 CEST

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