From patchwork Wed Feb 3 16:00:54 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "David S. Ahern" X-Patchwork-Id: 76739 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o13G17Y5023519 for ; Wed, 3 Feb 2010 16:01:07 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757371Ab0BCQBF (ORCPT ); Wed, 3 Feb 2010 11:01:05 -0500 Received: from sj-iport-2.cisco.com ([171.71.176.71]:44802 "EHLO sj-iport-2.cisco.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756050Ab0BCQBD (ORCPT ); Wed, 3 Feb 2010 11:01:03 -0500 Authentication-Results: sj-iport-2.cisco.com; dkim=neutral (message not signed) header.i=none X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: ApoEAA8taUurR7H+/2dsb2JhbADBKJgRhEUE X-IronPort-AV: E=Sophos;i="4.49,399,1262563200"; d="scan'208";a="237468942" Received: from sj-core-2.cisco.com ([171.71.177.254]) by sj-iport-2.cisco.com with ESMTP; 03 Feb 2010 16:00:55 +0000 Received: from [10.89.3.230] (rcdn-vpn-client-10-89-3-230.cisco.com [10.89.3.230]) by sj-core-2.cisco.com (8.13.8/8.14.3) with ESMTP id o13G0stl023211; Wed, 3 Feb 2010 16:00:55 GMT Message-ID: <4B699DB6.4090604@cisco.com> Date: Wed, 03 Feb 2010 09:00:54 -0700 From: "David S. Ahern" User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.7) Gecko/20100120 Fedora/3.0.1-1.fc11 Thunderbird/3.0.1 MIME-Version: 1.0 To: qemu-devel@nongnu.org CC: kvm-devel Subject: [PATCH] segfault due to buffer overrun in usb-serial Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Wed, 03 Feb 2010 16:01:07 +0000 (UTC) diff --git a/hw/usb-serial.c b/hw/usb-serial.c index 37293ea..c3f3401 100644 --- a/hw/usb-serial.c +++ b/hw/usb-serial.c @@ -497,12 +497,28 @@ static int usb_serial_can_read(void *opaque) static void usb_serial_read(void *opaque, const uint8_t *buf, int size) { USBSerialState *s = opaque; - int first_size = RECV_BUF - s->recv_ptr; - if (first_size > size) - first_size = size; - memcpy(s->recv_buf + s->recv_ptr + s->recv_used, buf, first_size); - if (size > first_size) - memcpy(s->recv_buf, buf + first_size, size - first_size); + int first_size, start; + + /* room in the buffer? */ + if (size > (RECV_BUF - s->recv_used)) + size = RECV_BUF - s->recv_used; + + start = s->recv_ptr + s->recv_used; + if (start < RECV_BUF) { + /* copy data to end of buffer */ + first_size = RECV_BUF - start; + if (first_size > size) + first_size = size; + + memcpy(s->recv_buf + start, buf, first_size); + + /* wrap around to front if needed */ + if (size > first_size) + memcpy(s->recv_buf, buf + first_size, size - first_size); + } else { + start -= RECV_BUF; + memcpy(s->recv_buf + start, buf, size); + } s->recv_used += size; }