使用Golang编译带有覆盖率检测的模糊测试

使用Golang编译带有覆盖率检测的模糊测试 我想构建一个独立的模糊测试二进制文件,以便在 Docker 容器中使用。

然而,二进制文件会提示测试二进制文件未使用覆盖率检测构建,因此模糊测试将在没有覆盖率指导的情况下运行,可能效率低下

我希望启用覆盖率检测。

示例测试:

package main

import (
	"bytes"
	"crypto/sha256"
	"testing"
)

func FuzzFoobar(f *testing.F) {
	f.Fuzz(func(t *testing.T, data []byte) {
		// 调用一些任意方法
		data = sha256.New().Sum(bytes.ToLower(data))
		if len(data) == 0 {
			panic(1)
		}
	})
}

正常运行时没有问题:

$ go test . -fuzz Foo
fuzz: elapsed: 0s, gathering baseline coverage: 0/66 completed
fuzz: elapsed: 0s, gathering baseline coverage: 66/66 completed, now fuzzing with 8 workers
^Cfuzz: elapsed: 3s, execs: 107197 (39642/sec), new interesting: 8 (total: 74)

编译它时会产生警告:

$ go test  -c .
$ ./testfuzz.test -test.fuzz=Foo -test.fuzzcachedir=/tmp
warning: the test binary was not built with coverage instrumentation, so fuzzing will run without coverage guidance and may be inefficient
warning: starting with empty corpus
fuzz: elapsed: 0s, execs: 0 (0/sec)

如果我尝试在编译时使用-cover,也没有帮助:

$ go test -cover -c .
$ ./testfuzz.test -test.fuzz=Foo -test.fuzzcachedir=/tmp
warning: the test binary was not built with coverage instrumentation, so fuzzing will run without coverage guidance and may be inefficient
warning: starting with empty corpus
fuzz: elapsed: 0s, execs: 0 (0/sec)

更多关于使用Golang编译带有覆盖率检测的模糊测试的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于使用Golang编译带有覆盖率检测的模糊测试的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


要编译带有覆盖率检测的模糊测试二进制文件,需要使用 go test -c 并设置 -cover 标志,同时还需要启用模糊测试的覆盖率检测。以下是解决方案:

// 编译命令
go test -c -cover -covermode=atomic -coverpkg=./...

// 运行编译后的二进制文件
./testfuzz.test -test.fuzz=Foo -test.fuzzcachedir=/tmp -test.parallel=1

完整示例:

package main

import (
    "bytes"
    "crypto/sha256"
    "testing"
)

func FuzzFoobar(f *testing.F) {
    f.Add([]byte("seed"))
    
    f.Fuzz(func(t *testing.T, data []byte) {
        // 调用一些任意方法
        data = sha256.New().Sum(bytes.ToLower(data))
        if len(data) == 0 {
            t.Fatal("empty data")
        }
    })
}

编译和运行步骤:

# 编译带有覆盖率检测的模糊测试二进制文件
go test -c -cover -covermode=atomic -coverpkg=./... -o fuzzer.test

# 运行模糊测试
./fuzzer.test -test.fuzz=Foo -test.fuzzcachedir=./fuzz-cache -test.parallel=1

# 或者使用更详细的运行命令
./fuzzer.test -test.v -test.fuzz=Foo -test.fuzzcachedir=./fuzz-cache -test.fuzztime=30s

如果需要生成覆盖率报告:

# 运行测试并生成覆盖率数据
./fuzzer.test -test.fuzz=Foo -test.fuzzcachedir=./fuzz-cache -test.fuzztime=10s -test.outputdir=./coverage

# 查看覆盖率报告
go tool cover -html=./coverage/coverage.cov

对于 Docker 容器使用,可以创建 Dockerfile:

FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY . .
RUN go test -c -cover -covermode=atomic -coverpkg=./... -o /fuzzer.test

FROM alpine:latest
COPY --from=builder /fuzzer.test /fuzzer.test
ENTRYPOINT ["/fuzzer.test", "-test.fuzz=Foo", "-test.fuzzcachedir=/fuzz-cache"]

关键点:

  1. 必须使用 -covermode=atomic 标志来支持并发执行
  2. -coverpkg=./... 确保所有包都启用覆盖率检测
  3. 运行二进制文件时需要指定 -test.parallel=1 以避免覆盖率数据竞争
  4. 模糊测试的覆盖率检测需要 Go 1.20 或更高版本
回到顶部