Package: libserf-1-1
Version: 1.3.9-5
Severity: normal
Tags: patch
User: ubuntu-de...@lists.ubuntu.com
Usertags: origin-ubuntu bionic ubuntu-patch

bzr-svn segfaults due to a list management bug in
serf_bucket_aggregate_append.  This is unfortunately hard to observe
because bzr-svn isn't in Debian any more and various things around it
have bitrotted a bit, but we still rely on it for Subversion imports in
Launchpad, and it is possible to set up a reproduction environment in
unstable with a bit of hacking.

First, install bzr from unstable.

Next, grab commit 01cfebd2e32b940ddfa55373640907b39da8413f of subvertpy
(https://github.com/jelmer/subvertpy), which makes a bit of API that
bzr-svn needs available with modern versions of Subversion, and build it
("sudo apt build-dep python-subvertpy && make").

Next, grab bzr-svn ("bzr branch lp:bzr-svn").  It's a bit broken with
modern versions of libsvn; I had to apply the following hacky patch,
which is almost certainly not quite right in some way (which is why I
haven't submitted it yet), but it'll do for the purposes of this bug:

=== modified file 'logwalker.py'
--- logwalker.py        2012-03-08 17:52:35 +0000
+++ logwalker.py        2018-03-21 08:25:52 +0000
@@ -206,7 +206,8 @@ class CachingLogWalkerUpdater(object):
         self.count += 1
         self.pb.update('fetching svn revision info', self.count, self.total)
         self.logwalker.cache.insert_paths(revision, orig_paths,
-            revprops, self.all_revprops)
+            {key.encode("UTF-8"): value for key, value in revprops.items()},
+            self.all_revprops)
         self.logwalker.saved_maxrevnum = max(revision,
             self.logwalker.saved_maxrevnum)
         if self.logwalker.saved_minrevnum is None:

=== modified file 'transport.py'
--- transport.py        2012-03-08 17:52:35 +0000
+++ transport.py        2018-03-21 08:21:59 +0000
@@ -440,7 +440,7 @@ class SvnRaTransport(Transport):
         if self._uuid is None:
             conn = self.get_any_connection()
             try:
-                return conn.get_uuid()
+                return conn.get_uuid().encode("UTF-8")
             finally:
                 self.add_connection(conn)
         return self._uuid
@@ -456,7 +456,7 @@ class SvnRaTransport(Transport):
         if self._repos_root is None:
             conn = self.get_any_connection()
             try:
-                self._repos_root = conn.get_repos_root()
+                self._repos_root = conn.get_repos_root().encode("UTF-8")
             finally:
                 self.add_connection(conn)
         return self._repos_root

Make ~/.bazaar/plugins/svn be a symlink to the bzr-svn branch.

Now try this branch operation, with PYTHONPATH adjusted to point to
wherever you cloned subvertpy:

  PYTHONPATH=/path/to/subvertpy bzr branch 
https://svn.code.sf.net/p/truckliststudio/svn/trunk truckliststudio

The fix is rather easier than describing the setup, since it was fixed
upstream some time ago:

  https://svn.apache.org/viewvc?view=revision&revision=1712790

diff -Nru serf-1.3.9/debian/changelog serf-1.3.9/debian/changelog
--- serf-1.3.9/debian/changelog 2018-02-05 23:28:07.000000000 +0000
+++ serf-1.3.9/debian/changelog 2018-03-20 12:41:54.000000000 +0000
@@ -1,3 +1,10 @@
+serf (1.3.9-5) UNRELEASED; urgency=medium
+
+  * Backport r1712790 from upstream to fix a segfault in
+    serf_bucket_aggregate_prepend when prepending a bucket to an empty list.
+
+ -- Colin Watson <cjwat...@ubuntu.com>  Tue, 20 Mar 2018 12:41:52 +0000
+
 serf (1.3.9-4) unstable; urgency=medium
 
   * Mark serf_debug_closed_conn as a public symbol, since svn has been using
diff -Nru 
serf-1.3.9/debian/patches/r1712790-serf_bucket_aggregate_prepend-empty-list 
serf-1.3.9/debian/patches/r1712790-serf_bucket_aggregate_prepend-empty-list
--- serf-1.3.9/debian/patches/r1712790-serf_bucket_aggregate_prepend-empty-list 
1970-01-01 01:00:00.000000000 +0100
+++ serf-1.3.9/debian/patches/r1712790-serf_bucket_aggregate_prepend-empty-list 
2017-05-16 14:32:26.000000000 +0100
@@ -0,0 +1,34 @@
+Description: Make serf_bucket_aggregate_prepend() behave properly when 
prepending a bucket to an empty list
+Origin: upstream, https://svn.apache.org/viewvc?view=revision&revision=1712790
+
+Index: b/buckets/aggregate_buckets.c
+===================================================================
+--- a/buckets/aggregate_buckets.c
++++ b/buckets/aggregate_buckets.c
+@@ -149,6 +149,8 @@
+     new_list->bucket = prepend_bucket;
+     new_list->next = ctx->list;
+ 
++    if (ctx->list == NULL)
++        ctx->last = new_list;
+     ctx->list = new_list;
+ }
+ 
+@@ -278,6 +280,8 @@
+ 
+             /* If we have no more in our list, return EOF. */
+             if (!ctx->list) {
++                ctx->last = NULL;
++
+                 if (ctx->hold_open) {
+                     return ctx->hold_open(ctx->hold_open_baton, bucket);
+                 }
+@@ -390,6 +394,8 @@
+ 
+             /* If we have no more in our list, return EOF. */
+             if (!ctx->list) {
++                ctx->last = NULL;
++
+                 if (ctx->hold_open) {
+                     return ctx->hold_open(ctx->hold_open_baton, bucket);
+                 }
diff -Nru serf-1.3.9/debian/patches/series serf-1.3.9/debian/patches/series
--- serf-1.3.9/debian/patches/series    2017-11-13 02:19:32.000000000 +0000
+++ serf-1.3.9/debian/patches/series    2018-03-20 12:38:28.000000000 +0000
@@ -1,2 +1,3 @@
 libtool
 r1792234-expired-certs
+r1712790-serf_bucket_aggregate_prepend-empty-list

-- 
Colin Watson                                       [cjwat...@ubuntu.com]

Reply via email to