Issue description

VULNERABILITY DETAILS
Upstream's bspatch.c implemenation doesn't check for negative values on the number of bytes to read from the "diff" and "extra" streams, allowing an attacker controlling the patch file to write at arbitrary locations in the heap.
bspatch's main loop reads three numbers from the "control" stream in the patch: X, Y and Z. The first two are the number of bytes to read from "diff" and "extra" (and thus only non-negative), while the third one could be positive or negative and moves the oldpos pointer on the source image. These 3 values are 64bits signed ints (encoded somehow on the file) that are later passed the function that reads from the streams, but those values are not verified to be non-negative.
Chrome[OS] has four different implementations of this program, all derived from the same original code by Colin Percival.
VERSION
Chrome Version: ToT / See details
Operating System: Mac / ChromeOS
* On Mac, src/chrome/installer/mac/third_party/bsdiff/goobspatch.c (although it seems to not be vulnerable due to proper error handling on cfread()). I don't know where the patches come from.
* On ChromeOS, src/third_party/chromiumos-overlay/dev-util/bsdiff/bsdiff-4.3-r5.ebuild the command is definitively vulnerable, but update_engine checks the hash of the patch *before* running bspatch, so not exploitable on that context.
* On Chrome/Win, src/third_party/bspatch/mbspatch.cc (from Mozilla) seems to not be vulnerable to this overflow because it reads a struct with X and Y as unsigned values and checks that the resulting pointer is in range.
* On Chrome/Win, src/courgette/third_party/bsdiff_apply.cc (used by courgette during Chrome updates) it uses a variant of the mbspatch.cc which again reads unsigned values. That impl seems to be ok.
REPRODUCTION CASE
The attached python script creates a patch that exposes the bug for the first two cases.
Essentially, you need to pass negative values for X or Y that BZRead() treats properly.

> * On Mac, src/chrome/installer/mac/third_party/bsdiff/goobspatch.c (although
> it seems to not be vulnerable due to proper error handling on cfread()). I
> don't know where the patches come from.
I wrote the patches directly in the Chrome source tree, there is no other source for this version than the one you’re patching.
This bug is a very good find.