Skip to content

Instantly share code, notes, and snippets.

@ericychoi
Last active February 26, 2016 01:08
Show Gist options
  • Save ericychoi/2e298ce920ae00f59eaa to your computer and use it in GitHub Desktop.
Save ericychoi/2e298ce920ae00f59eaa to your computer and use it in GitHub Desktop.
Benchmark and compare regexp vs base64 decoding for a given payload
package base64Benchmark
import (
"bytes"
"encoding/base64"
"flag"
"io/ioutil"
"os"
"regexp"
"testing"
"unicode/utf8"
)
var filename string
var encodedContent string
var isVerbose bool
var regex *regexp.Regexp
var nRegex *regexp.Regexp
var charMap map[rune]struct{}
func TestMain(m *testing.M) {
flag.StringVar(&filename, "file", "input.txt", "input file for testing")
flag.BoolVar(&isVerbose, "verbose", false, "display filename and content")
flag.Parse()
// encode given file into base64
fi, err := os.Open(filename)
if err != nil {
panic(err)
}
defer fi.Close()
buf, _ := ioutil.ReadAll(fi)
var outBuf bytes.Buffer
encoder := base64.NewEncoder(base64.StdEncoding, &outBuf)
encoder.Write(buf)
encoder.Close()
encodedContent = outBuf.String()
// regex prep
regex = regexp.MustCompile("^[a-zA-Z0-9+/=]+$")
nRegex = regexp.MustCompile("[^a-zA-Z0-9+/=]+")
// manual matching prep
charMap = make(map[rune]struct{})
str := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/="
for _, r := range str {
charMap[r] = struct{}{}
}
os.Exit(m.Run())
}
func BenchmarkDecoder(b *testing.B) {
if isVerbose {
b.Logf("starting decoder with name: %s\n content %s\n", filename, encodedContent)
}
for i := 0; i < b.N; i++ {
if _, err := base64.StdEncoding.DecodeString(encodedContent); err != nil {
b.Errorf("encoding error: %s\n", err)
}
}
}
func BenchmarkRegex(b *testing.B) {
if isVerbose {
b.Logf("starting regex with name: %s\n content %s\n", filename, encodedContent)
}
for i := 0; i < b.N; i++ {
if !regex.MatchString(encodedContent) {
b.Error("string didn't match!\n")
}
}
}
func BenchmarkNegativeRegex(b *testing.B) {
if isVerbose {
b.Logf("starting neg regex with name: %s\n content %s\n", filename, encodedContent)
}
for i := 0; i < b.N; i++ {
if nRegex.MatchString(encodedContent) {
b.Error("string didn't match!\n")
}
}
}
func BenchmarkManualMatching(b *testing.B) {
if isVerbose {
b.Logf("starting manual matching with name: %s\n content %s\n", filename, encodedContent)
}
for i := 0; i < b.N; i++ {
bSlice := []byte(encodedContent)
for len(bSlice) > 0 {
r, size := utf8.DecodeRune(bSlice)
_, ok := charMap[r]
if !ok {
b.Errorf("string didn't match! %c\n", r)
}
bSlice = bSlice[size:]
}
}
}
// use range(string)
func BenchmarkManualMatching2(b *testing.B) {
if isVerbose {
b.Logf("starting manual matching2 with name: %s\n content %s\n", filename, encodedContent)
}
for i := 0; i < b.N; i++ {
for _, r := range encodedContent {
_, ok := charMap[r]
if !ok {
b.Errorf("string didn't match! %c\n", r)
}
}
}
}
func BenchmarkLengthCheck(b *testing.B) {
if isVerbose {
b.Logf("starting manual length check with name: %s\n content %s\n", filename, encodedContent)
}
for i := 0; i < b.N; i++ {
if len(encodedContent)%4 != 0 {
b.Errorf("string isn't base64! \n")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment