Hi Tristan,

I have not seen that behaviour, I would suggest stepping through the daemon 
with gdb
and providing a backtrace when the daemon gets kicked from the session.

We found the source of the bug yesterday. The second INVITE contains a `display-name` made of invalid characters. In this instance, `display-name` starts with 0xb1, which is invalid in utf-8.

It seems like sflphoned does not verify that the `display-name` is valid before sending it to the GUI through dbus.

I have created and attached a sipp test that simulates this case. You can run this test with the following command:

$ sipp -sf bad-display-name.xml -inf character.txt -m 1 remote-host:[remote-port]

For the time being, our temporary fix is to patch `sip_utils.cpp` to check for a valid `display-name`. I know that this is not a solid fix, but I'm providing it here so you can see one functional workaround.

Cheers,

Pascal Potvin
Software Developer
[email protected]

Extenway Solutions Inc.
514-694-1916 x290

Attachment: bad-display-name-sipp-test.tar.gz
Description: application/gzip

diff --git a/daemon/src/sip/sip_utils.cpp b/daemon/src/sip/sip_utils.cpp
index 48df5f4..5226ee2 100644
--- daemon.orig/src/sip/sip_utils.cpp
+++ daemon/src/sip/sip_utils.cpp
@@ -50,6 +50,87 @@
 #include <vector>
 #include <algorithm>
 
+bool
+is_utf8(const char * string)
+{
+    if(!string)
+        return false;
+
+    const unsigned char * bytes = (const unsigned char *)string;
+    while(*bytes)
+    {
+        if( (// ASCII
+             // use bytes[0] <= 0x7F to allow ASCII control characters
+                bytes[0] == 0x09 ||
+                bytes[0] == 0x0A ||
+                bytes[0] == 0x0D ||
+                (0x20 <= bytes[0] && bytes[0] <= 0x7E)
+            )
+        ) {
+            bytes += 1;
+            continue;
+        }
+
+        if( (// non-overlong 2-byte
+                (0xC2 <= bytes[0] && bytes[0] <= 0xDF) &&
+                (0x80 <= bytes[1] && bytes[1] <= 0xBF)
+            )
+        ) {
+            bytes += 2;
+            continue;
+        }
+
+        if( (// excluding overlongs
+                bytes[0] == 0xE0 &&
+                (0xA0 <= bytes[1] && bytes[1] <= 0xBF) &&
+                (0x80 <= bytes[2] && bytes[2] <= 0xBF)
+            ) ||
+            (// straight 3-byte
+                ((0xE1 <= bytes[0] && bytes[0] <= 0xEC) ||
+                    bytes[0] == 0xEE ||
+                    bytes[0] == 0xEF) &&
+                (0x80 <= bytes[1] && bytes[1] <= 0xBF) &&
+                (0x80 <= bytes[2] && bytes[2] <= 0xBF)
+            ) ||
+            (// excluding surrogates
+                bytes[0] == 0xED &&
+                (0x80 <= bytes[1] && bytes[1] <= 0x9F) &&
+                (0x80 <= bytes[2] && bytes[2] <= 0xBF)
+            )
+        ) {
+            bytes += 3;
+            continue;
+        }
+
+        if( (// planes 1-3
+                bytes[0] == 0xF0 &&
+                (0x90 <= bytes[1] && bytes[1] <= 0xBF) &&
+                (0x80 <= bytes[2] && bytes[2] <= 0xBF) &&
+                (0x80 <= bytes[3] && bytes[3] <= 0xBF)
+            ) ||
+            (// planes 4-15
+                (0xF1 <= bytes[0] && bytes[0] <= 0xF3) &&
+                (0x80 <= bytes[1] && bytes[1] <= 0xBF) &&
+                (0x80 <= bytes[2] && bytes[2] <= 0xBF) &&
+                (0x80 <= bytes[3] && bytes[3] <= 0xBF)
+            ) ||
+            (// plane 16
+                bytes[0] == 0xF4 &&
+                (0x80 <= bytes[1] && bytes[1] <= 0x8F) &&
+                (0x80 <= bytes[2] && bytes[2] <= 0xBF) &&
+                (0x80 <= bytes[3] && bytes[3] <= 0xBF)
+            )
+        ) {
+            bytes += 4;
+            continue;
+        }
+
+        return false;
+    }
+
+    return true;
+}
+
 std::string
 sip_utils::fetchHeaderValue(pjsip_msg *msg, const std::string &field)
 {
@@ -137,6 +218,9 @@ sip_utils::parseDisplayName(const char * buffer)
     std::string displayName = temp.substr(begin_displayName + 1,
                                           end_displayName - begin_displayName - 1);
 
+    if (!is_utf8(displayName.c_str()))
+        return "";
+
     static const size_t MAX_DISPLAY_NAME_SIZE = 25;
     if (displayName.size() > MAX_DISPLAY_NAME_SIZE)
         return displayName.substr(0, MAX_DISPLAY_NAME_SIZE);
_______________________________________________
SFLphone mailing list
[email protected]
http://lists.savoirfairelinux.net/mailman/listinfo/sflphone

Reply via email to