是否可以告诉 libfuzzer 忽略某些代码?

Is it possible to tell libfuzzer ignore certain code?

我使用 libfuzzer,到目前为止它是很棒的体验。 我在 fuzz 下的代码充满了这样的分支:

bool fuzzingThisFunc() {
  if(!checkSomething()) {
    fmt::printf("error log");
    return false;
  }

  ...

  return true;
}

其中 fmt::printf 是来自第三方库 (http://github.com/fmtlib/fmt) 的函数。

我觉得在几次迭代后模糊器进入这个函数并有效地开始模糊测试它里面的所有分支(就像它使用 DFS instead of BFS 时一样)。

我想向模糊器添加一些屏障或指令,以不将工具插入第三方库,因此我的模糊器将尝试仅覆盖我的代码。

可能吗?

Libfuzzer 支持源文件级别的检测。一个选项是构建没有 -fsanitize=fuzzer 标志的第三方库。 检查传递给这些库的配置的 CFLAGS,以删除此标志。

Header-only 库通常包含模板,fmt 就是这种情况。它们必须在编译时实例化。我认为没有简单的方法来处理这些。您可以找到所有使用过的模板参数,创建将它们与这些参数一起使用的 thunk 代码,从检测中排除此代码并修改您的调用代码以使用这些实例化的函数,但这非常困难。

当您不希望检测的代码仅执行日志记录或其他无需修改应用程序行为即可跳过的活动时,您可以使其成为编译的条件。 Libfuzzer 文档建议使用 FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION define 来标记您不想为模糊测试构建的代码。在 fmt 情况下,这将是:

bool fuzzingThisFunc() {
  if(!checkSomething()) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
    fmt::printf("error log");
#endif
    return false;
  }

  ...

  return true;
}

或修改库代码:

template <typename S, typename... Args,
          FMT_ENABLE_IF(detail::is_string<S>::value)>
inline int printf(const S& format_str, const Args&... args) {

#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  using context = basic_printf_context_t<char_t<S>>;
  return vprintf(to_string_view(format_str),
                 make_format_args<context>(args...));
#else
  return 0; //C printf returns number of characters written, I assume same for fmt.
#endif
}

第二种情况更容易编码(每个排除的函数一个修改),但每次获得新的 fmt 版本时都必须添加此修改。 在第一种情况下,您必须修改每个排除的函数调用站点。

对于这两种情况,您应该将 -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 添加到配置的 CFLAGS 中以构建模糊测试目标。