Blame SOURCES/Fix-silent-crash-with-duplicate-config-sections.patch

1f3433
From caec174b203206185b6075c0e822c6f45070dd87 Mon Sep 17 00:00:00 2001
1f3433
From: Alexander Scheel <ascheel@redhat.com>
1f3433
Date: Wed, 9 Aug 2017 15:00:26 -0400
1f3433
Subject: [PATCH] Fix silent crash with duplicate config sections
1f3433
1f3433
Signed-off-by: Alexander Scheel <ascheel@redhat.com>
1f3433
Reviewed-by: Simo Sorce <simo@redhat.com>
1f3433
Resolves: #194
1f3433
Merges: #202
1f3433
(cherry picked from commit c0d85387fc38f9554d601ec2ddb111031a694387)
1f3433
---
1f3433
 proxy/configure.ac    | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++
1f3433
 proxy/src/gp_config.c |  27 +++++------
1f3433
 2 files changed, 137 insertions(+), 15 deletions(-)
1f3433
1f3433
diff --git a/proxy/configure.ac b/proxy/configure.ac
1f3433
index c52dbb6..9e01f7d 100644
1f3433
--- a/proxy/configure.ac
1f3433
+++ b/proxy/configure.ac
1f3433
@@ -107,6 +107,131 @@ fi
1f3433
 AC_SUBST(INI_LIBS)
1f3433
 AC_SUBST(INI_CFLAGS)
1f3433
 
1f3433
+AC_CHECK_LIB(ref_array, ref_array_destroy, [],
1f3433
+             [AC_MSG_WARN([ref_array library must support ref_array_destroy])],
1f3433
+             [$INI_CONFIG_LIBS])
1f3433
+
1f3433
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
1f3433
+/* See: https://pagure.io/SSSD/ding-libs/pull-request/3172 */
1f3433
+#include <linux/limits.h>
1f3433
+#include <string.h>
1f3433
+#include <errno.h>
1f3433
+#include <stdio.h>
1f3433
+#include <stdlib.h>
1f3433
+#include <stdint.h>
1f3433
+#include <ini_configobj.h>
1f3433
+#include <ini_config.h>
1f3433
+
1f3433
+static int write_to_file(char *path, char *text)
1f3433
+{
1f3433
+    FILE *f = fopen(path, "w");
1f3433
+    int bytes = 0;
1f3433
+    if (f == NULL)
1f3433
+        return 1;
1f3433
+
1f3433
+    bytes = fprintf(f, "%s", text);
1f3433
+    if (bytes != strlen(text))
1f3433
+        return 1;
1f3433
+
1f3433
+    return fclose(f);
1f3433
+}
1f3433
+
1f3433
+int main(void)
1f3433
+{
1f3433
+    char base_path[PATH_MAX];
1f3433
+    char augment_path[PATH_MAX];
1f3433
+
1f3433
+    char config_base[] =
1f3433
+        "[section]\n"
1f3433
+        "key1 = first\n"
1f3433
+        "key2 = exists\n";
1f3433
+
1f3433
+    char config_augment[] =
1f3433
+        "[section]\n"
1f3433
+        "key1 = augment\n"
1f3433
+        "key3 = exists\n";
1f3433
+
1f3433
+    char *builddir;
1f3433
+
1f3433
+    struct ini_cfgobj *in_cfg, *result_cfg;
1f3433
+    struct ini_cfgfile *file_ctx;
1f3433
+
1f3433
+    uint32_t merge_flags = INI_MS_DETECT | INI_MS_PRESERVE;
1f3433
+
1f3433
+    int ret;
1f3433
+
1f3433
+    builddir = getenv("builddir");
1f3433
+    if (builddir == NULL) {
1f3433
+        builddir = strdup(".");
1f3433
+    }
1f3433
+
1f3433
+    snprintf(base_path, PATH_MAX, "%s/tmp_augment_base.conf", builddir);
1f3433
+    snprintf(augment_path, PATH_MAX, "%s/tmp_augment_augment.conf", builddir);
1f3433
+
1f3433
+    ret = write_to_file(base_path, config_base);
1f3433
+    if (ret != 0) {
1f3433
+        ret = 1;
1f3433
+        goto cleanup;
1f3433
+    }
1f3433
+
1f3433
+    ret = write_to_file(augment_path, config_augment);
1f3433
+    if (ret != 0) {
1f3433
+        goto cleanup;
1f3433
+    }
1f3433
+
1f3433
+    /* Match only augment.conf */
1f3433
+    const char *m_patterns[] = { "^tmp_augment_augment.conf$", NULL };
1f3433
+
1f3433
+     /* Match all sections */
1f3433
+    const char *m_sections[] = { ".*", NULL };
1f3433
+
1f3433
+    /* Create config collection */
1f3433
+    ret = ini_config_create(&in_cfg);
1f3433
+    if (ret != EOK)
1f3433
+        goto cleanup;
1f3433
+
1f3433
+    /* Open base.conf */
1f3433
+    ret = ini_config_file_open(base_path, 0, &file_ctx);
1f3433
+    if (ret != EOK)
1f3433
+        goto cleanup;
1f3433
+
1f3433
+    /* Seed in_cfg with base.conf */
1f3433
+    ret = ini_config_parse(file_ctx, 1, 0, 0, in_cfg);
1f3433
+    if (ret != EOK)
1f3433
+        goto cleanup;
1f3433
+
1f3433
+    /* Update base.conf with augment.conf */
1f3433
+    ret = ini_config_augment(in_cfg,
1f3433
+                             builddir,
1f3433
+                             m_patterns,
1f3433
+                             m_sections,
1f3433
+                             NULL,
1f3433
+                             INI_STOP_ON_NONE,
1f3433
+                             0,
1f3433
+                             INI_PARSE_NOSPACE|INI_PARSE_NOTAB,
1f3433
+                             merge_flags,
1f3433
+                             &result_cfg,
1f3433
+                             NULL,
1f3433
+                             NULL);
1f3433
+    /* We always expect EEXIST due to DETECT being set. */
1f3433
+    if (ret != EEXIST)
1f3433
+        goto cleanup;
1f3433
+
1f3433
+    ret = 0;
1f3433
+
1f3433
+cleanup:
1f3433
+    remove(base_path);
1f3433
+    remove(augment_path);
1f3433
+
1f3433
+    /* Per autoconf guidelines */
1f3433
+    if (ret != 0)
1f3433
+        ret = 1;
1f3433
+
1f3433
+    return ret;
1f3433
+}
1f3433
+]])]
1f3433
+,, [AC_MSG_ERROR(["ini_config library must support extended INI_MS_DETECT. See: https://pagure.io/SSSD/ding-libs/pull-request/3172"])])
1f3433
+
1f3433
 AX_PTHREAD(,[AC_MSG_ERROR([Could not find Pthreads support])])
1f3433
 
1f3433
 LIBS="$PTHREAD_LIBS $LIBS"
1f3433
diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c
1f3433
index 07f7c8d..cd057a0 100644
1f3433
--- a/proxy/src/gp_config.c
1f3433
+++ b/proxy/src/gp_config.c
1f3433
@@ -728,7 +728,7 @@ static int gp_config_from_file(const char *config_file,
1f3433
                                0, /* metadata_flags, FIXME */
1f3433
                                &file_ctx);
1f3433
     if (ret) {
1f3433
-        GPDEBUG("Failed to open config file: %d (%s)\n",
1f3433
+        GPERROR("Failed to open config file: %d (%s)\n",
1f3433
                 ret, gp_strerror(ret));
1f3433
         ini_config_destroy(ini_config);
1f3433
         return ret;
1f3433
@@ -742,7 +742,7 @@ static int gp_config_from_file(const char *config_file,
1f3433
     if (ret) {
1f3433
         char **errors = NULL;
1f3433
         /* we had a parsing failure */
1f3433
-        GPDEBUG("Failed to parse config file: %d (%s)\n",
1f3433
+        GPERROR("Failed to parse config file: %d (%s)\n",
1f3433
                 ret, gp_strerror(ret));
1f3433
         if (ini_config_error_count(ini_config)) {
1f3433
             ini_config_get_errors(ini_config, &errors);
1f3433
@@ -791,26 +791,25 @@ static int gp_config_from_dir(const char *config_dir,
1f3433
                              INI_STOP_ON_ANY, /* error_level */
1f3433
                              collision_flags,
1f3433
                              INI_PARSE_NOWRAP,
1f3433
-                             /* do not allow colliding sections with the same
1f3433
-                              * name in different files */
1f3433
-                             INI_MS_ERROR,
1f3433
+                             /* allow sections with the same name in
1f3433
+                              * different files, but log warnings */
1f3433
+                             INI_MS_DETECT | INI_MS_PRESERVE,
1f3433
                              &result_cfg,
1f3433
                              &error_list,
1f3433
                              NULL);
1f3433
-    if (ret) {
1f3433
+    if (error_list) {
1f3433
         uint32_t len;
1f3433
-
1f3433
-        if (!error_list) {
1f3433
-            GPAUDIT("Error when reading config directory number: %d\n", ret);
1f3433
-            return ret;
1f3433
-        }
1f3433
-
1f3433
         len = ref_array_len(error_list);
1f3433
         for (uint32_t i = 0; i < len; i++) {
1f3433
             /* libini has an unfixable bug where error strings are (char **) */
1f3433
             GPAUDIT("Error when reading config directory: %s\n",
1f3433
                     *(char **)ref_array_get(error_list, i, NULL));
1f3433
         }
1f3433
+        ref_array_destroy(error_list);
1f3433
+    }
1f3433
+
1f3433
+    if (ret && ret != EEXIST) {
1f3433
+        GPERROR("Error when reading config directory number: %d\n", ret);
1f3433
 
1f3433
         ref_array_destroy(error_list);
1f3433
         return ret;
1f3433
@@ -821,9 +820,7 @@ static int gp_config_from_dir(const char *config_dir,
1f3433
         ini_config_destroy(*ini_config);
1f3433
         *ini_config = result_cfg;
1f3433
     }
1f3433
-    if (error_list) {
1f3433
-        ref_array_destroy(error_list);
1f3433
-    }
1f3433
+
1f3433
     return 0;
1f3433
 }
1f3433