[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