Skip to content

Commit

Permalink
initial commit for enhancing fuzz tests
Browse files Browse the repository at this point in the history
Signed-off-by: Sepehrdad Sh <26747519+sepehrdaddev@users.noreply.github.com>
  • Loading branch information
sepehrdaddev committed Nov 21, 2023
1 parent 69f2b6a commit a8f05b9
Show file tree
Hide file tree
Showing 13 changed files with 417 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ _test_plugins_fail/%.so: _test_plugins_fail/%.go

.PHONY: fuzz
fuzz: ## run all fuzz tests
for p in $(PACKAGES); do go test -run=NONE -fuzz=Fuzz -fuzztime 30s $$p; done
$(MAKE) -C fuzz $(MAKECMDGOALS)

.PHONY: lint
lint: build staticcheck ## run all linters
Expand Down
18 changes: 18 additions & 0 deletions fuzz/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM golang:buster

WORKDIR /workspace

COPY . .

ENV DEBIAN_FRONTEND=noninteractive \
CC=clang

RUN apt-get update && apt-get install -y make clang && \
go install github.com/mdempsky/go114-fuzz-build@latest && \
apt-get autoremove --purge -y && apt-get autoclean && \
go mod init fuzz && go mod tidy && \
/usr/bin/make all

ENTRYPOINT [ "/usr/bin/make" ]

CMD ["fuzz", "FUZZ_TARGETS=FuzzParseEskip"]
62 changes: 62 additions & 0 deletions fuzz/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
MKDIR = mkdir -p
GO_FUZZ_BUILD ?= go114-fuzz-build

PREFIX ?= $(CURDIR)
ARTIFACTS_PATH = $(PREFIX)/artifacts
DICTIONARY_PATH = $(PREFIX)/dictionaries
CORPUS_PATH = $(PREFIX)/corpus
FUZZ_TARGETS_PATH = $(PREFIX)/fuzz_targets

FUZZ_TARGETS ?= FuzzParseCIDRs FuzzParseEskip FuzzParseFilters \
FuzzParseIngressV1JSON FuzzParseJwt \
FuzzParsePredicates FuzzParseRouteGroupsJSON \
FuzzServer

FUZZ_SANITIZER ?= address
FUZZ_FORKS ?= 2
FUZZ_MAX_TOTAL_TIME ?= 600
FUZZ_RUNS ?= -1
FUZZER_ARGS ?= -artifact_prefix=$(ARTIFACTS_PATH) \
-rss_limit_mb=2560 -timeout=25 \
-max_total_time=$(FUZZ_MAX_TOTAL_TIME) \
-len_control=0 -detect_leaks=0 -max_len=4096 \
-fork=$(FUZZ_FORKS) -runs=$(FUZZ_RUNS)

ifeq ($(FUZZ_SANITIZER), address)
FUZZ_BUILD_ARGS = -fsanitize=fuzzer -fsanitize=address -fsanitize-address-use-after-scope
else ifeq ($(FUZZ_SANITIZER), undefined)
FUZZ_BUILD_ARGS = -fsanitize=fuzzer -fsanitize=array-bounds,bool,builtin,enum,float-divide-by-zero,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr -fno-sanitize-recover=array-bounds,bool,builtin,enum,float-divide-by-zero,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr
else ifeq ($(FUZZ_SANITIZER), memory)
FUZZ_BUILD_ARGS = -fsanitize=fuzzer -fsanitize=memory -fsanitize-memory-track-origins
else
$(error $(FUZZ_SANITIZER) is invalid sanitizer, available options are address, undefined, memory)
endif

export ASAN_OPTIONS = alloc_dealloc_mismatch=0:allocator_may_return_null=1:allocator_release_to_os_interval_ms=500:check_malloc_usable_size=0:detect_container_overflow=1:detect_odr_violation=0:detect_leaks=1:detect_stack_use_after_return=1:fast_unwind_on_fatal=0:handle_abort=1:handle_segv=1:handle_sigill=1:max_uar_stack_size_log=16:print_scariness=1:quarantine_size_mb=10:strict_memcmp=1:symbolize=1:use_sigaltstack=1:dedup_token_length=3
export UBSAN_OPTIONS = print_stacktrace=1:print_summary=1:silence_unsigned_overflow=1:symbolize=1:dedup_token_length=3
export MSAN_OPTIONS = print_stats=1:symbolize=1:dedup_token_length=3

.PHONY: help all fuzz clean
default: all

help: ## display this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

all: $(FUZZ_TARGETS:=.out) ## build all fuzz binaries

%.a:
$(GO_FUZZ_BUILD) -func $(@:.a=) -o $@ $(FUZZ_TARGETS_PATH)

%.out: %.a
$(CC) $(FUZZ_BUILD_ARGS) -lresolv $< -o $@

fuzz: $(FUZZ_TARGETS:=.out) ## run all fuzz tests
for TARGET in $(FUZZ_TARGETS); do \
$(MKDIR) $(CORPUS_PATH)/$$TARGET $(ARTIFACTS_PATH); \
ARGS="$(FUZZER_ARGS)"; \
[ -f "$(DICTIONARY_PATH)/$$TARGET.dict" ] && ARGS="$$ARGS -dict=$(DICTIONARY_PATH)/$$TARGET.dict"; \
$(PREFIX)/$$TARGET.out $$ARGS $(CORPUS_PATH)/$$TARGET; \
done

clean: ## clean temporary files and directories
$(RM) $(PREFIX)/*.out $(PREFIX)/*.h $(PREFIX)/main.*.go
3 changes: 3 additions & 0 deletions fuzz/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Fuzzing

This directory contains a set of dictionaries and fuzz targets along with other tooling to fuzz skipper.
188 changes: 188 additions & 0 deletions fuzz/dictionaries/FuzzParseEskip.dict
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
"&&"
"*"
"->"
")"
":"
","
"("
";"
"<shunt>"
"<loopback>"
"<dynamic>"
"<"
">"
"backendIsProxy"
"modRequestHeader"
"setRequestHeader"
"appendRequestHeader"
"dropRequestHeader"
"modResponseHeader"
"setResponseHeader"
"appendResponseHeader"
"dropResponseHeader"
"setContextRequestHeader"
"appendContextRequestHeader"
"setContextResponseHeader"
"appendContextResponseHeader"
"copyRequestHeader"
"copyResponseHeader"
"modPath"
"setPath"
"redirectTo"
"redirectToLower"
"static"
"stripQuery"
"preserveHost"
"status"
"compress"
"decompress"
"setQuery"
"dropQuery"
"inlineContent"
"inlineContentIfStatus"
"flowId"
"xforward"
"xforwardFirst"
"randomContent"
"repeatContent"
"repeatContentHex"
"wrapContent"
"wrapContentHex"
"backendTimeout"
"readTimeout"
"writeTimeout"
"blockContent"
"blockContentHex"
"latency"
"bandwidth"
"chunks"
"backendLatency"
"backendBandwidth"
"backendChunks"
"absorb"
"absorbSilent"
"uniformRequestLatency"
"uniformResponseLatency"
"normalRequestLatency"
"normalResponseLatency"
"histogramRequestLatency"
"histogramResponseLatency"
"logHeader"
"tee"
"teenf"
"teeLoopback"
"sed"
"sedDelim"
"sedRequest"
"sedRequestDelim"
"basicAuth"
"webhook"
"oauthTokeninfoAnyScope"
"oauthTokeninfoAllScope"
"oauthTokeninfoAnyKV"
"oauthTokeninfoAllKV"
"oauthTokenintrospectionAnyClaims"
"oauthTokenintrospectionAllClaims"
"oauthTokenintrospectionAnyKV"
"oauthTokenintrospectionAllKV"
"secureOauthTokenintrospectionAnyClaims"
"secureOauthTokenintrospectionAllClaims"
"secureOauthTokenintrospectionAnyKV"
"secureOauthTokenintrospectionAllKV"
"forwardToken"
"forwardTokenField"
"oauthGrant"
"grantCallback"
"grantLogout"
"grantClaimsQuery"
"jwtValidation"
"oauthOidcUserInfo"
"oauthOidcAnyClaims"
"oauthOidcAllClaims"
"oidcClaimsQuery"
"dropRequestCookie"
"dropResponseCookie"
"requestCookie"
"responseCookie"
"jsCookie"
"consecutiveBreaker"
"rateBreaker"
"disableBreaker"
"admissionControl"
"clientRatelimit"
"ratelimit"
"clusterClientRatelimit"
"clusterRatelimit"
"clusterLeakyBucketRatelimit"
"backendRatelimit"
"ratelimitFailClosed"
"lua"
"corsOrigin"
"headerToQuery"
"queryToHeader"
"disableAccessLog"
"enableAccessLog"
"auditLog"
"unverifiedAuditLog"
"setDynamicBackendHostFromHeader"
"setDynamicBackendSchemeFromHeader"
"setDynamicBackendUrlFromHeader"
"setDynamicBackendHost"
"setDynamicBackendScheme"
"setDynamicBackendUrl"
"apiUsageMonitoring"
"fifo"
"lifo"
"lifoGroup"
"rfcPath"
"rfcHost"
"bearerinjector"
"tracingBaggageToTag"
"stateBagToTag"
"tracingTag"
"tracingTagFromResponse"
"tracingSpanName"
"originMarker"
"fadeIn"
"endpointCreated"
"consistentHashKey"
"consistentHashBalanceFactor"
"opaAuthorizeRequest"
"opaServeResponse"
"healthcheck"
"setFastCgiFilename"
"disableRatelimit"
"unknownRatelimit"
"Path"
"PathSubtree"
"PathRegexp"
"Host"
"HostAny"
"ForwardedHost"
"ForwardedProtocol"
"Weight"
"True"
"False"
"Shutdown"
"Method"
"Methods"
"Header"
"HeaderRegexp"
"Cookie"
"JWTPayloadAnyKV"
"JWTPayloadAllKV"
"JWTPayloadAnyKVRegexp"
"JWTPayloadAllKVRegexp"
"HeaderSHA256"
"After"
"Before"
"Between"
"Cron"
"QueryParam"
"Source"
"SourceFromLast"
"ClientIP"
"Tee"
"Traffic"
"TrafficSegment"
"ContentLengthBetween"
14 changes: 14 additions & 0 deletions fuzz/fuzz_targets/FuzzParseCIDRs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//go:build gofuzz
// +build gofuzz

package fuzz

import "github.com/zalando/skipper/net"

func FuzzParseCIDRs(data []byte) int {
if _, err := net.ParseCIDRs([]string{string(data)}); err != nil {
return 0
}

return 1
}
14 changes: 14 additions & 0 deletions fuzz/fuzz_targets/FuzzParseEskip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//go:build gofuzz
// +build gofuzz

package fuzz

import "github.com/zalando/skipper/eskip"

func FuzzParseEskip(data []byte) int {
if _, err := eskip.Parse(string(data)); err != nil {
return 0
}

return 1
}
14 changes: 14 additions & 0 deletions fuzz/fuzz_targets/FuzzParseFilters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//go:build gofuzz
// +build gofuzz

package fuzz

import "github.com/zalando/skipper/eskip"

func FuzzParseFilters(data []byte) int {
if _, err := eskip.ParseFilters(string(data)); err != nil {
return 0
}

return 1
}
16 changes: 16 additions & 0 deletions fuzz/fuzz_targets/FuzzParseIngressV1JSON.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//go:build gofuzz
// +build gofuzz

package fuzz

import (
"github.com/zalando/skipper/dataclients/kubernetes/definitions"
)

func FuzzParseIngressV1JSON(data []byte) int {
if _, err := definitions.ParseIngressV1JSON(data); err != nil {
return 0
}

return 1
}
14 changes: 14 additions & 0 deletions fuzz/fuzz_targets/FuzzParseJwt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//go:build gofuzz
// +build gofuzz

package fuzz

import "github.com/zalando/skipper/jwt"

func FuzzParseJwt(data []byte) int {
if _, err := jwt.Parse(string(data)); err != nil {
return 0
}

return 1
}
14 changes: 14 additions & 0 deletions fuzz/fuzz_targets/FuzzParsePredicates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//go:build gofuzz
// +build gofuzz

package fuzz

import "github.com/zalando/skipper/eskip"

func FuzzParsePredicates(data []byte) int {
if _, err := eskip.ParsePredicates(string(data)); err != nil {
return 0
}

return 1
}
16 changes: 16 additions & 0 deletions fuzz/fuzz_targets/FuzzParseRouteGroupsJSON.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//go:build gofuzz
// +build gofuzz

package fuzz

import (
"github.com/zalando/skipper/dataclients/kubernetes/definitions"
)

func FuzzParseRouteGroupsJSON(data []byte) int {
if _, err := definitions.ParseRouteGroupsJSON(data); err != nil {
return 0
}

return 1
}
Loading

0 comments on commit a8f05b9

Please sign in to comment.