二 Syzkaller学习笔记---更新syz-manager(18)


这个函数是 repro 方法的一部分,它的作用是从执行日志中提取出触发崩溃的程序 。具体来说:
首先,该函数会对所有执行记录进行处理,找到每个进程(proc)所执行的最后一个程序,并将这些程序保存到变量中 。接下来,该函数会尝试按照一定顺序执行中的每个程序,并检查是否有任何简单的崩溃 。如果找到了崩溃程序,则返回包含相应信息的对象 。如果没有找到崩溃程序,且执行记录中包含多个程序,则尝试执行所有程序,并使用二分法()来检查哪些程序可能导致崩溃 。如果找到崩溃程序,则同样返回相应信息的对象 。最后,如果无论如何都无法找到崩溃程序,则返回 nil 。
需要注意的是,该函数在具体实现上使用了许多其他辅助函数和数据类型,如和等 。
()
调用链:ctx.() -> prog.()(重点函数)
位置:prog/.go: ()
功能:简化所有的调用和参数 。
说明:
// Minimize calls and arguments.func (ctx *context) minimizeProg(res *Result) (*Result, error) {res.Prog, _ = prog.Minimize(res.Prog, -1, true,
调用 也就是 prog/.go: ()
// Minimize minimizes program p into an equivalent program using the equivalence// predicate pred. It iteratively generates simpler programs and asks pred// whether it is equal to the original program or not. If it is equivalent then// the simplification attempt is committed and the process continues.func Minimize(p0 *Prog, callIndex0 int, crash bool, pred0 func(*Prog, int) bool) (*Prog, int) {pred := func(p *Prog, callIndex int) bool {p.sanitizeFix()// [1] 有些系统调用需要做一些特殊的处理 !!!p.debugValidate()return pred0(p, callIndex)}name0 := ""if callIndex0 != -1 {if callIndex0 < 0 || callIndex0 >= len(p0.Calls) {panic("bad call index")}name0 = p0.Calls[callIndex0].Meta.Name}// Try to remove all calls except the last one one-by-one.p0, callIndex0 = removeCalls(p0, callIndex0, crash, pred)// [2] 尝试逐个移除系统调用// Try to reset all call props to their default values.p0 = resetCallProps(p0, callIndex0, pred)// Try to minimize individual calls.for i := 0; i < len(p0.Calls); i++ {// [3] 去除系统调用的无关参数if p0.Calls[i].Meta.Attrs.NoMinimize {continue}ctx := &minimizeArgsCtx{target:p0.Target,p0:&p0,callIndex0: callIndex0,crash:crash,pred:pred,triedPaths: make(map[string]bool),}again:ctx.p = p0.Clone()ctx.call = ctx.p.Calls[i]for j, field := range ctx.call.Meta.Args {if ctx.do(ctx.call.Args[j], field.Name, "") {// [4] 在do函数中,根据不同的参数类型调用不同的minimize函数 !!!goto again}}p0 = minimizeCallProps(p0, i, callIndex0, pred)}if callIndex0 != -1 {if callIndex0 < 0 || callIndex0 >= len(p0.Calls) || name0 != p0.Calls[callIndex0].Meta.Name {panic(fmt.Sprintf("bad call index after minimization: ncalls=%v index=%v call=%v/%v",len(p0.Calls), callIndex0, name0, p0.Calls[callIndex0].Meta.Name))}}return p0, callIndex0}
这个函数实现了程序的最小化,旨在将一个程序简化为与其等价的最小形式 。具体来说:
首先,该函数尝试逐个删除所有调用,直到只剩下最后一个调用 。在每次删除前,调用 pred 判断是否仍然等效,如果是,则继续删除操作 。接下来,该函数尝试将所有调用的属性重置为默认值,并再次调用 pred 判断是否仍然等效 。最后,该函数对每个调用进行单独的最小化操作 。对于每个调用,它会将参数传递给 do 方法,并生成新的程序 。如果 pred 返回 true,则表示新程序仍然等效,此时重复上述过程,直到不能再进一步简化为止 。
需要注意的是,该函数在具体实现上使用了许多其他辅助函数和数据类型,如和等 。
()
调用链:ctx.() -> ctx.() -> inst.() -> .Write() & .() & inst.()