fetch-pack: fix out-of-bounds buffer offset in get_ack

When we read acks from the remote, we expect either: ACK <sha1> or ACK <sha1> <multi-ack-flag> We parse the "ACK <sha1>" bit from the line, and then start looking for the flag strings at "line+45"; if we don't have them, we assume it's of the first type. But if we do have the first type, then line+45 is not necessarily inside our string at all! It turns out that this works most of the time due to the way we parse the packets. They should come in with a newline, and packet_read puts an extra NUL into the buffer, so we end up with: ACK <sha1>\n\0 with the newline at offset 44 and the NUL at offset 45. We then strip the newline, putting a NUL at offset 44. So when we look at "line+45", we are looking past the end of our string; but it's OK, because we hit the terminator from the original string. This breaks down, however, if the other side does not terminate their packets with a newline. In that case, our packet is one character shorter, and we start looking through uninitialized memory for the flag. No known implementation sends such a packet, so it has never come up in practice. This patch tightens the check by looking for a short, flagless ACK before trying to parse the flag. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Feb 20, 2013 at 15:00 UTC 030e9dd64f931c0ccfb6ad4be88775f8272f02eb
1 file changed +2
fetch-pack.c
+2
@@ -226,6 +226,8 @@ static enum ack_type get_ack(int fd, unsigned char *result_sha1)
226 return NAK;
227 if (!prefixcmp(line, "ACK ")) {
228 if (!get_sha1_hex(line+4, result_sha1)) {
229 + if (len < 45)
230 + return ACK;
231 if (strstr(line+45, "continue"))
232 return ACK_continue;
233 if (strstr(line+45, "common"))