Skip to content

Commit

Permalink
WIP notice
Browse files Browse the repository at this point in the history
  • Loading branch information
gabstv committed Feb 25, 2019
1 parent b1fdfb7 commit 06e241c
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 45 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.DS_Store
tmp/
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# go-bsdiff
Pure Go implementation of [bsdiff](http://www.daemonology.net/bsdiff/) 4.

WORK IN PROGRESS!
https://github.com/cnSchwarzer/bsdiff-win/blob/master/bsdiff-win/bsdiff.c

[![GoDoc](https://godoc.org/github.com/gabstv/go-bsdiff?status.svg)](https://godoc.org/github.com/gabstv/go-bsdiff)

bsdiff and bspatch are tools for building and applying patches to binary files. By using suffix sorting (specifically, Larsson and Sadakane's [qsufsort](http://www.larsson.dogma.net/ssrev-tr.pdf)) and taking advantage of how executable files change.
Expand Down
70 changes: 25 additions & 45 deletions pkg/bsdiff/bsdiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,12 @@ func File(oldfile, newfile, patchfile string) error {
return nil
}

// REVIEW OK
func diffb(oldbin, newbin []byte) ([]byte, error) {
bziprule := &bzip2.WriterConfig{
Level: bzip2.BestCompression,
}
iii := make([]int, len(oldbin)+1)
vvv := make([]int, len(oldbin)+1)
qsufsort(iii, vvv, oldbin)
// [C] free(V)
vvv = nil
qsufsort(iii, oldbin)

//var db
var dblen, eblen int
Expand All @@ -99,11 +95,11 @@ func diffb(oldbin, newbin []byte) ([]byte, error) {
// 8 8 length of bzip2ed ctrl block
// 16 8 length of bzip2ed diff block
// 24 8 length of pnew file */
// /* File is
// 0 32 Header
// 32 ?? Bzip2ed ctrl block
// ?? ?? Bzip2ed diff block
// ?? ?? Bzip2ed extra block
// File is
// 0 32 Header
// 32 ?? Bzip2ed ctrl block
// ?? ?? Bzip2ed diff block
// ?? ?? Bzip2ed extra block

newsize := len(newbin)
oldsize := len(oldbin)
Expand Down Expand Up @@ -140,7 +136,6 @@ func diffb(oldbin, newbin []byte) ([]byte, error) {
}
}()

// L 289: while (scan < newsize) {
for scan < newsize {
oldscore = 0

Expand All @@ -165,7 +160,6 @@ func diffb(oldbin, newbin []byte) ([]byte, error) {
}
}

// L 309:
if ln != oldscore || scan == newsize {
s = 0
Sf = 0
Expand Down Expand Up @@ -196,7 +190,7 @@ func diffb(oldbin, newbin []byte) ([]byte, error) {
}
}
}
// L 326:

if lastscan+lenf > scan-lenb {
overlap = (lastscan + lenf) - (scan - lenb)
s = 0
Expand All @@ -206,7 +200,7 @@ func diffb(oldbin, newbin []byte) ([]byte, error) {
if newbin[lastscan+lenf-overlap+i] == oldbin[lastpos+lenf-overlap+i] {
s++
}
// L 332:

if newbin[scan-lenb+i] == oldbin[pos-lenb+i] {
s--
}
Expand All @@ -220,7 +214,6 @@ func diffb(oldbin, newbin []byte) ([]byte, error) {
lenb -= lens
}

// L 341:
for i = 0; i < lenf; i++ {
db[dblen+i] = newbin[lastscan+i] - oldbin[lastpos+i]
}
Expand All @@ -240,12 +233,12 @@ func diffb(oldbin, newbin []byte) ([]byte, error) {
if _, err := pfbz2.Write(buf); err != nil {
return nil, err
}
// L 359

offtout((pos-lenb)-(lastpos+lenf), buf)
if _, err := pfbz2.Write(buf); err != nil {
return nil, err
}
// L 364

lastscan = scan - lenb
lastpos = pos - lenb
lastoffset = pos - scan
Expand All @@ -255,29 +248,25 @@ func diffb(oldbin, newbin []byte) ([]byte, error) {
return nil, err
}

/* Compute size of compressed ctrl data */
if ln = pf.Len(); ln == -1 {
return nil, fmt.Errorf("ftello") // TODO: remove?
}
// Compute size of compressed ctrl data
offtout(ln-32, header[8:])

/* Write compressed diff data */
// Write compressed diff data
pfbz2, err = bzip2.NewWriter(pf, bziprule)
if err != nil {
return nil, err
}
if _, err = pfbz2.Write(db[:dblen]); err != nil {
return nil, err
}
// L 384

if err = pfbz2.Close(); err != nil {
return nil, err
}
/* Compute size of compressed diff data */
// Compute size of compressed diff data
newsize = pf.Len()
offtout(newsize-ln, header[16:])
/* Write compressed extra data */
// L 394
// Write compressed extra data
pfbz2, err = bzip2.NewWriter(pf, bziprule)
if err != nil {
return nil, err
Expand All @@ -288,7 +277,7 @@ func diffb(oldbin, newbin []byte) ([]byte, error) {
if err = pfbz2.Close(); err != nil {
return nil, err
}
/* Seek to the beginning, write the header, and close the file */
// Seek to the beginning, write the header, and close the file
if _, err = pf.Seek(0, io.SeekStart); err != nil {
return nil, err
}
Expand All @@ -304,7 +293,6 @@ func diffb(oldbin, newbin []byte) ([]byte, error) {
return pf.Bytes(), nil
}

// REVIEW OK (*)
func search(iii []int, oldbin []byte, newbin []byte, st, en int, pos *int) int {
var x, y int
oldsize := len(oldbin)
Expand All @@ -324,14 +312,12 @@ func search(iii []int, oldbin []byte, newbin []byte, st, en int, pos *int) int {

x = st + (en-st)/2
cmpln := util.Min(oldsize-iii[x], newsize)
// xxx = oldbin[iii[x]:]
if bytes.Compare(oldbin[iii[x]:iii[x]+cmpln], newbin[:cmpln]) < 0 {
return search(iii, oldbin, newbin, x, en, pos)
}
return search(iii, oldbin, newbin, st, x, pos)
}

// REVIEW OK
func matchlen(oldbin []byte, newbin []byte) int {
var i int
oldsize := len(oldbin)
Expand All @@ -345,7 +331,6 @@ func matchlen(oldbin []byte, newbin []byte) int {
return i
}

// REVIEW OK
func offtout(x int, buf []byte) {
var y int
if x < 0 {
Expand Down Expand Up @@ -381,48 +366,46 @@ func offtout(x int, buf []byte) {
}
}

// REVIEW OK
func qsufsort(iii, vvv []int, buf []byte) {
func qsufsort(iii []int, buf []byte) {
buckets := make([]int, 256)
vvv := make([]int, len(iii))
var i, h, ln int
bufzise := len(buf)
// [C] for (i = 0;i < 256;i++) buckets[i] = 0;
// [C] for (i = 0;i < oldsize;i++) buckets[pold[i]]++;

for i = 0; i < bufzise; i++ {
buckets[buf[i]]++
}
// [C] for (i = 1;i < 256;i++) buckets[i] += buckets[i - 1];

for i = 1; i < 256; i++ {
buckets[i] += buckets[i-1]
}
// [C] for (i = 255;i > 0;i--) buckets[i] = buckets[i - 1];

for i = 255; i > 0; i-- {
buckets[i] = buckets[i-1]
}
buckets[0] = 0

// [C] for (i = 0;i < oldsize;i++) I[++buckets[pold[i]]] = i;
for i = 0; i < bufzise; i++ {
buckets[buf[i]]++
iii[buckets[buf[i]]] = i
}
iii[0] = bufzise
// [C] for (i = 0;i < oldsize;i++) V[i] = buckets[pold[i]];

for i = 0; i < bufzise; i++ {
vvv[i] = buckets[buf[i]]
}
vvv[bufzise] = 0
// [C] for (i = 1;i < 256;i++) if (buckets[i] == buckets[i - 1] + 1) I[buckets[i]] = -1;

for i = 1; i < 256; i++ {
if buckets[i] == buckets[i-1]+1 {
iii[buckets[i]] = -1
}
}
iii[0] = -1
// [C] for (h = 1;I[0] != -(oldsize + 1);h += h) {

for h = 1; iii[0] != -(bufzise + 1); h += h {
ln = 0
// [C] for (i = 0;i < oldsize + 1;) {

i = 0
for i < bufzise+1 {
if iii[i] < 0 {
Expand All @@ -448,17 +431,14 @@ func qsufsort(iii, vvv []int, buf []byte) {
}
}

// REVIEW OK
func split(iii, vvv []int, start, ln, h int) {
var i, j, k, x int
//var tmp int32

if ln < 16 {
for k = start; k < start+ln; k += j {
j = 1
x = vvv[iii[k]+h]
for i = 1; k+i < start+ln; i++ {
// L 54:
if vvv[iii[k+i]+h] < x {
x = vvv[iii[k+i]+h]
j = 0
Expand Down
47 changes: 47 additions & 0 deletions pkg/bspatch/bspatch_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package bspatch

import (
"bytes"
"testing"
)

func TestPatch(t *testing.T) {
oldfile := []byte{
0x66, 0xFF, 0xD1, 0x55, 0x56, 0x10, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1,
}
newfilecomp := []byte{
0x66, 0xFF, 0xD1, 0x55, 0x56, 0x10, 0x30, 0x00,
0x44, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xD1, 0xFF, 0xD1,
}
patchfile := []byte{
0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34, 0x30,
0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26,
0x53, 0x59, 0xDA, 0xE4, 0x46, 0xF2, 0x00, 0x00,
0x05, 0xC0, 0x00, 0x4A, 0x09, 0x20, 0x00, 0x22,
0x34, 0xD9, 0x06, 0x06, 0x4B, 0x21, 0xEE, 0x17,
0x72, 0x45, 0x38, 0x50, 0x90, 0xDA, 0xE4, 0x46,
0xF2, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59,
0x26, 0x53, 0x59, 0x30, 0x88, 0x1C, 0x89, 0x00,
0x00, 0x02, 0xC4, 0x00, 0x44, 0x00, 0x06, 0x00,
0x20, 0x00, 0x21, 0x21, 0xA0, 0xC3, 0x1B, 0x03,
0x3C, 0x5D, 0xC9, 0x14, 0xE1, 0x42, 0x40, 0xC2,
0x20, 0x72, 0x24, 0x42, 0x5A, 0x68, 0x39, 0x31,
0x41, 0x59, 0x26, 0x53, 0x59, 0x65, 0x25, 0x30,
0x43, 0x00, 0x00, 0x00, 0x40, 0x02, 0xC0, 0x00,
0x20, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x22, 0x1F,
0xA4, 0x19, 0x82, 0x58, 0x5D, 0xC9, 0x14, 0xE1,
0x42, 0x41, 0x94, 0x94, 0xC1, 0x0C,
}
newfile, err := Bytes(oldfile, patchfile)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(newfile, newfilecomp) {
t.Fatal("expected:", newfilecomp, "got:", newfile)
}
}

0 comments on commit 06e241c

Please sign in to comment.