cfg: Prevent infinite loop in cfg_del_section().
authorBen Pfaff <blp@nicira.com>
Mon, 6 Apr 2009 22:38:30 +0000 (15:38 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 6 Apr 2009 23:34:32 +0000 (16:34 -0700)
When the last entry in the file was deleted, cfg_del_section() would loop
forever because *p was never set to NULL by svec_del().  (Alternatively,
it could segfault because we were accessing freed memory.)

This better implementation is also O(N) instead of O(N**2).

lib/cfg.c
lib/svec.c
lib/svec.h

index 916cb932fb7dd4d806f9d756a955dfafacd9f1a9..4495f670df0163db207ec91db65d3ba4f3d036aa 100644 (file)
--- a/lib/cfg.c
+++ b/lib/cfg.c
@@ -526,16 +526,15 @@ cfg_del_section(const char *section_, ...)
     ds_put_char(&section, '.');
     va_end(args);
 
-    for (p = cfg.names; *p; ) { /* XXX this is inefficient */
+    for (p = cfg.names; *p; p++) {
         if (!strncmp(section.string, *p, section.length)) {
-            /* Delete this matching entry in-place, so don't move on to
-             * the next entry. */
-            svec_del(&cfg, *p);
-        } else {
-            /* Move onto the next entry. */
-            p++;
+            free(*p);
+            *p = NULL;
         }
     }
+    svec_compact(&cfg);
+    svec_terminate(&cfg);
+
     ds_destroy(&section);
     dirty = true;
 }
index e04893046ef7edf031a01e49639d52e7ad622045..e635d499e098bd3e8ac05684c6b548b235761078 100644 (file)
@@ -171,6 +171,19 @@ svec_unique(struct svec *svec)
     }
 }
 
+void
+svec_compact(struct svec *svec)
+{
+    size_t i, j;
+
+    for (i = j = 0; i < svec->n; i++) {
+        if (svec->names[i] != NULL) {
+            svec->names[j++] = svec->names[i];
+        }
+    }
+    svec->n = j;
+}
+
 void
 svec_diff(const struct svec *a, const struct svec *b,
           struct svec *a_only, struct svec *both, struct svec *b_only)
index 0af162d9b4f9d530f0cca459bfb9c4a72f0da483..981d43b992011cd38eb5b5b2fdcdb032c3923bec 100644 (file)
@@ -57,6 +57,7 @@ void svec_terminate(struct svec *);
 void svec_sort(struct svec *);
 void svec_sort_unique(struct svec *);
 void svec_unique(struct svec *);
+void svec_compact(struct svec *);
 void svec_diff(const struct svec *a, const struct svec *b,
                struct svec *a_only, struct svec *both, struct svec *b_only);
 bool svec_contains(const struct svec *, const char *);