From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:39977) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SmDKu-0001f7-6r for qemu-devel@nongnu.org; Tue, 03 Jul 2012 20:20:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SmDKs-0005lh-7x for qemu-devel@nongnu.org; Tue, 03 Jul 2012 20:20:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:63216) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SmDKr-0005kZ-Ou for qemu-devel@nongnu.org; Tue, 03 Jul 2012 20:20:49 -0400 Message-ID: <4FF38C46.9060305@redhat.com> Date: Tue, 03 Jul 2012 18:20:22 -0600 From: Eric Blake MIME-Version: 1.0 References: <1341323574-23206-1-git-send-email-owasserm@redhat.com> <1341323574-23206-11-git-send-email-owasserm@redhat.com> <4FF364D8.4020407@redhat.com> <4FF3667B.50106@redhat.com> In-Reply-To: <4FF3667B.50106@redhat.com> Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="------------enigBD097622112AEA84B52AF691" Subject: Re: [Qemu-devel] [PATCH v14 10/13] Add xbzrle_encode_buffer and xbzrle_decode_buffer functions List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, aliguori@us.ibm.com, quintela@redhat.com, stefanha@gmail.com, Orit Wasserman , qemu-devel@nongnu.org, mdroth@linux.vnet.ibm.com, blauwirbel@gmail.com, Petter Svard , Benoit Hudzia , avi@redhat.com, Aidan Shribman , pbonzini@redhat.com, chegu_vinod@hp.com This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enigBD097622112AEA84B52AF691 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On 07/03/2012 03:39 PM, Eric Blake wrote: > On 07/03/2012 03:32 PM, Eric Blake wrote: >=20 >>> + ret =3D uleb128_decode_small(src + i, &count); >>> + if (ret < 0) { >> >> An nzrun should be a non-zero value; I'd write this as (ret <=3D 0) to= >> rule out an attempt to pass a zero-length nzrun. >=20 > Correcting myself, >=20 > if (ret < 0 || !count) { >=20 > At this point, I think I will just bite the bullet and post a version o= f > this code that incorporates my review. Something like this (lightly tested): /* page =3D zrun nzrun | zrun nzrun page zrun =3D length nzrun =3D length byte... length =3D uleb128 encoded integer */ int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen, uint8_t *dst, int dlen) { uint32_t zrun_len =3D 0, nzrun_len =3D 0; int d =3D 0, i =3D 0; long res, xor; uint8_t *nzrun_start =3D NULL; g_assert(!(((uintptr_t)old_buf | (uintptr_t)new_buf | slen) % sizeof(long))); while (i < slen) { /* overflow */ if (d + 2 > dlen) { return -1; } /* not aligned to sizeof(long) */ res =3D (slen - i) % sizeof(long); while (res && old_buf[i] =3D=3D new_buf[i]) { zrun_len++; i++; res--; } if (!res) { while (i < slen && (*(long *)(old_buf + i)) =3D=3D (*(long *)(new_buf + i= ))) { i +=3D sizeof(long); zrun_len +=3D sizeof(long); } /* go over the rest */ while (i < slen && old_buf[i] =3D=3D new_buf[i]) { zrun_len++; i++; } } /* buffer unchanged */ if (zrun_len =3D=3D slen) { return 0; } /* skip last zero run */ if (i =3D=3D slen) { return d; } d +=3D uleb128_encode_small(dst + d, zrun_len); zrun_len =3D 0; nzrun_start =3D new_buf + i; /* overflow */ if (d + 2 > dlen) { return -1; } /* not aligned to sizeof(long) */ res =3D (slen - i) % sizeof(long); while (res && old_buf[i] !=3D new_buf[i]) { nzrun_len++; i++; res--; } if (!res) { /* truncation to 32-bit long okay */ long mask =3D 0x0101010101010101ULL; while (i < slen) { xor =3D *(long *)(old_buf + i) ^ *(long *)(new_buf + i); if ((xor - mask) & ~xor & (mask << 7)) { /* found the end of an nzrun within the current long */ while (old_buf[i] !=3D new_buf[i]) { nzrun_len++; i++; } break; } else { i +=3D sizeof(long); nzrun_len +=3D sizeof(long); } } } d +=3D uleb128_encode_small(dst + d, nzrun_len); /* overflow */ if (d + nzrun_len > dlen) { return -1; } memcpy(dst + d, nzrun_start, nzrun_len); d +=3D nzrun_len; nzrun_len =3D 0; } return d; } int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen) { int i =3D 0, d =3D 0; int ret; uint32_t count =3D 0; while (i < slen) { /* zrun */ if (slen - i < 2) { return -1; } ret =3D uleb128_decode_small(src + i, &count); if (ret < 0 || (i && !count)) { return -1; } i +=3D ret; d +=3D count; /* overflow */ if (d > dlen) { return -1; } /* nzrun */ if (slen - i < 2) { return -1; } ret =3D uleb128_decode_small(src + i, &count); if (ret < 0 || !count) { return -1; } i +=3D ret; /* overflow */ if (d + count > dlen || i + count > slen) { return -1; } memcpy(dst + d , src + i, count); d +=3D count; i +=3D count; } return d; } --=20 Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org --------------enigBD097622112AEA84B52AF691 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) Comment: Public key at http://people.redhat.com/eblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQEcBAEBCAAGBQJP84xHAAoJEKeha0olJ0Nqa18H/0W2BOwipQVQ7eeu2xl9jFJg w0wcNCra2PhiFJwYRkpxWd1Hi+NfPd0GiIPrEr4Rn4Y+g/SHAvQ6LpLnCw+oiqNS OTtdNHCvgLJo1KKHW9mtz5qnVrvmUzf8ZhogjDV+UorsN4VuGhhdOiRBIFfd7tKz tds3fUNHZdbEnRtpR50A78dWyZWIY/7eZyWsF+fMeUry2UVH0DJuQL30zVvmDtoS 8OFueH38NPLlj4YhwaAioor2T6rpW4ntjdO2VgxQQ4Opd+0IqCN3fGgAiBDtmmcx t63/OD3aWfa3bqw9NHkLuinC24WfXAQtne/pzg7vJVHMSz37Sv4FGPQvHW5RBYo= =NUcA -----END PGP SIGNATURE----- --------------enigBD097622112AEA84B52AF691--