Skip to content

Instantly share code, notes, and snippets.

@deoxxa
Last active July 12, 2016 11:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save deoxxa/e1c2b1af3049074fb0d2891093eb80b0 to your computer and use it in GitHub Desktop.
Save deoxxa/e1c2b1af3049074fb0d2891093eb80b0 to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
"unicode/utf8"
)
func decode(input []byte, offset int64, depth int) (int, []string, error) {
r := bytes.NewReader(input)
var a []string
n := 0
for {
o, err := r.Seek(0, os.SEEK_CUR)
if err != nil {
return n, a, err
}
o += offset
i, err := binary.ReadUvarint(r)
if err != nil {
if err == io.EOF {
return n, a, nil
}
return n, a, err
}
if i == 0 {
return n, a, fmt.Errorf("tag was zero")
}
t := i & 0x03
k := i >> 3
if k < 0 {
return n, a, fmt.Errorf("invalid key %d", k)
}
if k > 1024 {
return n, a, fmt.Errorf("probably invalid key %d", k)
}
switch t {
case 0:
v, err := binary.ReadUvarint(r)
if err != nil {
return n, a, err
}
a = append(a, fmt.Sprintf("[%d] %d (varint @ %d)", k, t, o))
a = append(a, fmt.Sprintf(" signed: %d", v))
a = append(a, fmt.Sprintf(" unsigned: %d", uint64(v)))
case 1:
v := make([]byte, 8)
if _, err := r.Read(v); err != nil {
return n, a, err
}
a = append(a, fmt.Sprintf("[%d] %d (64bit @ %d): %s", k, t, o, hex.EncodeToString(v)))
case 2:
l, err := binary.ReadUvarint(r)
if err != nil {
return n, a, err
}
if l < 0 {
return n, a, fmt.Errorf("invalid length %d", l)
}
if l > 1024*32 {
return n, a, fmt.Errorf("probably invalid length %d", l)
}
a = append(a, fmt.Sprintf("[%d] %d (length-prefix @ %d): %d", k, t, o, l))
o, err = r.Seek(0, os.SEEK_CUR)
if err != nil {
return n, a, err
}
o += offset
v := make([]byte, l)
if j, err := r.Read(v); err != nil && err != io.EOF {
return n, a, err
} else if j < len(v) {
return n, a, fmt.Errorf("couldn't read enough data")
}
_, ma, merr := decode(v, o, depth+1)
if merr == nil {
for _, s := range ma {
a = append(a, " "+s)
}
} else {
if utf8.ValidString(string(v)) {
a = append(a, fmt.Sprintf(" %q", string(v)))
} else {
a = append(a, fmt.Sprintf(" %s", hex.EncodeToString(v)))
}
}
case 5:
v := make([]byte, 4)
if _, err := r.Read(v); err != nil {
return n, a, err
}
a = append(a, fmt.Sprintf("[%d] %d (32bit @ %d): %s", k, t, o, hex.EncodeToString(v)))
default:
return n, a, fmt.Errorf("invalid type %d @ %d", t, o)
}
n++
}
}
func main() {
for _, f := range os.Args[1:] {
fmt.Printf("parsing %s\n", f)
d, err := ioutil.ReadFile(f)
if err != nil {
panic(err)
}
n, lines, err := decode(d, 0, 0)
if n > 0 && err == nil {
fmt.Printf("decoded %d fields\n", n)
if err != nil {
fmt.Printf("error was %s\n", err.Error())
}
fmt.Printf("\n")
for _, l := range lines {
fmt.Printf(" %s\n", l)
}
fmt.Printf("\n")
}
}
}
package main
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
"unicode/utf8"
)
func decode(input []byte, offset int64, depth int) (int, []string, error) {
r := bytes.NewReader(input)
var a []string
n := 0
for {
o, err := r.Seek(0, os.SEEK_CUR)
if err != nil {
return n, a, err
}
o += offset
i, err := binary.ReadUvarint(r)
if err != nil {
if err == io.EOF {
return n, a, nil
}
return n, a, err
}
if i == 0 {
return n, a, fmt.Errorf("tag was zero")
}
t := i & 0x03
k := i >> 3
if k < 0 {
return n, a, fmt.Errorf("invalid key %d", k)
}
if k > 1024 {
return n, a, fmt.Errorf("probably invalid key %d", k)
}
switch t {
case 0:
v, err := binary.ReadUvarint(r)
if err != nil {
return n, a, err
}
a = append(a, fmt.Sprintf("[%d] %d (varint @ %d)", k, t, o))
a = append(a, fmt.Sprintf(" signed: %d", v))
a = append(a, fmt.Sprintf(" unsigned: %d", uint64(v)))
case 1:
v := make([]byte, 8)
if _, err := r.Read(v); err != nil {
return n, a, err
}
a = append(a, fmt.Sprintf("[%d] %d (64bit @ %d): %s", k, t, o, hex.EncodeToString(v)))
{
var fbe float64
if err := binary.Read(bytes.NewReader(v), binary.BigEndian, &fbe); err == nil {
a = append(a, fmt.Sprintf(" (doublebe) %f", fbe))
}
var fle float64
if err := binary.Read(bytes.NewReader(v), binary.LittleEndian, &fle); err == nil {
a = append(a, fmt.Sprintf(" (doublele) %f", fle))
}
var slbe int64
if err := binary.Read(bytes.NewReader(v), binary.BigEndian, &slbe); err == nil {
a = append(a, fmt.Sprintf(" (int64be) %d", slbe))
}
var slle int64
if err := binary.Read(bytes.NewReader(v), binary.LittleEndian, &slle); err == nil {
a = append(a, fmt.Sprintf(" (int64le) %d", slle))
}
var ulbe uint64
if err := binary.Read(bytes.NewReader(v), binary.BigEndian, &ulbe); err == nil {
a = append(a, fmt.Sprintf(" (uint64be) %d", ulbe))
}
var ulle uint64
if err := binary.Read(bytes.NewReader(v), binary.LittleEndian, &ulle); err == nil {
a = append(a, fmt.Sprintf(" (uint64le) %d", ulle))
}
}
case 2:
l, err := binary.ReadUvarint(r)
if err != nil {
return n, a, err
}
if l < 0 {
return n, a, fmt.Errorf("invalid length %d", l)
}
if l > 1024*32 {
return n, a, fmt.Errorf("probably invalid length %d", l)
}
a = append(a, fmt.Sprintf("[%d] %d (length-prefix @ %d): %d", k, t, o, l))
o, err = r.Seek(0, os.SEEK_CUR)
if err != nil {
return n, a, err
}
o += offset
v := make([]byte, l)
if j, err := r.Read(v); err != nil && err != io.EOF {
return n, a, err
} else if j < len(v) {
return n, a, fmt.Errorf("couldn't read enough data")
}
_, ma, merr := decode(v, o, depth+1)
if merr == nil {
for _, s := range ma {
a = append(a, " "+s)
}
} else {
if utf8.ValidString(string(v)) {
a = append(a, fmt.Sprintf(" %q", string(v)))
} else {
a = append(a, fmt.Sprintf(" %s", hex.EncodeToString(v)))
}
}
case 5:
v := make([]byte, 4)
if _, err := r.Read(v); err != nil {
return n, a, err
}
a = append(a, fmt.Sprintf("[%d] %d (32bit @ %d): %s", k, t, o, hex.EncodeToString(v)))
{
var fbe float32
if err := binary.Read(bytes.NewReader(v), binary.BigEndian, &fbe); err == nil {
a = append(a, fmt.Sprintf(" (floatbe) %f", fbe))
}
var fle float32
if err := binary.Read(bytes.NewReader(v), binary.LittleEndian, &fle); err == nil {
a = append(a, fmt.Sprintf(" (floatle) %f", fle))
}
var slbe int32
if err := binary.Read(bytes.NewReader(v), binary.BigEndian, &slbe); err == nil {
a = append(a, fmt.Sprintf(" (int32be) %d", slbe))
}
var slle int32
if err := binary.Read(bytes.NewReader(v), binary.LittleEndian, &slle); err == nil {
a = append(a, fmt.Sprintf(" (int32le) %d", slle))
}
var ulbe uint32
if err := binary.Read(bytes.NewReader(v), binary.BigEndian, &ulbe); err == nil {
a = append(a, fmt.Sprintf(" (uin324be) %d", ulbe))
}
var ulle uint32
if err := binary.Read(bytes.NewReader(v), binary.LittleEndian, &ulle); err == nil {
a = append(a, fmt.Sprintf(" (uin324le) %d", ulle))
}
}
default:
return n, a, fmt.Errorf("invalid type %d @ %d", t, o)
}
n++
}
}
func main() {
for _, f := range os.Args[1:] {
fmt.Printf("parsing %s\n", f)
d, err := ioutil.ReadFile(f)
if err != nil {
panic(err)
}
n, lines, err := decode(d, 0, 0)
if n > 0 && err == nil {
fmt.Printf("decoded %d fields\n", n)
if err != nil {
fmt.Printf("error was %s\n", err.Error())
}
fmt.Printf("\n")
for _, l := range lines {
fmt.Printf(" %s\n", l)
}
fmt.Printf("\n")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment