[telepathy-gabble/master] gabble_presence_cache_update_cache_entry: allow in == NULL

Simon McVittie simon.mcvittie at collabora.co.uk
Tue Jul 21 11:31:39 PDT 2009


When the meaning of a caps bundle is forcibly inserted into the cache
with gabble_presence_cache_add_bundle_caps, it doesn't come with any
channel-manager-specific caps (the hash table in the struct describing
the bundle is NULL).

This could cause a crash when gabble_presence_cache_update_cache_entry is
called by _process_caps_uri, with the assumption that the hash table
is non-NULL.

This special-casing is currently done for one bundle, GTalk's voice-v1,
to work around failure to respond to disco correctly in old versions
of GTalk.

Also add a regression test, which models a real-world situation in which
this crash can occur - when a sipphone.com user tries to call an
@gmail.com JID (but apparently not an @googlemail.com JID!) as if it was
a SIP URI, sipphone.com's servers automatically bridge the call through
gtalk2voip.com, which makes the call by emulating an old version of GTalk.

Reviewed-by: Will Thompson <will.thompson at collabora.co.uk>
---
 src/presence-cache.c                       |    6 ++-
 tests/twisted/Makefile.am                  |    1 +
 tests/twisted/jingle/jingletest2.py        |    5 ++-
 tests/twisted/jingle/preload-caps-crash.py |   46 ++++++++++++++++++++++++++++
 4 files changed, 54 insertions(+), 4 deletions(-)
 create mode 100644 tests/twisted/jingle/preload-caps-crash.py

diff --git a/src/presence-cache.c b/src/presence-cache.c
index a67ab12..81eaa4f 100644
--- a/src/presence-cache.c
+++ b/src/presence-cache.c
@@ -818,8 +818,10 @@ void
 gabble_presence_cache_update_cache_entry (
     GHashTable *out, GHashTable *in)
 {
-  g_hash_table_foreach (in, update_caps_helper,
-      out);
+  g_return_if_fail (out != NULL);
+
+  if (in != NULL)
+    g_hash_table_foreach (in, update_caps_helper, out);
 }
 
 static void _caps_disco_cb (GabbleDisco *disco,
diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am
index 5261da2..f3d852a 100644
--- a/tests/twisted/Makefile.am
+++ b/tests/twisted/Makefile.am
@@ -89,6 +89,7 @@ TWISTED_TESTS = \
 	jingle/outgoing-many-streams.py \
 	jingle/outgoing-not-answered.py \
 	jingle/payload-types.py \
+	jingle/preload-caps-crash.py \
 	jingle/stream-handler-error.py \
 	jingle/test-content-adding-removal.py \
 	jingle/test-description-info.py \
diff --git a/tests/twisted/jingle/jingletest2.py b/tests/twisted/jingle/jingletest2.py
index ae2600d..94ed8df 100644
--- a/tests/twisted/jingle/jingletest2.py
+++ b/tests/twisted/jingle/jingletest2.py
@@ -380,7 +380,7 @@ class JingleTest2:
         self.stream = stream
         self.sid = 'sess' + str(int(random.random() * 10000))
 
-    def prepare(self):
+    def prepare(self, send_presence=True):
         # If we need to override remote caps, feats, codecs or caps,
         # we should do it prior to calling this method.
 
@@ -401,7 +401,8 @@ class JingleTest2:
                     query_name='vCard'),
                 )
 
-        self.send_presence_and_caps()
+        if send_presence:
+            self.send_presence_and_caps()
 
     def send_presence_and_caps(self):
         # We need remote end's presence for capabilities
diff --git a/tests/twisted/jingle/preload-caps-crash.py b/tests/twisted/jingle/preload-caps-crash.py
new file mode 100644
index 0000000..252e8a4
--- /dev/null
+++ b/tests/twisted/jingle/preload-caps-crash.py
@@ -0,0 +1,46 @@
+"""
+Regression test for a crash in which PRESENCE_CAP_GOOGLE_VOICE is preloaded
+and we don't have any per_channel_manager_caps by the time we receive a
+call, when called by gtalk2voip.com on behalf of a sipphone.com user.
+"""
+
+import dbus
+
+from gabbletest import make_result_iq, exec_test, sync_stream
+from servicetest import (
+    make_channel_proxy, unwrap, tp_path_prefix, EventPattern,
+    assertEquals, assertLength
+    )
+from jingletest2 import JingleTest2, GtalkProtocol03
+import constants as cs
+import ns
+
+from twisted.words.xish import xpath
+
+class MyJingleTest(JingleTest2):
+    remote_caps = { 'ext': 'sidebar voice-v1',
+            'node': 'http://www.google.com/xmpp/client/caps',
+            'ver': '1.0.0.104'
+            }
+
+def test(q, bus, conn, stream):
+    jp = GtalkProtocol03()
+    jt = MyJingleTest(jp, conn, q, stream, 'test at localhost', 'foo at gtalk2voip.com')
+    jt.prepare(send_presence=False)
+    # Send the presence from a bare JID to our bare JID...
+    stream.send(jp.xml(jp.Presence('foo at gtalk2voip.com', 'test at localhost',
+        jt.remote_caps)))
+
+    event = q.expect('stream-iq', query_ns=ns.DISCO_INFO, to='foo at gtalk2voip.com')
+    # ... then immediately send from a bare JID to our full JID
+    stream.send(jp.xml(jp.Presence('foo at gtalk2voip.com', 'test at localhost/test',
+        jt.remote_caps)))
+
+    stream.send(jp.xml(jp.ResultIq('test at localhost/test', event.stanza,
+        [ jp.Query(None, ns.DISCO_INFO,
+            [ jp.Feature(x) for x in jp.features ]) ]) ))
+
+    sync_stream(q, stream)
+
+if __name__ == '__main__':
+    exec_test(test)
-- 
1.5.6.5



More information about the telepathy-commits mailing list