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
--- 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 ("");