On Mon, Jan 9, 2012 at 10:16 AM, Paul Burba <ptbu...@gmail.com> wrote:
> On Thu, Jan 5, 2012 at 2:37 PM, Stefan Küng <tortoise...@gmail.com> wrote:
>> Hi,
>>
>> From a crash report dump sent for TSVN for an update the attached stack
>> trace happened.
>>
>> libsvn_wc\props.c, svn_wc__merge_props()
>>      to_val = incoming_change->value
>>        ? svn_string_dup(incoming_change->value, result_pool) : NULL;
>> ....
>>      if (! from_val)  /* adding a new property */
>>        SVN_ERR(apply_single_prop_add(state, &conflict_remains,
>>                                      db, local_abspath,
>>                                      left_version, right_version,
>>                                      is_dir, actual_props,
>>                                      propname, base_val, to_val,
>>                                      conflict_func, conflict_baton,
>>                                      dry_run, result_pool, iterpool));
>> and then in apply_single_prop_add():
>> ...
>>      if (svn_string_compare(working_val, new_val))
>> crashes, because new_val is NULL.
>>
>> the property is "svn:mergeinfo".
>
>
> Hi Stefan,
>
> I saw 'mergeinfo' so took a quick look (happily it has nothing to do
> with mergeinfo per se, any property will do ;-)
>
>> Could this happen if someone manually removes the svn:mergeinfo property and
>> then the next update (from another working copy) gets the to_val as NULL?
>
> I'm not sure if this is what you mean, but I see one way to replicate
> this problem: Create a file external mapping to a file with some
> arbitrary property.  Remap the same external to a file without that
> property.  Boom.
>
> I filed an issue (issue #4093) which gives the full replication
> recipe.  I also added a regression test in r1228340.

Hi Bert,

I traced this regression back to your change in r1124782:

> Modified: subversion/trunk/subversion/libsvn_wc/externals.c
> URL: 
> http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/externals.c?rev=1124782&r1=1124781&r2=1124782&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/libsvn_wc/externals.c (original)
> +++ subversion/trunk/subversion/libsvn_wc/externals.c Thu May 19 13:53:20 2011
.
<snip>
.
> @@ -607,41 +607,17 @@ close_file(void *file_baton,
>     svn_skel_t *all_work_items = NULL;
>     svn_skel_t *work_item;
>     apr_hash_t *base_props = NULL;

base_props set to null...

>     apr_hash_t *actual_props = NULL;
>     apr_hash_t *new_pristine_props = NULL;
>     apr_hash_t *new_actual_props = NULL;
>     apr_hash_t *new_dav_props = NULL;
>     const svn_checksum_t *new_checksum = NULL;
>     const svn_checksum_t *original_checksum = NULL;
> -    svn_revnum_t changed_rev = SVN_INVALID_REVNUM;
> -    apr_time_t changed_date = 0;
> -    const char *changed_author = NULL;
> +
>     svn_boolean_t added = !SVN_IS_VALID_REVNUM(eb->original_revision);
>     const char *repos_relpath = svn_uri_is_child(eb->repos_root_url,
>                                                       eb->url, pool);
>
>     if (! added)
>       {
> -        svn_boolean_t had_props;
> -        svn_boolean_t props_mod;
> +        new_checksum = eb->original_checksum;
>
> -        SVN_ERR(svn_wc__db_external_read(NULL, NULL, NULL, NULL, NULL, NULL,
> -                                         &changed_rev, &changed_date,
> -                                         &changed_author, &original_checksum,
> -                                         NULL, NULL, NULL, NULL, NULL, NULL,
> -                                         NULL, NULL, NULL, &had_props,
> -                                         &props_mod,
> -                                         eb->db, eb->local_abspath,
> -                                         eb->wri_abspath,
> -                                         pool, pool));
> -
> -        new_checksum = original_checksum;
> -
> -        if (had_props)
> -          SVN_ERR(svn_wc__db_external_read_pristine_props(&base_props, 
> eb->db,
> -                                                          eb->local_abspath,
> -                                                          eb->wri_abspath,
> -                                                          pool, pool));

but we no longer populate base_props...

> -        if (props_mod)
> -          SVN_ERR(svn_wc__db_external_read_props(&actual_props, eb->db,
> -                                                 eb->local_abspath,
> -                                                 eb->wri_abspath,
> -                                                 pool, pool));
> +        SVN_ERR(svn_wc__db_base_get_props(&actual_props, eb->db,
> +                                          eb->local_abspath, pool, pool));
>       }
>
>     if (!base_props)
>       base_props = apr_hash_make(pool);

So base_props is unconditionally an empty hash.  Which causes the
segfault when close_file calls svn_wc__merge_props with an empty hash
as the PRISTINE_PROPS argument.  svn_wc__merge_props has a prop
deletion, but the empty hash makes it think it has a prop addition:

[[[
svn_error_t *
svn_wc__merge_props(svn_skel_t **work_items,
                    svn_wc_notify_state_t *state,
                    apr_hash_t **new_pristine_props,
                    apr_hash_t **new_actual_props,
                    svn_wc__db_t *db,
                    const char *local_abspath,
                    svn_kind_t kind,
                    const svn_wc_conflict_version_t *left_version,
                    const svn_wc_conflict_version_t *right_version,
                    apr_hash_t *server_baseprops,
                    apr_hash_t *pristine_props,
                    apr_hash_t *actual_props,
                    const apr_array_header_t *propchanges,
                    svn_boolean_t base_merge,
                    svn_boolean_t dry_run,
                    svn_wc_conflict_resolver_func2_t conflict_func,
                    void *conflict_baton,
                    svn_cancel_func_t cancel_func,
                    void *cancel_baton,
                    apr_pool_t *result_pool,
                    apr_pool_t *scratch_pool)
{

<snip>

  if (!server_baseprops)
    server_baseprops = pristine_props;

<snip>

  /* Looping over the array of incoming propchanges we want to apply: */
  iterpool = svn_pool_create(scratch_pool);
  for (i = 0; i < propchanges->nelts; i++)
    {

<snip>

      to_val = incoming_change->value
        ? svn_string_dup(incoming_change->value, result_pool) : NULL;
      from_val = apr_hash_get(server_baseprops, propname, APR_HASH_KEY_STRING);
      base_val = apr_hash_get(pristine_props, propname, APR_HASH_KEY_STRING);

<snip>

      if (! from_val)  /* adding a new property */
        SVN_ERR(apply_single_prop_add(state, &conflict_remains,
                                      db, local_abspath,
                                      left_version, right_version,
                                      is_dir, actual_props,
                                      propname, base_val, to_val,
###                                                                 ^^^^
###    This is obviously going to blow up since to_val is null!

                                      conflict_func, conflict_baton,
                                      dry_run, result_pool, iterpool));
]]]

So it seems we need to put
subversion/libsvn_wc/wc_db.c:svn_wc__db_external_read_pristine_props()
back.  Does that seem right to you, or is there a better way?

Paul

Reply via email to