summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2023-03-26 15:35:00 -0400
committerPaul Smith <psmith@gnu.org>2023-04-01 11:13:12 -0400
commit9db74434cd34b2b875b3f9bfbab4f1e0b682e27c (patch)
treeb488a9766c9e1a932518fd6e4e1db25ae6b788b5 /src
parent23f70b0cb86208d3b9b47b0efa9707a1dac5360b (diff)
downloadmake-git-9db74434cd34b2b875b3f9bfbab4f1e0b682e27c.tar.gz
Clean up memory leak warnings from ASAN and Valgrind
* src/main.c (main): Add "sanitize" to .FEATURES if ASAN is enabled. * src/expand.c (expand_variable_output): Remember "recursive" setting in case it's changed by the expansion of the variable. * src/file.c (rehash_file): If we drop a file from the global 'files' hash, remember it in rehashed_files. We can't free it because it's still being referenced (callers will invoke check_renamed()) but it will be a leak since it's no longer referenced by 'files'. * src/remake.c (update_file_1): If we drop a dependency, remember it in dropped_list. We can't free it because it's still being referenced by callers but it will be a leak since it's no longer referenced as a prerequisite. * tests/scripts/functions/guile: Don't run Guile tests when ASAN is enabled. * tests/scripts/functions/wildcard: Enabling ASAN causes glob(3) to break! Don't run this test. * tests/scripts/features/exec: Valgrind's exec() doesn't support scripts with no shbang. * tests/scripts/jobserver: Valgrind fails if TMPDIR is set to an invalid directory: skip those tests. * tests/scripts/features/output-sync: Ditto. * tests/scripts/features/temp_stdin: Ditto.
Diffstat (limited to 'src')
-rw-r--r--src/expand.c8
-rw-r--r--src/file.c17
-rw-r--r--src/main.c3
-rw-r--r--src/read.c26
-rw-r--r--src/remake.c19
5 files changed, 54 insertions, 19 deletions
diff --git a/src/expand.c b/src/expand.c
index 01fff81e..533e7dfa 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -226,6 +226,7 @@ char *
expand_variable_output (char *ptr, const char *name, size_t length)
{
struct variable *v;
+ unsigned int recursive;
char *value;
v = lookup_variable (name, length);
@@ -237,11 +238,14 @@ expand_variable_output (char *ptr, const char *name, size_t length)
if (!v || (v->value[0] == '\0' && !v->append))
return ptr;
- value = v->recursive ? recursively_expand (v) : v->value;
+ /* Remember this since expansion could change it. */
+ recursive = v->recursive;
+
+ value = recursive ? recursively_expand (v) : v->value;
ptr = variable_buffer_output (ptr, value, strlen (value));
- if (v->recursive)
+ if (recursive)
free (value);
return ptr;
diff --git a/src/file.c b/src/file.c
index 9828d283..f8e4fb91 100644
--- a/src/file.c
+++ b/src/file.c
@@ -60,6 +60,14 @@ file_hash_cmp (const void *x, const void *y)
static struct hash_table files;
+/* We can't free files we take out of the hash table, because they are still
+ likely pointed to in various places. The check_renamed() will be used if
+ we come across these, to find the new correct file. This is mainly to
+ prevent leak checkers from complaining. */
+static struct file **rehashed_files = NULL;
+static size_t rehashed_files_len = 0;
+#define REHASHED_FILES_INCR 5
+
/* Whether or not .SECONDARY with no prerequisites was given. */
static int all_secondary = 0;
@@ -217,8 +225,7 @@ rehash_file (struct file *from_file, const char *to_hname)
/* Find the end of the renamed list for the "from" file. */
file_key.hname = from_file->hname;
- while (from_file->renamed != 0)
- from_file = from_file->renamed;
+ check_renamed (from_file);
if (file_hash_cmp (from_file, &file_key))
/* hname changed unexpectedly!! */
abort ();
@@ -331,6 +338,12 @@ rehash_file (struct file *from_file, const char *to_hname)
to_file->builtin = 0;
from_file->renamed = to_file;
+
+ if (rehashed_files_len % REHASHED_FILES_INCR == 0)
+ rehashed_files = xrealloc (rehashed_files,
+ sizeof (struct file *) * (rehashed_files_len + REHASHED_FILES_INCR));
+
+ rehashed_files[rehashed_files_len++] = from_file;
}
/* Rename FILE to NAME. This is not as simple as resetting
diff --git a/src/main.c b/src/main.c
index 16bbb83a..bf74ab94 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1467,6 +1467,9 @@ main (int argc, char **argv, char **envp)
#ifdef MAKE_MAINTAINER_MODE
" maintainer"
#endif
+#if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_MEMORY__)
+ " sanitize"
+#endif
;
define_variable_cname (".FEATURES", features, o_default, 0);
diff --git a/src/read.c b/src/read.c
index bae836f2..2d25be6a 100644
--- a/src/read.c
+++ b/src/read.c
@@ -3261,22 +3261,24 @@ parse_file_seq (char **stringp, size_t size, int stopmap,
/* Strip leading "this directory" references. */
if (NONE_SET (flags, PARSEFS_NOSTRIP))
+ {
#if MK_OS_VMS
- /* Skip leading '[]'s. should only be one set or bug somewhere else */
- if (p - s > 2 && s[0] == '[' && s[1] == ']')
+ /* Skip leading '[]'s. should only be one set or bug somewhere else */
+ if (p - s > 2 && s[0] == '[' && s[1] == ']')
s += 2;
- /* Skip leading '<>'s. should only be one set or bug somewhere else */
- if (p - s > 2 && s[0] == '<' && s[1] == '>')
+ /* Skip leading '<>'s. should only be one set or bug somewhere else */
+ if (p - s > 2 && s[0] == '<' && s[1] == '>')
s += 2;
#endif
- /* Skip leading './'s. */
- while (p - s > 2 && s[0] == '.' && s[1] == '/')
- {
- /* Skip "./" and all following slashes. */
- s += 2;
- while (*s == '/')
- ++s;
- }
+ /* Skip leading './'s. */
+ while (p - s > 2 && s[0] == '.' && s[1] == '/')
+ {
+ /* Skip "./" and all following slashes. */
+ s += 2;
+ while (*s == '/')
+ ++s;
+ }
+ }
/* Extract the filename just found, and skip it.
Set NAME to the string, and NLEN to its length. */
diff --git a/src/remake.c b/src/remake.c
index d5cd3b38..dfe981c3 100644
--- a/src/remake.c
+++ b/src/remake.c
@@ -69,6 +69,13 @@ static struct dep *goal_dep;
All files start with considered == 0. */
static unsigned int considered = 0;
+/* During processing we might drop some dependencies, which can't be freed
+ immediately because they are still in use. Remember them: this is mainly
+ to satisfy leak detectors. */
+static struct dep **dropped_list = NULL;
+static size_t dropped_list_len = 0;
+#define DROPPED_LIST_INCR 5
+
static enum update_status update_file (struct file *file, unsigned int depth);
static enum update_status update_file_1 (struct file *file, unsigned int depth);
static enum update_status check_dep (struct file *file, unsigned int depth,
@@ -608,15 +615,21 @@ update_file_1 (struct file *file, unsigned int depth)
OSS (error, NILF, _("Circular %s <- %s dependency dropped."),
file->name, d->file->name);
- /* We cannot free D here because our the caller will still have
- a reference to it when we were called recursively via
- check_dep below. */
if (lastd == 0)
file->deps = du->next;
else
lastd->next = du->next;
du = du->next;
+
+ /* We cannot free D here because our the caller will still have
+ a reference to it when we were called recursively via
+ check_dep below. */
+ if (dropped_list_len % DROPPED_LIST_INCR == 0)
+ dropped_list = xrealloc (dropped_list,
+ sizeof (struct dep *) * (dropped_list_len + DROPPED_LIST_INCR));
+ dropped_list[dropped_list_len++] = d;
+
continue;
}