[build-path-prefix-map-spec] 17/50: Use ASAN with AFL and fix some memory leaks

Ximin Luo infinity0 at debian.org
Fri Mar 10 15:17:19 UTC 2017


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch master
in repository build-path-prefix-map-spec.

commit c013f5a64b8277e8454435ea16f7376038df268c
Author: Ximin Luo <infinity0 at debian.org>
Date:   Fri Jan 27 20:35:13 2017 +0100

    Use ASAN with AFL and fix some memory leaks
    
    - Move all memory allocation out of the parser for a simpler API
---
 consume/Makefile     |   8 +++-
 consume/pecsplit.c   |  17 +++----
 consume/prefix_map.h | 133 ++++++++++++++++++++++++++++++++++++---------------
 3 files changed, 106 insertions(+), 52 deletions(-)

diff --git a/consume/Makefile b/consume/Makefile
index 5c65f97..2b91082 100644
--- a/consume/Makefile
+++ b/consume/Makefile
@@ -5,6 +5,10 @@ ALL_FORMATS = pecsplit
 ALL_SOURCE = pecsplit.c
 ALLCHECK_pecsplit = pecsplit.c.out pecsplit.js pecsplit.py
 
+export AFL_USE_ASAN=1
+AFL_MEMLIM = none
+# 20971595M also seems to work with afl-gcc amd64 6.2.1-5
+
 find_testcases = \
 	TESTCASES_$(1) = $(patsubst $(T)$(1).%.in,$(1).%,$(wildcard $(T)$(1).*.in))
 $(eval $(call find_testcases,0))
@@ -61,10 +65,10 @@ fuzz-%: %.out
 	echo >&2 "warning: you didn't set CC=afl-gcc, fuzzing might not work"
 	set -e; if test -d "afl-out-$*"; then \
 	echo >&2 "afl-out-$* exists, reusing. run 'make reset-fuzz-$* to delete it."; \
-	afl-fuzz -i - -o "afl-out-$*" -- "./$<" -; else \
+	afl-fuzz -m $(AFL_MEMLIM) -i - -o "afl-out-$*" -- "./$<" -; else \
 	mkdir -p $(TMPDIR); \
 	ln -s "$$(mktemp -d -p $(TMPDIR))" "afl-out-$*"; \
-	afl-fuzz -i "afl-in-$(basename $*)" -o "afl-out-$*" -- "./$<" -; fi
+	afl-fuzz -m $(AFL_MEMLIM) -i "afl-in-$(basename $*)" -o "afl-out-$*" -- "./$<" -; fi
 
 .PHONY: reset-fuzz-%
 reset-fuzz-%:
diff --git a/consume/pecsplit.c b/consume/pecsplit.c
index ec00cbf..9468ab4 100644
--- a/consume/pecsplit.c
+++ b/consume/pecsplit.c
@@ -1,5 +1,4 @@
 #include "prefix_map.h"
-#include <errno.h>
 
 /* Parsing the variable. */
 /* For Applying the variable, see prefix_map.h. */
@@ -29,8 +28,9 @@ unquote (char *src)
   return 1;
 }
 
+/* Returns 0 on failure and 1 on success. */
 int
-parse_prefix_map (char *arg, struct prefix_map *map)
+parse_prefix_map (char *arg, struct prefix_maps *maps)
 {
   char *p;
   p = strchr (arg, '=');
@@ -39,16 +39,14 @@ parse_prefix_map (char *arg, struct prefix_map *map)
   *p = '\0';
   if (!unquote (arg))
     return 0;
-  map->old_prefix = xstrdup (arg);
-  map->old_len = strlen (arg);
   p++;
   if (!unquote (p))
     return 0;
-  map->new_prefix = xstrdup (p);
-  map->new_len = strlen (p);
-  return 1;
+
+  return add_prefix_map (arg, p, maps);
 }
 
+/* Returns 0 on failure and 1 on success. */
 int
 parse_prefix_maps (const char *arg, struct prefix_maps *maps)
 {
@@ -60,15 +58,12 @@ parse_prefix_maps (const char *arg, struct prefix_maps *maps)
   char *tok = strtok_r (copy, sep, &end);
   while (tok != NULL)
     {
-      struct prefix_map *map = XNEW (struct prefix_map);
-      if (!parse_prefix_map (tok, map))
+      if (!parse_prefix_map (tok, maps))
 	{
 	  fprintf (stderr, "invalid value for prefix-map: '%s'\n", arg);
-	  free (map);
 	  return 0;
 	}
 
-      add_prefix_map (map, maps);
       tok = strtok_r (NULL, sep, &end);
     }
 
diff --git a/consume/prefix_map.h b/consume/prefix_map.h
index 46fac3a..857c698 100644
--- a/consume/prefix_map.h
+++ b/consume/prefix_map.h
@@ -17,21 +17,6 @@ xstrdup (const char *s)
   return (char *) memcpy (ret, s, len);
 }
 
-char *
-xstrndup (const char *s, size_t n)
-{
-  char *result;
-  size_t len = strlen (s);
-
-  if (n < len)
-    len = n;
-
-  result = XNEWVEC (char, len + 1);
-
-  result[len] = '\0';
-  return (char *) memcpy (result, s, len);
-}
-
 /* Rest of it, including Applying the variable */
 
 struct prefix_map
@@ -43,9 +28,81 @@ struct prefix_map
   struct prefix_map *next;
 };
 
+struct prefix_maps
+{
+  struct prefix_map *head;
+  size_t max_replace;
+};
+
+/* Add a new mapping.
+ *
+ * The input strings are duplicated and a new prefix_map struct is allocated.
+ * Ownership of the duplicates, as well as the new prefix_map, is the same as
+ * the owner of the overall prefix_maps struct.
+ *
+ * Returns 0 on failure and 1 on success.
+ */
+int
+add_prefix_map (const char *old_prefix, const char *new_prefix,
+		struct prefix_maps *maps)
+{
+  struct prefix_map *map = XNEW (struct prefix_map);
+  if (!map)
+    goto rewind_0;
+
+  map->old_prefix = xstrdup (old_prefix);
+  if (!map->old_prefix)
+    goto rewind_1;
+  map->old_len = strlen (old_prefix);
+
+  map->new_prefix = xstrdup (new_prefix);
+  if (!map->new_prefix)
+    goto rewind_2;
+  map->new_len = strlen (new_prefix);
+
+  map->next = maps->head;
+  maps->head = map;
+
+  if (map->new_len > maps->max_replace)
+    maps->max_replace = map->new_len;
+
+  return 1;
+
+rewind_2:
+  free ((void *) map->old_prefix);
+rewind_1:
+  free (map);
+rewind_0:
+  return 0;
+}
+
+
+/* Clear all mappings.
+ *
+ * All child structs of [maps] are freed, but it itself is not freed.
+ */
+void
+clear_prefix_maps (struct prefix_maps *maps)
+{
+  struct prefix_map *map;
+  struct prefix_map *next;
+
+  for (map = maps->head; map; map = next)
+    {
+      free ((void *) map->old_prefix);
+      free ((void *) map->new_prefix);
+      next = map->next;
+      free (map);
+    }
+
+  maps->max_replace = 0;
+}
+
+
+/* Private function, assumes new_name is wide enough to hold the remapped name. */
 const char *
-apply_prefix_map (const char *old_name, char *new_name,
-		  struct prefix_map *map_head)
+_apply_prefix_map (const char *old_name, char *new_name,
+		   struct prefix_map *map_head)
 {
   struct prefix_map *map;
   const char *name;
@@ -62,23 +119,9 @@ apply_prefix_map (const char *old_name, char *new_name,
   return new_name;
 }
 
-struct prefix_maps
-{
-  struct prefix_map *head;
-  size_t max_replace;
-};
-
-void
-add_prefix_map (struct prefix_map *map, struct prefix_maps *maps)
-{
-  map->next = maps->head;
-  maps->head = map;
 
-  if (map->new_len > maps->max_replace)
-    maps->max_replace = map->new_len;
-}
-
-/*
+/* Remap a filename.
+ *
  * This function does not consume nor take ownership of filename; the caller is
  * responsible for freeing it, if and only if it was already responsible for
  * freeing it before the call.
@@ -92,7 +135,7 @@ remap_prefix_alloc (const char *filename, struct prefix_maps *maps, void *(*allo
 {
   size_t maxlen = strlen (filename) + maps->max_replace + 1;
   char *newname = (char *) alloca (maxlen);
-  const char *name = apply_prefix_map (filename, newname, maps->head);
+  const char *name = _apply_prefix_map (filename, newname, maps->head);
 
   if (name == filename)
     return filename;
@@ -101,21 +144,28 @@ remap_prefix_alloc (const char *filename, struct prefix_maps *maps, void *(*allo
   return (char *) memcpy (alloc (len), newname, len);
 }
 
-// Like remap_prefix_alloc but with the system allocator.
+
+/* Like remap_prefix_alloc but with the system allocator. */
 const char *
 remap_prefix (const char *filename, struct prefix_maps *maps)
 {
   return remap_prefix_alloc (filename, maps, malloc);
 }
 
+
 #include <stdlib.h>
 #include <stdio.h>
 
 /*
- * Run as one of:
+ * Run as:
  *
  * $ BUILD_PATH_PREFIX_MAP=${map} ./main ${path0} ${path1} ${path2}
+ *
+ * Or a more clumsy interface, required by afl-fuzz:
+ *
  * $ printf "${map}\0${path0}\0${path1}\0${path2}\0" | ./main -
+ *
+ * Returns 1 on failure and 0 on success.
  */
 int
 generic_main (int (*parse_prefix_maps) (const char *, struct prefix_maps *), int argc, char *argv[])
@@ -142,7 +192,7 @@ generic_main (int (*parse_prefix_maps) (const char *, struct prefix_maps *), int
     if (!parse_prefix_maps (str, &build_path_prefix_map))
       {
 	fprintf (stderr, "parse_prefix_maps failed\n");
-	return 1;
+	goto err_exit;
       }
 
   if (using_stdin)
@@ -163,14 +213,19 @@ generic_main (int (*parse_prefix_maps) (const char *, struct prefix_maps *), int
     {
       for (int i = using_stdin ? 2 : 1; i < argc; i++)
 	{
-	  //fprintf (stderr, "%s", argv[i]);
-	  printf ("%s\n", remap_prefix (argv[i], &build_path_prefix_map));
+	  const char *newarg = remap_prefix (argv[i], &build_path_prefix_map);
+	  printf ("%s\n", newarg);
+	  if (newarg != argv[i])
+	    free ((void *) newarg); // as per contract of remap_prefix()
 	}
     }
 
+  clear_prefix_maps (&build_path_prefix_map);
   return 0;
 
 err_stdin:
   perror ("failed to read from stdin");
+err_exit:
+  clear_prefix_maps (&build_path_prefix_map);
   return 1;
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/build-path-prefix-map-spec.git



More information about the Reproducible-commits mailing list