krb5 commit [krb5-1.16]: Merge duplicate subsections in profile library

Greg Hudson <[email protected]>
Newsgroups gmane.comp.encryption.kerberos.cvs
Message-ID <[email protected]>
https://github.com/krb5/krb5/commit/98d0061c8083af960438ad1ac088f60497694a68
commit 98d0061c8083af960438ad1ac088f60497694a68
Author: Robbie Harwood <[email protected]>
Date:   Tue Apr 10 15:55:41 2018 -0400

    Merge duplicate subsections in profile library
    
    Modify profile_add_node() to return the existing node, rather than
    making a new one, when adding subsection configuration.
    
    This fixes an issue where the first instance of a subsection will hide
    the second instance entirely.  In particular, it was previously
    impossible to split realm-specific configuration across multiple
    config files.
    
    [[email protected]: adjusted style, added test case]
    
    (cherry picked from commit efab9fa5a6d23c486467264e20b58bf5a9c60f0c)
    
    ticket: 7863
    version_fixed: 1.16.1

 src/util/profile/prof_test1  |   22 ++++++++++++++++++++++
 src/util/profile/prof_tree.c |   15 +++++++++++----
 src/util/profile/test.ini    |    6 ++++++
 3 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/src/util/profile/prof_test1 b/src/util/profile/prof_test1
index 7e30fc1..7d13c93 100644
--- a/src/util/profile/prof_test1
+++ b/src/util/profile/prof_test1
@@ -341,6 +341,27 @@ proc test9 {} {
     puts "OK: test9: profile_flush_to_file with no changes"
 }
 
+proc test10 {} {
+    global wd verbose
+
+    # Regression test for #7863: multiply-specified subsections should
+    # be merged.
+    set p [profile_init_path $wd/test2.ini]
+    set x [profile_get_values $p {{test section 2} child_section2 child}]
+    if $verbose { puts "Read $x from profile" }
+    if ![string equal $x "slick harry {john\tb } ron"] {
+	puts stderr "Error: test10: Did not get expected merged children."
+	exit 1
+    }
+
+    set x [profile_get_string $p {test section 2} child_section2 chores]
+    if $verbose { puts "Read $x from profile" }
+    if ![string equal $x "cleaning"] {
+	puts stderr "Error: test10: Did not find expected chores."
+	exit 1
+    }
+}
+
 test1
 test2
 test3
@@ -350,5 +371,6 @@ test6
 test7
 test8
 test9
+test10
 
 exit 0
diff --git a/src/util/profile/prof_tree.c b/src/util/profile/prof_tree.c
index 081f688..38aadc4 100644
--- a/src/util/profile/prof_tree.c
+++ b/src/util/profile/prof_tree.c
@@ -9,7 +9,7 @@
  *
  * Each node may represent either a relation or a section header.
  *
- * A section header must have its value field set to 0, and may a one
+ * A section header must have its value field be null, and may have one
  * or more child nodes, pointed to by first_child.
  *
  * A relation has as its value a pointer to allocated memory
@@ -159,15 +159,22 @@ errcode_t profile_add_node(struct profile_node *section, const char *name,
         return PROF_ADD_NOT_SECTION;
 
     /*
-     * Find the place to insert the new node.  We look for the
-     * place *after* the last match of the node name, since
+     * Find the place to insert the new node.  If we are adding a subsection
+     * and already have a subsection with that name, merge them.  Otherwise,
+     * we look for the place *after* the last match of the node name, since
      * order matters.
      */
     for (p=section->first_child, last = 0; p; last = p, p = p->next) {
         int cmp;
         cmp = strcmp(p->name, name);
-        if (cmp > 0)
+        if (cmp > 0) {
             break;
+        } else if (value == NULL && cmp == 0 &&
+                   p->value == NULL && p->deleted != 1) {
+            /* Found duplicate subsection, so don't make a new one. */
+            *ret_node = p;
+            return 0;
+        }
     }
     retval = profile_create_node(name, value, &new);
     if (retval)
diff --git a/src/util/profile/test.ini b/src/util/profile/test.ini
index 23ca896..6622df1 100644
--- a/src/util/profile/test.ini
+++ b/src/util/profile/test.ini
@@ -10,6 +10,12 @@ this is a comment.  Everything up to the first square brace is ignored.
 	}
 	child_section2 = foo
 
+[test section 2]
+	child_section2 = {
+		child = ron
+		chores = cleaning
+	}
+
 [realms]
 ATHENA.MIT.EDU = {
 	server = KERBEROS.MIT.EDU:88
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.