Skip to content

stefanovazzocell/bencode

Repository files navigation

Bencode

A fast and secure Go library to encode and parse Bencode.

Inspired by the great work done by @jackpal/bencode-go and @marksamman/bencode.

Examples

Here are some usage examples:

import "github.com/stefanovazzocell/bencode" // Parse a string bencode.NewParserFromString("10:helloworld").AsString() // "helloworld", nil // Parse an object bencode.NewParserFromString("d4:name5:Alice3:agei35ee").AsInterface() // map[string]{}{ "name": "Alice", "age": 35 }, nil // Parse a map from an io.Reader // fileReader implements io.Reader and returns "li1ei2ei3ee" bencode.NewParserFromReader(fileReader).AsList() // []interface{1, 2, 3} // Encode an object encoder, err := bencode.NewEncoderFromInterface([]interface{}{1,2,3}) if err != nil { // TODO: Handle error } encoder.String() // "li1ei2ei3ee"

Aims

As per the introduction I aim to make this library fast and secure. Here I will address how I plan to achieve those goals.

Secure

Since this library contains a parser that might be used to read user-generated content it's important for it to be well tested.

  • Near-100% code coverage (make test, coverage: up_to* 96.1%).
  • Extensively fuzzed (make fuzz, coverage: 99.3%).
  • Checked for security issues with gosec (make security).
  • No external dependencies

*up_to: one of the tests uses an intentionally unreliable io.Reader.

Performance

This library needs to perform well as it might need to encode/decode a large amount of data efficiently. Benchmarks are available with make bench.

$ make bench go test -run=^$ -cover -bench . goos: linux goarch: amd64 pkg: github.com/stefanovazzocell/bencode cpu: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz BenchmarkEncoder/torrentString-12 13454383 88.96 ns/op BenchmarkEncoder/complexMap-12 1384812 867.4 ns/op BenchmarkReaderParser/complexMap-12 545340 1873 ns/op BenchmarkReaderParser/torrentString-12 3972987 329.2 ns/op BenchmarkReaderParser/torrentStringAsString-12 4413070 269.6 ns/op BenchmarkStringParser/complexMap-12 730975 1386 ns/op BenchmarkStringParser/torrentString-12 14311644 77.85 ns/op BenchmarkStringParser/torrentStringAsString-12 26242033 42.01 ns/op 

Furthermore you can profile specific components with the following:

  • make profileEncoder
  • make profileStringParser

Caveats

There are some things to consider

  • This library can encode int and uint as well as all their variations (i.e.: int64, uint16, ...) but it can only parse numbers of type int.
  • This library can only encode maps of type map[string]interface{} and slices of type []interface{}.
  • Additional data after the initial parse will be ignored, unless another parse operation (such as .AsList()) is called on the same parser.
  • When parsing io.Reader strings are limited to ~8MB of size max.

About

An implementation of bencode in Go

Topics

Resources

License

Stars

Watchers

Forks