Last active
February 26, 2016 01:08
-
-
Save ericychoi/2e298ce920ae00f59eaa to your computer and use it in GitHub Desktop.
Benchmark and compare regexp vs base64 decoding for a given payload
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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