resolver: filter out duplicate target dependencies.
authorKrisztian Litkey <kli@iki.fi>
Mon, 30 Sep 2013 14:49:50 +0000 (17:49 +0300)
committerKrisztian Litkey <kli@iki.fi>
Mon, 30 Sep 2013 15:16:48 +0000 (18:16 +0300)
Currently failing to do so could trigger dereferencing
fact_stamps beyond its end in older_than_facts (as
fact_stamps is allocated in the graph sorter and its
size reflects the number of unique dependencies).

src/resolver/target.c

index 8099159..bd2c998 100644 (file)
@@ -124,7 +124,7 @@ target_t *create_target(mrp_resolver_t *r, const char *target,
 {
     target_t *t;
     size_t    old_size, new_size;
-    int       i;
+    int       i, j, found, nduplicate;
 
     for (i = 0, t = r->targets; i < r->ntarget; i++, t++) {
         if (!strcmp(t->name, target)) {
@@ -149,14 +149,30 @@ target_t *create_target(mrp_resolver_t *r, const char *target,
         t->depends = mrp_allocz_array(char *, ndepend);
 
         if (t->depends != NULL) {
+            nduplicate = 0;
             for (i = 0; i < ndepend; i++) {
-                t->depends[i] = mrp_strdup(depends[i]);
-
-                if (t->depends[i] == NULL)
-                    goto undo_and_fail;
+                found = FALSE;
+                for (j = 0; j < i; j++)
+                    if (!strcmp(depends[i], depends[j]))
+                        found = TRUE;
+                if (!found) {
+                    t->depends[i - nduplicate] = mrp_strdup(depends[i]);
+
+                    if (t->depends[i] == NULL)
+                        goto undo_and_fail;
+                }
+                else
+                    nduplicate++;
             }
 
-            t->ndepend = ndepend;
+            t->ndepend = ndepend - nduplicate;
+
+            if (nduplicate > 0) {
+                mrp_reallocz(t->depends, ndepend, t->ndepend);
+                mrp_log_warning("Filtered out %d duplicate%s dependencies "
+                                "from target '%s'.", nduplicate,
+                                nduplicate == 1 ? "" : "s", t->name);
+            }
         }
         else
             goto undo_and_fail;