about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--docs/Changelog.md2
-rw-r--r--docs/env_variables.md3
-rw-r--r--include/config.h16
-rw-r--r--include/debug.h72
-rw-r--r--include/envs.h4
-rw-r--r--src/afl-fuzz-state.c16
-rw-r--r--src/afl-fuzz.c15
7 files changed, 122 insertions, 6 deletions
diff --git a/docs/Changelog.md b/docs/Changelog.md
index ac75c68d..ebc514f3 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -52,6 +52,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
     - somewhere we broke -n dumb fuzzing, fixed
     - added afl_custom_describe to the custom mutator API to allow for easy
       mutation reproduction on crashing inputs
+    - new env. var. AFL_NO_COLOR (or AFL_NO_COLOUR) to suppress colored
+      console output (when configured with USE_COLOR and not ALWAYS_COLORED)
   - instrumentation
     - We received an enhanced gcc_plugin module from AdaCore, thank you
       very much!!
diff --git a/docs/env_variables.md b/docs/env_variables.md
index e203055f..74863d8d 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -381,6 +381,9 @@ checks or alter some of the more exotic semantics of the tool:
     some basic stats. This behavior is also automatically triggered when the
     output from afl-fuzz is redirected to a file or to a pipe.
 
+  - Setting `AFL_NO_COLOR` or `AFL_NO_COLOUR` will omit control sequences for
+    coloring console output when configured with USE_COLOR and not ALWAYS_COLORED.
+
   - Setting `AFL_FORCE_UI` will force painting the UI on the screen even if
     no valid terminal was detected (for virtual consoles)
 
diff --git a/include/config.h b/include/config.h
index 1eb6bc5e..d57ef223 100644
--- a/include/config.h
+++ b/include/config.h
@@ -36,11 +36,27 @@
  *                                                    *
  ******************************************************/
 
+/* console output colors: There are three ways to configure its behavior
+ * 1. default: colored outputs fixed on: defined USE_COLOR && defined ALWAYS_COLORED
+ *    The env var. AFL_NO_COLOR will have no effect
+ * 2. defined USE_COLOR && !defined ALWAYS_COLORED
+ *    -> depending on env var AFL_NO_COLOR=1 colors can be switched off
+ *    at run-time. Default is to use colors.
+ * 3. colored outputs fixed off: !defined USE_COLOR
+ *    The env var. AFL_NO_COLOR will have no effect
+*/
+
 /* Comment out to disable terminal colors (note that this makes afl-analyze
    a lot less nice): */
 
 #define USE_COLOR
 
+#ifdef USE_COLOR
+/* Comment in to always enable terminal colors */
+/* Comment out to enable runtime controlled terminal colors via AFL_NO_COLOR */
+#define ALWAYS_COLORED  1
+#endif
+
 /* StatsD config
    Config can be adjusted via AFL_STATSD_HOST and AFL_STATSD_PORT environment
    variable.
diff --git a/include/debug.h b/include/debug.h
index 5512023c..7a1725b5 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -168,12 +168,72 @@
  * Debug & error macros *
  ************************/
 
-/* Just print stuff to the appropriate stream. */
+#if defined USE_COLOR && !defined ALWAYS_COLORED
+#include <unistd.h>
+#pragma GCC diagnostic ignored "-Wformat-security"
+static inline const char * colorfilter(const char * x) {
+  static int once = 1;
+  static int disabled = 0;
+
+  if (once) {
+    /* when there is no tty -> we always want filtering
+     * when AFL_NO_UI is set filtering depends on AFL_NO_COLOR
+     * otherwise we want always colors
+     */
+    disabled = isatty(2) && (!getenv("AFL_NO_UI") || (!getenv("AFL_NO_COLOR") && !getenv("AFL_NO_COLOUR")));
+    once = 0;
+  }
+  if (likely(disabled)) return x;
+
+  static char monochromestring[4096];
+  char *d = monochromestring;
+  int in_seq = 0;
+
+  while(*x) {
+    if (in_seq && *x == 'm') {
+      in_seq = 0;
+    } else {
+      if (!in_seq && *x == '\x1b') { in_seq = 1; }
+      if (!in_seq) {
+        *d++ = *x;
+      }
+    }
+    ++x;
+  }
+
+  *d = '\0';
+  return monochromestring;
+}
+#else
+#define colorfilter(x) x /* no filtering necessary */
+#endif
 
+/* macro magic to transform the first parameter to SAYF
+ * through colorfilter which strips coloring */
+#define GET_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,\
+_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,\
+_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,\
+_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,\
+NAME,...) NAME
+
+#define SAYF(...) GET_MACRO(__VA_ARGS__, \
+SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, \
+SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, \
+SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, \
+SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, \
+SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, \
+SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, \
+SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, \
+SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_1)(__VA_ARGS__)
+
+#define SAYF_1(x)  MY_SAYF(colorfilter(x))
+#define SAYF_N(x,...)  MY_SAYF(colorfilter(x), __VA_ARGS__)
+
+/* Just print stuff to the appropriate stream. */
 #ifdef MESSAGES_TO_STDOUT
-  #define SAYF(x...) printf(x)
+  #define MY_SAYF(x...) printf(x)
 #else
-  #define SAYF(x...) fprintf(stderr, x)
+  #define MY_SAYF(x...) fprintf(stderr, x)
 #endif                                               /* ^MESSAGES_TO_STDOUT */
 
 /* Show a prefixed warning. */
@@ -222,7 +282,7 @@
   do {                                                                   \
                                                                          \
     SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD                            \
-         "\n[-] PROGRAM ABORT : " cRST   x);                               \
+         "\n[-] PROGRAM ABORT : " cRST x);                               \
     SAYF(cLRD "\n         Location : " cRST "%s(), %s:%u\n\n", __func__, \
          __FILE__, __LINE__);                                            \
     exit(1);                                                             \
@@ -235,7 +295,7 @@
   do {                                                                   \
                                                                          \
     SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD                            \
-         "\n[-] PROGRAM ABORT : " cRST   x);                               \
+         "\n[-] PROGRAM ABORT : " cRST x);                               \
     SAYF(cLRD "\n    Stop location : " cRST "%s(), %s:%u\n\n", __func__, \
          __FILE__, __LINE__);                                            \
     abort();                                                             \
@@ -249,7 +309,7 @@
                                                                        \
     fflush(stdout);                                                    \
     SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD                          \
-         "\n[-]  SYSTEM ERROR : " cRST   x);                             \
+         "\n[-]  SYSTEM ERROR : " cRST x);                             \
     SAYF(cLRD "\n    Stop location : " cRST "%s(), %s:%u\n", __func__, \
          __FILE__, __LINE__);                                          \
     SAYF(cLRD "       OS message : " cRST "%s\n", strerror(errno));    \
diff --git a/include/envs.h b/include/envs.h
index c0f41ca5..f16e61f0 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -103,6 +103,10 @@ static char *afl_environment_variables[] = {
     "AFL_NO_ARITH",
     "AFL_NO_AUTODICT",
     "AFL_NO_BUILTIN",
+#if defined USE_COLOR && ! defined ALWAYS_COLORED
+    "AFL_NO_COLOR",
+    "AFL_NO_COLOUR",
+#endif
     "AFL_NO_CPU_RED",
     "AFL_NO_FORKSRV",
     "AFL_NO_UI",
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 9c51a3ef..e863c4c7 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -401,6 +401,22 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
             afl->afl_env.afl_crash_exitcode =
                 (u8 *)get_afl_env(afl_environment_variables[i]);
 
+#if defined USE_COLOR && ! defined ALWAYS_COLORED
+          } else if (!strncmp(env, "AFL_NO_COLOR",
+
+                              afl_environment_variable_len)) {
+
+            afl->afl_env.afl_statsd_tags_flavor =
+                (u8 *)get_afl_env(afl_environment_variables[i]);
+
+          } else if (!strncmp(env, "AFL_NO_COLOUR",
+
+                              afl_environment_variable_len)) {
+
+            afl->afl_env.afl_statsd_tags_flavor =
+                (u8 *)get_afl_env(afl_environment_variables[i]);
+#endif
+
           }
 
         } else {
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 391d4c4f..e0d46f7e 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -156,6 +156,12 @@ static void usage(u8 *argv0, int more_help) {
 
   if (more_help > 1) {
 
+#if defined USE_COLOR && !defined ALWAYS_COLORED
+  #define DYN_COLOR "AFL_NO_COLOR or AFL_NO_COLOUR: switch colored console output off\n"
+#else
+  #define DYN_COLOR
+#endif
+
     SAYF(
       "Environment variables used:\n"
       "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
@@ -194,6 +200,9 @@ static void usage(u8 *argv0, int more_help) {
       "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n"
       "AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
       "AFL_NO_UI: switch status screen off\n"
+
+      DYN_COLOR
+
       "AFL_PATH: path to AFL support binaries\n"
       "AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n"
       "AFL_QUIET: suppress forkserver status messages\n"
@@ -298,6 +307,12 @@ int main(int argc, char **argv_orig, char **envp) {
   struct timeval  tv;
   struct timezone tz;
 
+#if defined USE_COLOR && defined ALWAYS_COLORED
+  if (getenv("AFL_NO_COLOR") || getenv("AFL_NO_COLOUR")) {
+     WARNF("Setting AFL_NO_COLOR has no effect (colors are configured on at compile time)");
+  }
+#endif
+
   char **argv = argv_cpy_dup(argc, argv_orig);
 
   afl_state_t *afl = calloc(1, sizeof(afl_state_t));