Author: julianfoad
Date: Mon Dec 30 15:42:17 2019
New Revision: 1872118
URL: http://svn.apache.org/viewvc?rev=1872118&view=rev
Log:
Avoid aborting on assertion failure in the area of mergeinfo calculations.
Instead, raise a catchable assertion error.
If an error occurs in svn_rangelist_merge2(), produce a more detailed error
message to aid in debugging.
Introduce and use 'svn_sort__array_insert2()' which checks its inputs. The
old version of this function was aborting on out-of-range inputs. Introduce
and use 'svn_sort__array_delete2()' likewise, as similar issues may show up
here too. The old version of this function was ignoring calls with
out-of-range inputs. The old versions of both functions are still in use
elsewhere in the Subversion libraries.
For issue #4840, "Merge assertion failure in svn_sort__array_insert".
* subversion/include/private/svn_sorts_private.h,
subversion/libsvn_subr/sorts.c
(svn_sort__array_insert2,
svn_sort__array_delete2): New.
* subversion/libsvn_client/merge.c
(slice_remaining_ranges,
insert_child_to_merge): Allow returning an error.
Everywhere: use svn_sort__array_insert2() and svn_sort__array_delete2().
* subversion/libsvn_subr/mergeinfo.c
(adjust_remaining_ranges): Allow returning an error.
(dual_dump): Replace this old debug helper...
(rangelist_to_string_debug): ... with this new one.
(svn_rangelist_merge2): Extract the body of this function into a local
'rangelist_merge2', leaving the original as an error-checking
wrapper. If an error occurs, report its inputs.
(rangelist_is_sorted): New.
Everywhere: use svn_sort__array_insert2() and svn_sort__array_delete2().
* subversion/tests/libsvn_subr/mergeinfo-test.c
(test_rangelist_merge_random_non_validated_inputs): Expect assertion
failures; ignore them.
(test_funcs): Expect that test to pass now.
Modified:
subversion/trunk/subversion/include/private/svn_sorts_private.h
subversion/trunk/subversion/libsvn_client/merge.c
subversion/trunk/subversion/libsvn_subr/mergeinfo.c
subversion/trunk/subversion/libsvn_subr/sorts.c
subversion/trunk/subversion/tests/libsvn_subr/mergeinfo-test.c
Modified: subversion/trunk/subversion/include/private/svn_sorts_private.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_sorts_private.h?rev=1872118&r1=1872117&r2=1872118&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_sorts_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_sorts_private.h Mon Dec 30
15:42:17 2019
@@ -127,6 +127,16 @@ svn_sort__array_insert(apr_array_header_
const void *new_element,
int insert_index);
+/* Like svn_sort__array_insert() but raise an error if @a insert_index
+ * is less than 0 or greater than the length of the array.
+ *
+ * @note Private. For use by Subversion's own code only.
+ */
+svn_error_t *
+svn_sort__array_insert2(apr_array_header_t *array,
+ const void *new_element,
+ int insert_index);
+
/* Remove @a elements_to_delete elements starting at @a delete_index from the
* array @a arr. If @a delete_index is not a valid element of @a arr,
@@ -141,6 +151,16 @@ svn_sort__array_delete(apr_array_header_
int delete_index,
int elements_to_delete);
+/* Like svn_sort__array_delete() but raise an error if attempting
+ * to delete a range of elements that goes out of bounds of the array.
+ *
+ * @note Private. For use by Subversion's own code only.
+ */
+svn_error_t *
+svn_sort__array_delete2(apr_array_header_t *arr,
+ int delete_index,
+ int elements_to_delete);
+
/* Reverse the order of elements in @a array, in place.
*
* @note Private. For use by Subversion's own code only.
Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1872118&r1=1872117&r2=1872118&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Mon Dec 30 15:42:17 2019
@@ -5975,7 +5975,7 @@ get_most_inclusive_rev(const apr_array_h
remaining_ranges is inclusive of END_REV, Slice the first range in
to two at END_REV. All the allocations are persistent and allocated
from POOL. */
-static void
+static svn_error_t *
slice_remaining_ranges(apr_array_header_t *children_with_mergeinfo,
svn_boolean_t is_rollback, svn_revnum_t end_rev,
apr_pool_t *pool)
@@ -6005,10 +6005,12 @@ slice_remaining_ranges(apr_array_header_
split_range2->start = end_rev;
APR_ARRAY_IDX(child->remaining_ranges, 0,
svn_merge_range_t *) = split_range1;
- svn_sort__array_insert(child->remaining_ranges, &split_range2,
1);
+ SVN_ERR(svn_sort__array_insert2(child->remaining_ranges,
+ &split_range2, 1));
}
}
}
+ return SVN_NO_ERROR;
}
/* Helper for do_directory_merge().
@@ -6130,7 +6132,7 @@ get_child_with_mergeinfo(const apr_array
out of order and then sort afterwards. (One caller is doing a qsort
after calling this anyway.)
*/
-static void
+static svn_error_t *
insert_child_to_merge(apr_array_header_t *children_with_mergeinfo,
const svn_client__merge_path_t *insert_element,
apr_pool_t *pool)
@@ -6144,7 +6146,9 @@ insert_child_to_merge(apr_array_header_t
compare_merge_path_t_as_paths);
new_element = svn_client__merge_path_dup(insert_element, pool);
- svn_sort__array_insert(children_with_mergeinfo, &new_element, insert_index);
+ SVN_ERR(svn_sort__array_insert2(children_with_mergeinfo,
+ &new_element, insert_index));
+ return SVN_NO_ERROR;
}
/* Helper for get_mergeinfo_paths().
@@ -6205,7 +6209,7 @@ insert_parent_and_sibs_of_sw_absent_del_
parent->missing_child = child->absent;
parent->switched_child = child->switched;
/* Insert PARENT into CHILDREN_WITH_MERGEINFO. */
- insert_child_to_merge(children_with_mergeinfo, parent, pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo, parent, pool));
/* Increment for loop index so we don't process the inserted element. */
(*curr_index)++;
} /*(parent == NULL) */
@@ -6242,8 +6246,8 @@ insert_parent_and_sibs_of_sw_absent_del_
sibling_of_missing = svn_client__merge_path_create(child_abspath,
pool);
- insert_child_to_merge(children_with_mergeinfo, sibling_of_missing,
- pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ sibling_of_missing, pool));
}
}
@@ -6584,8 +6588,8 @@ get_mergeinfo_paths(apr_array_header_t *
svn_client__merge_path_t *switched_child =
svn_client__merge_path_create(wc_path, result_pool);
switched_child->switched = TRUE;
- insert_child_to_merge(children_with_mergeinfo, switched_child,
- result_pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ switched_child, result_pool));
}
}
}
@@ -6637,8 +6641,8 @@ get_mergeinfo_paths(apr_array_header_t *
}
if (new_shallow_child)
- insert_child_to_merge(children_with_mergeinfo, shallow_child,
- result_pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ shallow_child, result_pool));
}
}
@@ -6667,8 +6671,8 @@ get_mergeinfo_paths(apr_array_header_t *
svn_client__merge_path_t *absent_child =
svn_client__merge_path_create(wc_path, result_pool);
absent_child->absent = TRUE;
- insert_child_to_merge(children_with_mergeinfo, absent_child,
- result_pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ absent_child, result_pool));
}
}
}
@@ -6681,8 +6685,8 @@ get_mergeinfo_paths(apr_array_header_t *
svn_client__merge_path_t *target_child =
svn_client__merge_path_create(target->abspath,
result_pool);
- insert_child_to_merge(children_with_mergeinfo, target_child,
- result_pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo, target_child,
+ result_pool));
}
/* Case 8: Path is an immediate *directory* child of
@@ -6725,8 +6729,8 @@ get_mergeinfo_paths(apr_array_header_t *
&& depth == svn_depth_immediates)
immediate_child->immediate_child_dir = TRUE;
- insert_child_to_merge(children_with_mergeinfo,
- immediate_child, result_pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ immediate_child, result_pool));
}
}
}
@@ -6818,9 +6822,9 @@ get_mergeinfo_paths(apr_array_header_t *
child_of_noninheritable =
svn_client__merge_path_create(child_abspath, result_pool);
child_of_noninheritable->child_of_noninheritable = TRUE;
- insert_child_to_merge(children_with_mergeinfo,
- child_of_noninheritable,
- result_pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ child_of_noninheritable,
+ result_pool));
if (!dry_run && same_repos)
{
svn_mergeinfo_t mergeinfo;
@@ -7244,7 +7248,7 @@ normalize_merge_sources_internal(apr_arr
new_segment->path = original_repos_relpath;
new_segment->range_start = original_revision;
new_segment->range_end = original_revision;
- svn_sort__array_insert(segments, &new_segment, 0);
+ SVN_ERR(svn_sort__array_insert2(segments, &new_segment, 0));
}
}
}
@@ -7978,7 +7982,8 @@ process_children_with_new_mergeinfo(merg
/* Set the path's remaining_ranges equal to its parent's. */
new_child->remaining_ranges = svn_rangelist_dup(
parent->remaining_ranges, pool);
- insert_child_to_merge(children_with_mergeinfo, new_child, pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ new_child, pool));
}
}
}
@@ -9510,8 +9515,9 @@ do_mergeinfo_aware_dir_merge(svn_mergein
svn_pool_clear(iterpool);
- slice_remaining_ranges(children_with_mergeinfo,
- is_rollback, end_rev, scratch_pool);
+ SVN_ERR(slice_remaining_ranges(children_with_mergeinfo,
+ is_rollback, end_rev,
+ scratch_pool));
/* Reset variables that must be reset for every drive */
merge_b->notify_begin.last_abspath = NULL;
Modified: subversion/trunk/subversion/libsvn_subr/mergeinfo.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/mergeinfo.c?rev=1872118&r1=1872117&r2=1872118&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_subr/mergeinfo.c Mon Dec 30 15:42:17 2019
@@ -44,8 +44,9 @@
/* Return TRUE iff the forward revision range FIRST wholly contains the
* forward revision range SECOND and (if CONSIDER_INHERITANCE is TRUE) has
* the same inheritability. */
-static svn_boolean_t
-range_contains(const svn_merge_range_t *first, const svn_merge_range_t *second,
+static svn_error_t *
+range_contains(svn_boolean_t *result,
+ const svn_merge_range_t *first, const svn_merge_range_t *second,
svn_boolean_t consider_inheritance);
@@ -834,7 +835,7 @@ svn_mergeinfo_parse(svn_mergeinfo_t *mer
element is equal to the start rev of the younger element.
Any new elements inserted into RANGELIST are allocated in RESULT_POOL.*/
-static void
+static svn_error_t *
adjust_remaining_ranges(svn_rangelist_t *rangelist,
int *range_index,
apr_pool_t *result_pool)
@@ -845,7 +846,7 @@ adjust_remaining_ranges(svn_rangelist_t
svn_merge_range_t *modified_range;
if (*range_index >= rangelist->nelts)
- return;
+ return SVN_NO_ERROR;
starting_index = *range_index + 1;
modified_range = APR_ARRAY_IDX(rangelist, *range_index, svn_merge_range_t *);
@@ -919,10 +920,11 @@ adjust_remaining_ranges(svn_rangelist_t
new_modified_range->inheritable = FALSE;
modified_range->end = next_range->start;
(*range_index) += 2 + elements_to_delete;
- svn_sort__array_insert(rangelist, &new_modified_range,
- *range_index);
+ SVN_ERR(svn_sort__array_insert2(rangelist, &new_modified_range,
+ *range_index));
/* Recurse with the new range. */
- adjust_remaining_ranges(rangelist, range_index, result_pool);
+ SVN_ERR(adjust_remaining_ranges(rangelist, range_index,
+ result_pool));
break;
}
}
@@ -975,31 +977,35 @@ adjust_remaining_ranges(svn_rangelist_t
}
if (elements_to_delete)
- svn_sort__array_delete(rangelist, starting_index, elements_to_delete);
+ SVN_ERR(svn_sort__array_delete2(rangelist, starting_index,
+ elements_to_delete));
+
+ return SVN_NO_ERROR;
}
-#if 0 /* Temporary debug helper code */
-static svn_error_t *
-dual_dump(const char *prefix,
- const svn_rangelist_t *rangelist,
- const svn_rangelist_t *changes,
- apr_pool_t *scratch_pool)
+static const char *
+rangelist_to_string_debug(const svn_rangelist_t *rl,
+ apr_pool_t *pool)
{
- svn_string_t *rls, *chg;
-
- SVN_ERR(svn_rangelist_to_string(&rls, rangelist, scratch_pool));
- SVN_ERR(svn_rangelist_to_string(&chg, changes, scratch_pool));
+ svn_string_t *rls;
+ svn_error_t *err;
- SVN_DBG(("%s: %s / %s", prefix, rls->data, chg->data));
- return SVN_NO_ERROR;
+ err = svn_rangelist_to_string(&rls, rl, pool);
+ if (err)
+ {
+ char *s = apr_psprintf(pool, _("<bad rangelist [%d ranges]: %s>"),
+ rl->nelts, err->message);
+ svn_error_clear(err);
+ return s;
+ }
+ return rls->data;
}
-#endif
-svn_error_t *
-svn_rangelist_merge2(svn_rangelist_t *rangelist,
- const svn_rangelist_t *chg,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+static svn_error_t *
+rangelist_merge2(svn_rangelist_t *rangelist,
+ const svn_rangelist_t *chg,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_rangelist_t *changes;
int i = 0;
@@ -1016,6 +1022,7 @@ svn_rangelist_merge2(svn_rangelist_t *ra
svn_merge_range_t *range;
svn_merge_range_t *change =
APR_ARRAY_IDX(changes, j, svn_merge_range_t *);
+ svn_boolean_t change_contains_range, range_contains_change;
int res;
range = (i < rangelist->nelts)
@@ -1027,7 +1034,7 @@ svn_rangelist_merge2(svn_rangelist_t *ra
/* No overlap, nor adjoin, copy change to result range */
svn_merge_range_t *chg_copy = svn_merge_range_dup(change,
result_pool);
- svn_sort__array_insert(rangelist, &chg_copy, i++);
+ SVN_ERR(svn_sort__array_insert2(rangelist, &chg_copy, i++));
continue;
}
else if ((change->start > range->end)
@@ -1040,10 +1047,12 @@ svn_rangelist_merge2(svn_rangelist_t *ra
continue;
}
+ SVN_ERR(range_contains(&change_contains_range, change, range, FALSE));
+ SVN_ERR(range_contains(&range_contains_change, range, change, FALSE));
if (change->start < range->start
&& range->inheritable != change->inheritable
- && ! (change->inheritable && range_contains(change, range, FALSE))
- && ! (range->inheritable && range_contains(range, change, FALSE)))
+ && ! (change->inheritable && change_contains_range)
+ && ! (range->inheritable && range_contains_change))
{
/* Can't fold change into existing range.
Insert new range before range */
@@ -1057,7 +1066,7 @@ svn_rangelist_merge2(svn_rangelist_t *ra
else
range->start = change->end;
- svn_sort__array_insert(rangelist, &chg_copy, i++);
+ SVN_ERR(svn_sort__array_insert2(rangelist, &chg_copy, i++));
change->start = chg_copy->end;
if (change->start >= change->end)
@@ -1092,7 +1101,7 @@ svn_rangelist_merge2(svn_rangelist_t *ra
/* RANGE and CHANGE have the same inheritability so
RANGE expands to absord CHANGE. */
range->end = change->end;
- adjust_remaining_ranges(rangelist, &i, result_pool);
+ SVN_ERR(adjust_remaining_ranges(rangelist, &i, result_pool));
continue;
}
else
@@ -1132,7 +1141,8 @@ svn_rangelist_merge2(svn_rangelist_t *ra
svn_merge_range_dup(range, result_pool);
range_copy->end = change->start;
range->start = change->start;
- svn_sort__array_insert(rangelist, &range_copy, i++);
+ SVN_ERR(svn_sort__array_insert2(rangelist,
+ &range_copy, i++));
j--;
continue;
}
@@ -1181,7 +1191,8 @@ svn_rangelist_merge2(svn_rangelist_t *ra
/* ...but if RANGE is expanded ensure that we don't
violate any rangelist invariants. */
range->end = change->end;
- adjust_remaining_ranges(rangelist, &i, result_pool);
+ SVN_ERR(adjust_remaining_ranges(rangelist,
+ &i, result_pool));
}
continue;
}
@@ -1237,7 +1248,8 @@ svn_rangelist_merge2(svn_rangelist_t *ra
range->start = change->start;
range->end = change->end;
range->inheritable = TRUE;
- svn_sort__array_insert(rangelist, &range_copy, ++i);
+ SVN_ERR(svn_sort__array_insert2(rangelist,
+ &range_copy, ++i));
continue;
}
}
@@ -1255,7 +1267,8 @@ svn_rangelist_merge2(svn_rangelist_t *ra
range_copy->end = change->end;
range_copy->inheritable = TRUE;
range->start = change->end;
- svn_sort__array_insert(rangelist, &range_copy, i++);
+ SVN_ERR(svn_sort__array_insert2(rangelist,
+ &range_copy, i++));
continue;
}
}
@@ -1265,40 +1278,98 @@ svn_rangelist_merge2(svn_rangelist_t *ra
}
#ifdef SVN_DEBUG
- SVN_ERR_ASSERT(svn_rangelist__is_canonical(rangelist));
+ /*SVN_ERR_ASSERT(svn_rangelist__is_canonical(rangelist));*/
#endif
return SVN_NO_ERROR;
}
-/* Return TRUE iff the forward revision ranges FIRST and SECOND overlap and
- * (if CONSIDER_INHERITANCE is TRUE) have the same inheritability. */
static svn_boolean_t
-range_intersect(const svn_merge_range_t *first, const svn_merge_range_t
*second,
+rangelist_is_sorted(const svn_rangelist_t *rangelist)
+{
+ int i;
+
+ for (i = 1; i < rangelist->nelts; i++)
+ {
+ const svn_merge_range_t *lastrange
+ = APR_ARRAY_IDX(rangelist, i-1, svn_merge_range_t *);
+ const svn_merge_range_t *thisrange
+ = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
+
+ if (svn_sort_compare_ranges(&lastrange, &thisrange) > 0)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+svn_error_t *
+svn_rangelist_merge2(svn_rangelist_t *rangelist,
+ const svn_rangelist_t *chg,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_rangelist_t *rangelist_orig = svn_rangelist_dup(rangelist, scratch_pool);
+ svn_error_t *err;
+
+ SVN_ERR_ASSERT(rangelist_is_sorted(rangelist));
+ SVN_ERR_ASSERT(rangelist_is_sorted(chg));
+
+ err = svn_error_trace(rangelist_merge2(rangelist, chg, result_pool,
+ scratch_pool));
+ if (err)
+ {
+ err = svn_error_createf(SVN_ERR_ASSERTION_FAIL, err,
+ "svn_rangelist_merge2( %s / %s ): internal error",
+ rangelist_to_string_debug(rangelist_orig, scratch_pool),
+ rangelist_to_string_debug(chg, scratch_pool));
+ }
+ else if (! svn_rangelist__is_canonical(rangelist)
+ && svn_rangelist__is_canonical(rangelist_orig)
+ && svn_rangelist__is_canonical(chg))
+ {
+ err = svn_error_createf(SVN_ERR_ASSERTION_FAIL, NULL,
+ "svn_rangelist_merge2( %s / %s ): canonical inputs, "
+ "non-canonical result ( %s )",
+ rangelist_to_string_debug(rangelist_orig, scratch_pool),
+ rangelist_to_string_debug(chg, scratch_pool),
+ rangelist_to_string_debug(rangelist, scratch_pool));
+ }
+
+ return err;
+}
+
+/* Set *RESULT to TRUE iff the forward revision ranges FIRST and SECOND overlap
+ * and (if CONSIDER_INHERITANCE is TRUE) have the same inheritability. */
+static svn_error_t *
+range_intersect(svn_boolean_t *result,
+ const svn_merge_range_t *first, const svn_merge_range_t
*second,
svn_boolean_t consider_inheritance)
{
- SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(first));
- SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(second));
+ SVN_ERR_ASSERT(IS_VALID_FORWARD_RANGE(first));
+ SVN_ERR_ASSERT(IS_VALID_FORWARD_RANGE(second));
- return (first->start + 1 <= second->end)
- && (second->start + 1 <= first->end)
- && (!consider_inheritance
- || (!(first->inheritable) == !(second->inheritable)));
+ *result = (first->start + 1 <= second->end)
+ && (second->start + 1 <= first->end)
+ && (!consider_inheritance
+ || (!(first->inheritable) == !(second->inheritable)));
+ return SVN_NO_ERROR;
}
-/* Return TRUE iff the forward revision range FIRST wholly contains the
+/* Set *RESULT to TRUE iff the forward revision range FIRST wholly contains the
* forward revision range SECOND and (if CONSIDER_INHERITANCE is TRUE) has
* the same inheritability. */
-static svn_boolean_t
-range_contains(const svn_merge_range_t *first, const svn_merge_range_t *second,
+static svn_error_t *
+range_contains(svn_boolean_t *result,
+ const svn_merge_range_t *first, const svn_merge_range_t *second,
svn_boolean_t consider_inheritance)
{
- SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(first));
- SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(second));
+ SVN_ERR_ASSERT(IS_VALID_FORWARD_RANGE(first));
+ SVN_ERR_ASSERT(IS_VALID_FORWARD_RANGE(second));
- return (first->start <= second->start) && (second->end <= first->end)
- && (!consider_inheritance
- || (!(first->inheritable) == !(second->inheritable)));
+ *result = (first->start <= second->start) && (second->end <= first->end)
+ && (!consider_inheritance
+ || (!(first->inheritable) == !(second->inheritable)));
+ return SVN_NO_ERROR;
}
/* Swap start and end fields of RANGE. */
@@ -1417,6 +1488,7 @@ rangelist_intersect_or_remove(svn_rangel
while (i1 < rangelist1->nelts && i2 < rangelist2->nelts)
{
svn_merge_range_t *elt1, *elt2;
+ svn_boolean_t elt1_contains_elt2, elt1_intersects_elt2;
elt1 = APR_ARRAY_IDX(rangelist1, i1, svn_merge_range_t *);
@@ -1432,6 +1504,10 @@ rangelist_intersect_or_remove(svn_rangel
elt2 = &working_elt2;
+ SVN_ERR(range_contains(&elt1_contains_elt2,
+ elt1, elt2, consider_inheritance));
+ SVN_ERR(range_intersect(&elt1_intersects_elt2,
+ elt1, elt2, consider_inheritance));
/* If the rangelist2 range is contained completely in the
rangelist1, we increment the rangelist2.
If the ranges intersect, and match exactly, we increment both
@@ -1440,7 +1516,7 @@ rangelist_intersect_or_remove(svn_rangel
the removal of rangelist1 from rangelist2, and possibly change
the rangelist2 to the remaining portion of the right part of
the removal, to test against. */
- if (range_contains(elt1, elt2, consider_inheritance))
+ if (elt1_contains_elt2)
{
if (!do_remove)
{
@@ -1461,7 +1537,7 @@ rangelist_intersect_or_remove(svn_rangel
if (elt2->start == elt1->start && elt2->end == elt1->end)
i1++;
}
- else if (range_intersect(elt1, elt2, consider_inheritance))
+ else if (elt1_intersects_elt2)
{
if (elt2->start < elt1->start)
{
Modified: subversion/trunk/subversion/libsvn_subr/sorts.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/sorts.c?rev=1872118&r1=1872117&r2=1872118&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/sorts.c (original)
+++ subversion/trunk/subversion/libsvn_subr/sorts.c Mon Dec 30 15:42:17 2019
@@ -34,6 +34,8 @@
#include "svn_error.h"
#include "private/svn_sorts_private.h"
+#include "svn_private_config.h"
+
/*** svn_sort__hash() ***/
@@ -324,6 +326,20 @@ svn_sort__array_insert(apr_array_header_
memcpy(new_position, new_element, array->elt_size);
}
+svn_error_t *
+svn_sort__array_insert2(apr_array_header_t *array,
+ const void *new_element,
+ int insert_index)
+{
+ if (insert_index < 0 || insert_index > array->nelts)
+ return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+ _("svn_sort__array_insert2: Attempted insert "
+ "at index %d in array length %d"),
+ insert_index, array->nelts);
+ svn_sort__array_insert(array, new_element, insert_index);
+ return SVN_NO_ERROR;
+}
+
void
svn_sort__array_delete(apr_array_header_t *arr,
int delete_index,
@@ -349,6 +365,23 @@ svn_sort__array_delete(apr_array_header_
}
}
+svn_error_t *
+svn_sort__array_delete2(apr_array_header_t *arr,
+ int delete_index,
+ int elements_to_delete)
+{
+ if (!(delete_index >= 0
+ && delete_index < arr->nelts
+ && elements_to_delete > 0
+ && (arr->nelts - delete_index) >= elements_to_delete))
+ return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+ _("svn_sort__array_delete2: Attempted delete "
+ "at index %d, %d elements, in array length %d"),
+ delete_index, elements_to_delete, arr->nelts);
+ svn_sort__array_delete(arr, delete_index, elements_to_delete);
+ return SVN_NO_ERROR;
+}
+
void
svn_sort__array_reverse(apr_array_header_t *array,
apr_pool_t *scratch_pool)
Modified: subversion/trunk/subversion/tests/libsvn_subr/mergeinfo-test.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_subr/mergeinfo-test.c?rev=1872118&r1=1872117&r2=1872118&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_subr/mergeinfo-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_subr/mergeinfo-test.c Mon Dec 30
15:42:17 2019
@@ -2118,11 +2118,15 @@ test_rangelist_merge_random_semi_c_input
return SVN_NO_ERROR;
}
+/* Test svn_rangelist_merge2() with random non-validated inputs.
+ *
+ * Unlike the tests with valid inputs, this test expects many assertion
+ * failures. We don't care about those. All we care about is that it does
+ * not crash. */
static svn_error_t *
test_rangelist_merge_random_non_validated_inputs(apr_pool_t *pool)
{
apr_pool_t *iterpool = svn_pool_create(pool);
- svn_boolean_t pass = TRUE;
int ix, iy;
for (ix = 0; ix < 300; ix++)
@@ -2143,18 +2147,11 @@ test_rangelist_merge_random_non_validate
err = rangelist_merge_random_inputs(rlx, rly, iterpool);
if (err)
{
- printf("testcase FAIL: %s / %s\n",
- rangelist_to_string(rlx, iterpool),
- rangelist_to_string(rly, iterpool));
- svn_handle_error(err, stdout, FALSE);
svn_error_clear(err);
- pass = FALSE;
}
}
}
- if (!pass)
- return svn_error_create(SVN_ERR_TEST_FAILED, NULL, NULL);
return SVN_NO_ERROR;
}
@@ -2211,8 +2208,8 @@ static struct svn_test_descriptor_t test
"test rangelist merge random canonical inputs"),
SVN_TEST_XFAIL2(test_rangelist_merge_random_semi_c_inputs,
"test rangelist merge random semi-c inputs"),
- SVN_TEST_XFAIL2(test_rangelist_merge_random_non_validated_inputs,
- "test rangelist merge random non-validated inputs"),
+ SVN_TEST_PASS2(test_rangelist_merge_random_non_validated_inputs,
+ "test rangelist merge random non-validated inputs"),
SVN_TEST_NULL
};