当前位置: 首页 > news >正文

【Go语言成长之路】 模糊测试

文章目录

  • 模糊测试
    • 一、前提
    • 二、创建项目
    • 三、添加待测试代码
    • 四、添加单元测试
    • 五、添加模糊测试

模糊测试

​ 本教程介绍了 Go 中模糊测试的基础知识。通过模糊测试,随机数据会针对您的测试运行,以尝试找到漏洞或导致崩溃的输入。可以通过模糊测试发现的漏洞示例包括 SQL 注入、缓冲区溢出、拒绝服务和跨站点脚本攻击。

注:Go语言中模糊测试已经内置,具体可以参考: Go Fuzzing docs, 将来还会添加更多功能。

一、前提

  • Go1.18以及之后。
  • 支持模糊测试的环境。目前,使用覆盖率检测进行模糊测试仅适用于 AMD64 和 ARM64 架构。

二、创建项目

~$ mkdir fuzz
~$ cd fuzz/
~/fuzz$ go mod init example/fuzz
go: creating new go.mod: module example/fuzz

三、添加待测试代码

package mainimport "fmt"// accept a string, loop over it a byte at a time, and return the reversed string at the end.
func Reverse(s string) string {b := []byte(s)for i, j := 0, len(b)-1; i < len(b)/2; i, j = i+1, j-1 {b[i], b[j] = b[j], b[i]}return string(b)
}func main() {input := "The quick brown fox jumped over the lazy dog"rev := Reverse(input)doubleRev := Reverse(rev)fmt.Printf("original: %q\n", input)fmt.Printf("reversed: %q\n", rev)fmt.Printf("reversed again: %q\n", doubleRev)
}

运行代码:

~/fuzz$ go run ./fuzz
original: "The quick brown fox jumped over the lazy dog"
reversed: "god yzal eht revo depmuj xof nworb kciuq ehT"
reversed again: "The quick brown fox jumped over the lazy dog"

四、添加单元测试

为 Reverse 函数编写基本单元测试,在fuzz文件夹内新建一个测试文件reverse_test.go

package mainimport ("testing"
)func TestReverse(t *testing.T) {testcases := []struct {in, want string}{{"Hello, world", "dlrow ,olleH"},{" ", " "},{"!12345", "54321!"},}for _, tc := range testcases {rev := Reverse(tc.in)if rev != tc.want {t.Errorf("Reverse: %q, want %q", rev, tc.want)}}
}

这个简单的测试将断言列出的输入字符串将被正确反转。

之后运行测试代码:

~/fuzz$ go test . -v
=== RUN   TestReverse
--- PASS: TestReverse (0.00s)
PASS
ok      example/fuzz    0.003s

五、添加模糊测试

​ 单元测试有局限,即每个输入都必须由开发人员添加到测试中,使用模糊测试的好处就是可以为代码提供输入,并且可以识别测试用例没有达到边缘情况。

注:单元测试、基准测试和模糊测试可以保留在同一个*_test.go文件中。

​ 编写的模糊测试函数代码如下:

func FuzzReverse(f *testing.F) {testcases := []string{"Hello, world", " ", "!12345"}for _, tc := range testcases {f.Add(tc)  // Use f.Add to provide a seed corpus}f.Fuzz(func(t *testing.T, orig string) {rev := Reverse(orig)doubleRev := Reverse(rev)if orig != doubleRev {t.Errorf("Before: %q, after: %q", orig, doubleRev)}if utf8.ValidString(orig) && !utf8.ValidString(rev) {t.Errorf("Reverse produced invalid UTF-8 string %q", rev)}})
}

使用模糊测试有如下几个特点:

  • 无法预测结果。因为无法控制模糊测试的输入

  • 可以验证函数的属性,在本例中可以检查的属性有:

    • 将字符串反转两次可以保留原始值
    • 反转的字符串将其状态保留为有效的 UTF-8。

请注意单元测试和模糊测试之间的语法差异:

  • 该函数以 FuzzXxx 而不是TestXxx开头,并采用 *testing.F 而不是 *testing.T
  • 将 t.Run 替换为 f.Fuzz,它采用了一个模糊目标函数,其参数为 *testing.T 和要模糊的类型。使用 f.Add 将单元测试的输入作为种子语料库输入提供。

之后就可以运行模糊测试并查看结果:

~/fuzz$ go test ./fuzz -v
=== RUN   TestReverse
--- PASS: TestReverse (0.00s)
=== RUN   FuzzReverse
=== RUN   FuzzReverse/seed#0
=== RUN   FuzzReverse/seed#1
=== RUN   FuzzReverse/seed#2
--- PASS: FuzzReverse (0.00s)--- PASS: FuzzReverse/seed#0 (0.00s)--- PASS: FuzzReverse/seed#1 (0.00s)--- PASS: FuzzReverse/seed#2 (0.00s)
PASS
ok      example/fuzz    0.003s

如果你只想运行模糊测试,那么可以执行如下命令:

~/fuzz$ go test . -run=FuzzReverse -v # 运行特定的函数
=== RUN   FuzzReverse
=== RUN   FuzzReverse/seed#0
=== RUN   FuzzReverse/seed#1
=== RUN   FuzzReverse/seed#2
--- PASS: FuzzReverse (0.00s)--- PASS: FuzzReverse/seed#0 (0.00s)--- PASS: FuzzReverse/seed#1 (0.00s)--- PASS: FuzzReverse/seed#2 (0.00s)
PASS
ok      example/fuzz    0.003s 
~/fuzz$go test -fuzz=Fuzz . -v # 只运行模糊测试
=== RUN   TestReverse
--- PASS: TestReverse (0.00s)
=== RUN   FuzzReverse
fuzz: elapsed: 0s, gathering baseline coverage: 0/3 completed
fuzz: elapsed: 0s, gathering baseline coverage: 3/3 completed, now fuzzing with 8 workers
fuzz: elapsed: 0s, execs: 253 (10168/sec), new interesting: 2 (total: 5)
--- FAIL: FuzzReverse (0.03s)--- FAIL: FuzzReverse (0.00s)reverse_test.go:36: Reverse produced invalid UTF-8 string "\xa3\xd6"Failing input written to testdata/fuzz/FuzzReverse/14a85158d50021f3To re-run:go test -run=FuzzReverse/14a85158d50021f3
=== NAME  
FAIL
exit status 1
FAIL    example/fuzz    0.029s

​ 另一个有用的标志是 -fuzztime,它限制模糊测试所需的时间, 若没有指定模糊测试的运行时间,那么它将会一直运行下去,直到发生错误。

​ 模糊测试时发生故障,导致问题的输入被写入种子语料库文件,该文件将在下次调用 go test 时运行,即使没有 -fuzz 标志也是如此。要查看导致失败的输入,请在文本编辑器中打开写入 testdata/fuzz/FuzzReverse目录的语料库文件。您的种子语料库文件可能包含不同的字符串,但格式将相同, 类型如下:

go test fuzz v1
string("֣")

​ 语料库文件的第一行表示编码版本。接下来的每一行代表构成语料库条目的每种类型的值。由于模糊目标仅需要 1 个输入,因此版本后只有 1 个值。

​ 再次运行 go test,不带 -fuzz 标志;将使用新的失败种子语料库条目:

~/fuzz$ go test ./fuzz
--- FAIL: FuzzReverse (0.00s)--- FAIL: FuzzReverse/14a85158d50021f3 (0.00s)reverse_test.go:36: Reverse produced invalid UTF-8 string "\xa3\xd6"
FAIL
FAIL    example/fuzz    0.003s
FAIL

若想使用原来失败的语料种子,可以执行如下命令:

~/fuzz$ go test -run=FuzzReverse/28f36ef487f23e6c7a81ebdaa9feffe2f2b02b4cddaa6252e87f69863046a5e0
input: "\x91"
runes: ['�']
input: "�"
runes: ['�']
--- FAIL: FuzzReverse (0.00s)--- FAIL: FuzzReverse/28f36ef487f23e6c7a81ebdaa9feffe2f2b02b4cddaa6252e87f69863046a5e0 (0.00s)reverse_test.go:16: Number of runes: orig=1, rev=1, doubleRev=1reverse_test.go:18: Before: "\x91", after: "�"
FAIL
exit status 1
FAIL    example/fuzz    0.145s

之后就是定位问题并解决了。

遇到错误的几点建议:

  • 诊断错误

    有如下几种方法:

    • 通过VS Code设置调试器进行调查(遇到比较棘手的错误可以使用此方法)

    • 将把有用的调试信息记录到您的终端

      比如说使用t.LogF将错误相关的内容打印出来,或者如果发生错误,或者使用 -v 执行测试,此 t.Logf 行将打印到命令行,这可以帮助您调试此特定问题。

  • 解决错误

相关文章:

【Go语言成长之路】 模糊测试

文章目录 模糊测试一、前提二、创建项目三、添加待测试代码四、添加单元测试五、添加模糊测试 模糊测试 ​ 本教程介绍了 Go 中模糊测试的基础知识。通过模糊测试&#xff0c;随机数据会针对您的测试运行&#xff0c;以尝试找到漏洞或导致崩溃的输入。可以通过模糊测试发现的漏…...

异或运算的高级应用和Briankernighan算法

本篇文章主要回顾一下计算机的位运算&#xff0c;处理一些位运算的巧妙操作。 特别提醒&#xff1a;实现位运算要注意溢出和符号扩展等问题。 先看一个好玩的问题&#xff1a; $Problem1 $ 黑白球概率问题 袋子里一共a个白球&#xff0c;b个黑球&#xff0c;每次从袋子里拿…...

音视频入门基础:WAV专题(9)——FFmpeg源码中计算WAV音频文件每个packet的duration和duration_time的实现

一、引言 从文章《音视频入门基础&#xff1a;WAV专题&#xff08;6&#xff09;——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道&#xff0c;通过FFprobe命令可以显示WAV音频文件每个packet&#xff08;也称为数据包或多媒体包&#xff09;的信息&#xff0…...

AI写的论文查重率高吗?分享6款实测AI论文生成免费网站

在当今学术研究和论文写作领域&#xff0c;AI技术的迅猛发展为研究人员提供了极大的便利。特别是AI论文自动生成助手&#xff0c;它们不仅能够提高写作效率&#xff0c;还能帮助生成高质量的论文内容。以下是六款经过实测且免费的AI论文生成网站推荐&#xff1a; 一、千笔-AIP…...

【专题】2024年8月中国企业跨境、出海、国际化、全球化行业报告汇总PDF合集分享(附原数据表)

原文链接&#xff1a; https://tecdat.cn/?p37584 在全球化浪潮汹涌澎湃的当下&#xff0c;中国企业积极探索海外市场&#xff0c;开启了出海跨境的新征程。本报告合集旨在全面梳理出海跨境全球化行业的发展态势&#xff0c;涵盖多个领域的深度洞察。 从游戏、快消品、医疗器…...

[算法]单调栈解法

目录 739. 每日温度 - 力扣&#xff08;LeetCode&#xff09; 42. 接雨水 - 力扣&#xff08;LeetCode&#xff09; 84. 柱状图中最大的矩形 - 力扣&#xff08;LeetCode&#xff09; 739. 每日温度 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; 通常是一维数…...

构建数据安全防线:MySQL数据备份策略的文档化实践

在数据驱动的商业环境中&#xff0c;数据备份策略是确保数据安全和业务连续性的关键。MySQL&#xff0c;作为广泛使用的数据库管理系统&#xff0c;其数据备份策略的文档化对于规范备份流程、提高恢复效率和满足合规要求至关重要。本文将深入探讨如何在MySQL中实现数据备份的策…...

4. GIS前端工程师岗位职责、技术要求和常见面试题

本系列文章目录&#xff1a; 1. GIS开发工程师岗位职责、技术要求和常见面试题 2. GIS数据工程师岗位职责、技术要求和常见面试题 3. GIS后端工程师岗位职责、技术要求和常见面试题 4. GIS前端工程师岗位职责、技术要求和常见面试题 5. GIS工程师岗位职责、技术要求和常见面试…...

软件测试-Selenium+python自动化测试

目录 会用到谷歌浏览器Chrome测试,需要下载一个Chromedriver(Chrome for Testing availability)对应自己的浏览器版本号选择。 一、元素定位 对html网页中的元素进行定位,同时进行部分操作。 1.1一个简单的模板 from selenium import webdriver from selenium.webdrive…...

SpringBoot与Minio的极速之旅:解锁文件切片上传新境界

目录 一、前言 二、对象存储&#xff08;Object Storage&#xff09;介绍 &#xff08;1&#xff09;对象存储的特点 &#xff08;2&#xff09;Minio 与对象存储 &#xff08;3&#xff09;对象存储其他存储方式的区别 &#xff08;4&#xff09;对象存储的应用场景 三、…...

Java 7.3 - 分布式 id

分布式 ID 介绍 什么是 ID&#xff1f; ID 就是 数据的唯一标识。 什么是分布式 ID&#xff1f; 分布式 ID 是 分布式系统中的 ID&#xff0c;它不存在于现实生活&#xff0c;只存在于分布式系统中。 分库分表&#xff1a; 一个项目&#xff0c;在上线初期使用的是单机 My…...

144. 腾讯云Redis数据库

文章目录 一、Redis 的主要功能特性二、Redis 的典型应用场景三、Redis 的演进过程四、Redis 的架构设计五、Redis 的数据类型及操作命令六、腾讯云数据库 Redis七、总结 Redis 是一种由 C 语言开发的 NoSQL 数据库&#xff0c;以其高性能的键值对存储和多种应用场景而闻名。本…...

基于单片机的自动浇花控制写设计任务书

一、内容要求&#xff1a; 任务 随着社会的进步&#xff0c;人们的生活质量越来越高。在家里养养盆花可以陶冶情操&#xff0c;丰富生活。同时盆花可以通过光合作用吸收二氧化碳&#xff0c;净化室内空气&#xff0c;在有花木的地方空气中阴离子聚集较多&#xff0c;所以空气…...

从零到精通:用C++ STL string优化代码

目录 1:为什么要学习string类 2:标准库中的string类 2.1:string类(了解) 2.2:总结 3:string类的常用接口 3.1:string类对象的常见构造 3.1.1:代码1 3.1.2:代码2 3.2:string类对象的遍历操作 3.2.1:代码1(begin end) 3.2.2:代码2(rbegin rend) 3.3:string类对象的…...

鸿蒙轻内核M核源码分析系列五 时间管理

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 持续更新中…… 在鸿蒙轻内核源码分析上一篇文章中&#xff0c;我们剖析了中断的源码&#xff0c;简单提到了Tick中断。本文会继续分析Tick和时间相关的源…...

Python Opencv鼠标回调

使用 OpenCV 的 cv2.setMouseCallback() 方法来捕捉鼠标事件&#xff0c;并实现以下功能&#xff1a; 实时在鼠标指针附近显示其位置的像素坐标。通过左键双击&#xff0c;将像素坐标记录到数组中。通过右键点击&#xff0c;取消上一次添加的坐标。 下面是实现代码的示例&…...

Ubuntu环境的MySql下载安装

下载压缩包 此文章下载的mysql版本位5.7.29 sudo wget https://downloads.mysql.com/archives/get/p/23/file/mysql-server_5.7.29-1ubuntu18.04_amd64.deb-bundle.tar解压缩 sudo tar -xvf mysql-server_5.7.29-1ubuntu18.04_amd64.deb-bundle.tar命令解释 -x&#xff1a;…...

Android系统去掉WIFI模块

先说应用场景&#xff0c;有些特定设备&#xff0c;不能连接wifi。需要隐藏的模块&#xff0c;QS面板模块的wifi,还有设置里面的wifi.由于QS属于SystemUI&#xff0c;熟悉SystemUI之后&#xff0c;就可以直接去SystemUi那里找&#xff0c;找到QSTitle 默认配置的地方。 一、…...

代码随想录 -- 二叉树 -- 翻转二叉树

226. 翻转二叉树 - 力扣&#xff08;LeetCode&#xff09; 递归比较简单 class Solution(object):def invertTree(self, root):if rootNone:returnnode rootif node.left or node.right:tempnode.leftnode.leftnode.rightnode.righttempself.invertTree(node.left)self.inve…...

Node.js之文件复制

1.方式一&#xff1a;readFile // 导入fs模块 const fs require("fs") // 导入process模块 const process require("process")// 读取文件内容 let data fs.writeFileSync(./test.txt) // 写入文件内容 fs.writeFileSync(./test1.txt, data) 2.方式二&…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...