Add AFL_LLVM_WHITELIST_FNMATCH env var
Only enable UNIX pattern matching on the whitelist when
AFL_LLVM_WHITELIST_FNMATCH is set. The reason being that we keep
backwards compatibility with old whitelists.
MODIFY
llvm_mode/README.whitelist.md
llvm_mode/README.whitelist.md
@@ -73,3 +73,32 @@ For old LLVM versions this feature might require to be compiled with debug
information (-g), however at least from llvm version 6.0 onwards this is not
required anymore (and might hurt performance and crash detection, so better not
use -g).
+
+## 4) UNIX-style file name pattern matching
+By default you need to add all the files you want to whitelist to the file
+specified by AFL_LLVM_WHITELIST. By setting the env variable
+AFL_LLVM_WHITELIST_FNMATCH, afl++ will allows use of wildcards and other
+matching features available through `fnmatch` (we use `fnmatch` with no flags
+set). Note that setting AFL_LLVM_WHITELIST_FNMATCH might
+break backwards-compatibility, since it does not match on the end of the file
+entry anymore, but rather matches on the full filename path.
+
+The behavior should be the same if you prepend `*/` to every line.
+
+For example, the entry:
+```
+*/a*.cpp
+```
+
+Would now match:
+```
+feature_a/a1.cpp
+feature_a/a2.cpp
+```
+
+But
+```
+a*.cpp
+```
+
+Would not match any of the files in the previous example.

MODIFY
llvm_mode/afl-llvm-common.cc
llvm_mode/afl-llvm-common.cc
@@ -147,20 +147,25 @@ bool isInWhitelist(llvm::Function *F) {
/* Continue only if we know where we actually are */
if (!instFilename.str().empty()) {
+ char *enable_fnmatch = getenv("AFL_LLVM_WHITELIST_FNMATCH");
+
for (std::list<std::string>::iterator it = myWhitelist.begin();
it != myWhitelist.end(); ++it) {
/* We don't check for filename equality here because
* filenames might actually be full paths. Instead we
* check that the actual filename ends in the filename
- * specified in the list. */
- if (instFilename.str().length() >= it->length()) {
-
- if (fnmatch((*it).c_str(),
- instFilename.str().c_str(), FNM_PATHNAME) == 0) {
+ * specified in the list. Enable UNIX-style pattern
+ * matching if AFL_LLVM_WHITELIST_FNMATCH is set */
+ if (instFilename.str().length() >= it->length()) {
+ if (enable_fnmatch && fnmatch((*it).c_str(),
+ instFilename.str().c_str(), 0) == 0) {
+ return true;
+ } else if (!enable_fnmatch && instFilename.str().compare(
+ instFilename.str().length() - it->length(),
+ it->length(), *it) == 0) {
return true;
-
}
}
@@ -183,21 +188,25 @@ bool isInWhitelist(llvm::Function *F) {
/* Continue only if we know where we actually are */
if (!instFilename.str().empty()) {
+ char *enable_fnmatch = getenv("AFL_LLVM_WHITELIST_FNMATCH");
+
for (std::list<std::string>::iterator it = myWhitelist.begin();
it != myWhitelist.end(); ++it) {
/* We don't check for filename equality here because
* filenames might actually be full paths. Instead we
* check that the actual filename ends in the filename
- * specified in the list. */
- if (instFilename.str().length() >= it->length()) {
-
- if (instFilename.str().compare(
- instFilename.str().length() - it->length(), it->length(),
- *it) == 0) {
+ * specified in the list. Enable UNIX-style pattern
+ * matching if AFL_LLVM_WHITELIST_FNMATCH is set */
+ if (instFilename.str().length() >= it->length()) {
+ if (enable_fnmatch && fnmatch((*it).c_str(),
+ instFilename.str().c_str(), 0) == 0) {
+ return true;
+ } else if (!enable_fnmatch && instFilename.str().compare(
+ instFilename.str().length() - it->length(),
+ it->length(), *it) == 0) {
return true;
-
}
}

MODIFY
src/afl-common.c
src/afl-common.c
@@ -69,10 +69,11 @@ char *afl_environment_variables[] = {
"AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES",
"AFL_LLVM_LAF_ALL", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR",
"AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE",
- "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_SKIP_NEVERZERO",
- "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID",
- "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV",
- "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC",
+ "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST" , "AFL_LLVM_WHITELIST_FNMATCH",
+ "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID",
+ "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN",
+ "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON",
+ "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC",
"AFL_NO_X86", // not really an env but we dont want to warn on it
"AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE",
//"AFL_PERSISTENT", // not implemented anymore, so warn additionally

Add AFL_LLVM_WHITELIST_FNMATCH env var

Only enable UNIX pattern matching on the whitelist when
AFL_LLVM_WHITELIST_FNMATCH is set. The reason being that we keep
backwards compatibility with old whitelists.