Bug#304713: [patch] gtetrinet segfaults on some servers replies when channel list is enabled

Julien Plissonneau Duquene Julien Plissonneau Duquene <debbug2005@julien.plissonneau.duquene.net>, 304713@bugs.debian.org
Thu, 14 Apr 2005 23:43:50 +0200


--VS++wcV0S1rZb1Fb
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: inline
Content-Transfer-Encoding: 8bit

Package: gtetrinet
Version: 0.7.8-1

Hello,

There is a lack of error checking in the function decoding server
replies that looks like /list replies, causing gtetrinet to crash
(segfault) when receiving replies to some commands from some servers.

For example, typing /who when connected to tetridome.com with channel
list enabled will crash gtetrinet. Actually each line in response to
/who on this server starts with an opening parenthesis, and thus is fed
to partyline_add_channel() for parsing.

The attached patch fixes partyline_add_channel in partyline.c so it does
not crash anymore on parsing errors. It does not fix side effects of
/whatever response being mistaken for /list response, including the fact
that the expected response text may not appear at all in the UI.

Regards,

Julien Plissonneau Duqučne


--VS++wcV0S1rZb1Fb
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=patch

--- gtetrinet-0.7.8.orig/src/partyline.c	2004-12-26 16:59:45.000000000 +0100
+++ gtetrinet-0.7.8/src/partyline.c	2005-04-14 22:58:18.000000000 +0200
@@ -467,7 +467,7 @@
   scan->config->skip_comment_single = FALSE;
   
   while ((g_scanner_get_next_token (scan) != G_TOKEN_INT) && !g_scanner_eof (scan));
-  num = scan->value.v_int;
+  num = (scan->token==G_TOKEN_INT) ? scan->value.v_int : 0;
 
   g_scanner_get_next_token (scan); /* dump the ')' */
   
@@ -476,13 +476,13 @@
     scan->config->cpair_comment_single = "# ";
     
     while ((g_scanner_get_next_token (scan) != G_TOKEN_INT) && !g_scanner_eof (scan));
-    actual = scan->value.v_int;
+    actual = (scan->token==G_TOKEN_INT) ? scan->value.v_int : 0;
     
     while ((g_scanner_get_next_token (scan) != G_TOKEN_INT) && !g_scanner_eof (scan));
-    max = scan->value.v_int;
+    max = (scan->token==G_TOKEN_INT) ? scan->value.v_int : 0;
 
     while ((g_scanner_get_next_token (scan) != G_TOKEN_COMMENT_SINGLE) && !g_scanner_eof (scan));
-    utf8 = g_locale_to_utf8 (scan->value.v_comment, -1, NULL, NULL, NULL);
+    utf8 = g_locale_to_utf8 ((scan->token==G_TOKEN_COMMENT_SINGLE) ? scan->value.v_comment : "", -1, NULL, NULL, NULL);
     name = g_strconcat ("#", utf8, NULL);
     
     g_snprintf (final, 1024, "%d/%d", actual, max);
@@ -490,7 +490,7 @@
     scan->config->cpair_comment_single = "{}";
     while ((g_scanner_get_next_token (scan) != G_TOKEN_COMMENT_SINGLE) && !g_scanner_eof (scan));
     if (!g_scanner_eof (scan))
-      state = g_strdup (scan->value.v_comment);
+      state = g_strdup ((scan->token==G_TOKEN_COMMENT_SINGLE) ? scan->value.v_comment : "");
     else
       state = g_strdup ("IDLE");
 
@@ -500,21 +500,21 @@
   else
   {
     while ((g_scanner_get_next_token (scan) != G_TOKEN_COMMENT_SINGLE) && !g_scanner_eof (scan));
-    utf8 = g_locale_to_utf8 (scan->value.v_comment, -1, NULL, NULL, NULL);
+    utf8 = g_locale_to_utf8 ((scan->token==G_TOKEN_COMMENT_SINGLE) ? scan->value.v_comment : "", -1, NULL, NULL, NULL);
     name = g_strconcat ("#", utf8, NULL);
   
     while ((g_scanner_get_next_token (scan) != G_TOKEN_IDENTIFIER) && !g_scanner_eof (scan));
-    players = g_strdup (scan->value.v_identifier);
+    players = g_strdup ((scan->token==G_TOKEN_IDENTIFIER) ? scan->value.v_identifier : "");
 
     if (players != NULL)
     {
       if (strncmp (players, "FULL", 4))
       {
         while ((g_scanner_get_next_token (scan) != G_TOKEN_INT) && !g_scanner_eof (scan));
-        actual = scan->value.v_int;
+        actual = (scan->token==G_TOKEN_INT) ? scan->value.v_int : 0;
 
         while ((g_scanner_get_next_token (scan) != G_TOKEN_INT) && !g_scanner_eof (scan));
-        max = scan->value.v_int;
+        max = (scan->token==G_TOKEN_INT) ? scan->value.v_int : 0;
 
         g_snprintf (final, 1024, "%d/%d %s", actual, max, players);
       }
@@ -529,13 +529,13 @@
     if (g_scanner_get_next_token (scan) == G_TOKEN_LEFT_CURLY)
     {
       g_scanner_get_next_token (scan);
-      state = g_strdup (scan->value.v_identifier);
+      state = g_strdup ((scan->token==G_TOKEN_IDENTIFIER) ? scan->value.v_identifier : "");
     }
     else
       state = g_strdup ("IDLE");
   
     while ((g_scanner_get_next_token (scan) != G_TOKEN_RIGHT_PAREN) && !g_scanner_eof (scan));
-    if (line[scan->position] != 0)
+    if (!g_scanner_eof(scan) && (scan->position < strlen(line)))
       desc = g_strstrip (g_locale_to_utf8 (&line[scan->position], -1, NULL, NULL, NULL));
     else
       desc = g_strdup ("");

--VS++wcV0S1rZb1Fb--