Skip to content

bug: GameSpy 3 packet cleanup does not remove partial key #756

@cetteup

Description

@cetteup

During some testing with a Battlefield 2 server, I noticed that the server will send partial keys at the end of a packet in rare cases. The following packet will start with the same (now complete) key and the value. In GameDig, these partial keys completely throw off parsing of the packet (see gamedig/node-gamedig#708).

I noticed that GameQ seems to handle this case, cleaning up the partial key.

// Compare last var of current packet with first var of next packet
// On a partial match, remove last var from current packet,
// variable header from next packet
for ($i = 0, $x = $packetCount; $i < $x - 1; $i++) {
// First packet
$fst = substr($packets[$i], 0, -1);
// Second packet
$snd = $packets[$i + 1];
// Get last variable from first packet
$fstvar = substr($fst, strrpos($fst, "\x00") + 1);
// Get first variable from last packet
$snd = substr($snd, strpos($snd, "\x00") + 2);
$sndvar = substr($snd, 0, strpos($snd, "\x00"));
// Check if fstvar is a substring of sndvar
// If so, remove it from the first string
if (!empty($fstvar) && strpos($sndvar, $fstvar) !== false) {
$packets[$i] = preg_replace("#(\\x00[^\\x00]+\\x00)$#", "\x00", $packets[$i]);
}
}

However, running GameQ against my test server (202.61.196.80:29902) still returns broken data. After some debugging I found that GameQ actually skips the first key from the second package. Instead of comparing the last key of packet n with the first key of packet n+1, the cleanup loop compares it to the second key of packet n+1.

It seems the issue is caused by line 201, which skips the first key (and two more characters). Line 202 then extracts what used to be the second key.

// Get first variable from last packet
$snd = substr($snd, strpos($snd, "\x00") + 2);
$sndvar = substr($snd, 0, strpos($snd, "\x00"));

In my example, I end up with $fstvar = "bf2_sponsorlo" being compared to $sndvar = "bf2_communitylogo_url". Since the keys don't match, the partial key at the end of the first packet is not cleaned up and parsing breaks (complete key from 2nd packet is parsed as value for partial key from first packet).

If I remove line 201, the cleanup extracts $fstvar = "bf2_sponsorlo" and $sndvar = "bf2_sponsorlogo_url" - which do match and thus trigger the cleanup. The second packet is then parsed correctly.

It's entirely possible that the cleanup was built to clean up a different kind of packet split issue. But just going by the comment in line 200, it seems that line 201 was simply added in error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions