diff -ru yahoo-transport-2.3.2/yahoo.c yahoo-transport-2.3.2-new/yahoo.c --- yahoo-transport-2.3.2/yahoo.c 2004-07-01 21:13:29.000000000 +0200 +++ yahoo-transport-2.3.2-new/yahoo.c 2006-03-12 03:02:16.000000000 +0100 @@ -261,49 +261,77 @@ (((*((buf)+3) )&0x000000ff))) static void yahoo_packet_read(struct yahoo_packet *pkt, guchar *data, int len) { - int pos = 0; + int pos = 0; - while (pos + 1 < len) { - char key[64], *value = NULL; - int accept; - int x; - - struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1); - - x = 0; - while (pos + 1 < len) { - if (data[pos] == 0xc0 && data[pos + 1] == 0x80) - break; - key[x++] = data[pos++]; - } - key[x] = 0; - pos += 2; - pair->key = strtol(key, NULL, 10); - accept = x; /* if x is 0 there was no key, so don't accept it */ + while (pos + 1 < len) { + char key[64], *value = NULL, *esc; + int accept; + int x; + + struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1); + + /* this is weird, and in one of the chat packets, and causes us + * think all the values are keys and all the keys are values after + * this point if we don't handle it */ + if (data[pos] == '\0') { + while (pos + 1 < len) { + if (data[pos] == 0xc0 && data[pos + 1] == 0x80) + break; + pos++; + } + pos += 2; + g_free(pair); + continue; + } - if (accept) - value = g_malloc(len - pos + 1); - x = 0; - while (pos + 1 < len) { - if (data[pos] == 0xc0 && data[pos + 1] == 0x80) - break; - if (accept) - value[x++] = data[pos++]; - } - if (pos > len) - return; - if (accept) - value[x] = 0; - pos += 2; - if (accept) { - pair->value = g_strdup(value); - g_free(value); - pkt->hash = g_slist_append(pkt->hash, pair); - log_debug(ZONE, "[YAHOO]: Read Key: %d \tValue: %s\n", pair->key, pair->value); - } else { - g_free(pair); - } - } + x = 0; + while (pos + 1 < len) { + if (data[pos] == 0xc0 && data[pos + 1] == 0x80) + break; + if (x >= sizeof(key)-1) { + x++; + pos++; + continue; + } + key[x++] = data[pos++]; + } + if (x >= sizeof(key)-1) { + x = 0; + } + key[x] = 0; + pos += 2; + pair->key = strtol(key, NULL, 10); + accept = x; /* if x is 0 there was no key, so don't accept it */ + + if (len - pos + 1 <= 0) { + /* Truncated. Garbage or something. */ + accept = 0; + } + + if (accept) { + value = g_malloc(len - pos + 1); + x = 0; + while (pos + 1 < len) { + if (data[pos] == 0xc0 && data[pos + 1] == 0x80) + break; + value[x++] = data[pos++]; + } + value[x] = 0; + pair->value = g_strdup(value); + g_free(value); + pkt->hash = g_slist_append(pkt->hash, pair); + esc = g_strescape(pair->value); + log_debug(ZONE, "Read Key: %d \tValue: %s\n", pair->key, esc); + g_free(esc); + } else { + g_free(pair); + } + pos += 2; + + /* Skip over garbage we've noticed in the mail notifications */ + if (data[0] == '9' && data[pos] == 0x01) + pos++; + } } static void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data) {