Index: pkg-config/main.c =================================================================== --- pkg-config.orig/main.c +++ pkg-config/main.c @@ -317,8 +317,15 @@ process_package_args (const char *cmdlin { gboolean success = TRUE; GList *reqs; + int errval = 0; + + reqs = parse_module_list (NULL, cmdline, "(command line arguments)", &errval); + if (errval < 0 ) + { + fprintf (stderr, "Failed to process command line\n"); + return FALSE; + } - reqs = parse_module_list (NULL, cmdline, "(command line arguments)"); if (reqs == NULL) { fprintf (stderr, "Must specify package names on the command line\n"); Index: pkg-config/parse.c =================================================================== --- pkg-config.orig/parse.c +++ pkg-config/parse.c @@ -165,7 +165,7 @@ trim_and_sub (Package *pkg, const char * char *trimmed; GString *subst; char *p; - + trimmed = trim_string (str); subst = g_string_new (""); @@ -205,7 +205,11 @@ trim_and_sub (Package *pkg, const char * verbose_error ("Variable '%s' not defined in '%s'\n", varname, path); - exit (1); + g_free (varname); + g_free (varval); + g_free (trimmed); + g_string_free (subst, TRUE); + return NULL; } g_free (varname); @@ -228,43 +232,51 @@ trim_and_sub (Package *pkg, const char * return p; } -static void +static int parse_name (Package *pkg, const char *str, const char *path) { if (pkg->name) { verbose_error ("Name field occurs twice in '%s'\n", path); - exit (1); + return -1; } pkg->name = trim_and_sub (pkg, str, path); + if (pkg->name == NULL) + return -1; + return 0; } -static void +static int parse_version (Package *pkg, const char *str, const char *path) { if (pkg->version) { verbose_error ("Version field occurs twice in '%s'\n", path); - - exit (1); + return -1; } pkg->version = trim_and_sub (pkg, str, path); + if (pkg->version == NULL) + return -1; + return 0; } -static void +static int parse_description (Package *pkg, const char *str, const char *path) { if (pkg->description) { verbose_error ("Description field occurs twice in '%s'\n", path); - exit (1); + return -1; } pkg->description = trim_and_sub (pkg, str, path); + if (pkg->description == NULL) + return -1; + return 0; } @@ -406,7 +418,8 @@ split_module_list (const char *str, cons } GList * -parse_module_list (Package *pkg, const char *str, const char *path) +parse_module_list (Package *pkg, const char *str, const char *path, int + *errval) { GList *split; GList *iter; @@ -445,8 +458,12 @@ parse_module_list (Package *pkg, const c if (*start == '\0') { verbose_error ("Empty package name in Requires or Conflicts in file '%s'\n", path); + g_list_foreach (split, (GFunc) g_free, NULL); + g_list_free (split); - exit (1); + if (errval) + *errval = -1; + return NULL; } ver->name = g_strdup (start); @@ -480,7 +497,11 @@ parse_module_list (Package *pkg, const c { verbose_error ("Unknown version comparison operator '%s' after package name '%s' in file '%s'\n", start, ver->name, path); - exit (1); + g_list_foreach (split, (GFunc) g_free, NULL); + g_list_free (split); + if (errval) + *errval = -1; + return NULL; } } @@ -499,7 +520,9 @@ parse_module_list (Package *pkg, const c { verbose_error ("Comparison operator but no version after package name '%s' in file '%s'\n", ver->name, path); - exit (1); + g_list_foreach (split, (GFunc) g_free, NULL); + g_list_free (split); + return NULL; } if (*start != '\0') @@ -520,55 +543,98 @@ parse_module_list (Package *pkg, const c return retval; } -static void +static int parse_requires (Package *pkg, const char *str, const char *path) { - char *trimmed; + char *trimmed = NULL; + int retval = 0; + int errval; if (pkg->requires) { verbose_error ("Requires field occurs twice in '%s'\n", path); - exit (1); + retval = -1; + goto cleanup; } trimmed = trim_and_sub (pkg, str, path); - pkg->requires_entries = parse_module_list (pkg, trimmed, path); - g_free (trimmed); + if (trimmed == NULL) + { + retval = -1; + goto cleanup; + } + pkg->requires_entries = parse_module_list (pkg, trimmed, path, &errval); + if (errval < 0) + retval = -1; + +cleanup: + if (trimmed != NULL) + g_free (trimmed); + return retval; } -static void +static int parse_requires_private (Package *pkg, const char *str, const char *path) { - char *trimmed; + char *trimmed = NULL; + int retval = 0; + int errval = 0; if (pkg->requires_private) { verbose_error ("Requires.private field occurs twice in '%s'\n", path); - exit (1); + retval = -1; } trimmed = trim_and_sub (pkg, str, path); - pkg->requires_private_entries = parse_module_list (pkg, trimmed, path); - g_free (trimmed); + if (trimmed == NULL) + { + retval = -1; + goto cleanup; + } + pkg->requires_private_entries = parse_module_list (pkg, trimmed, path, + &errval); + if (errval < 0) + retval = -1; + +cleanup: + if (trimmed != NULL) + g_free (trimmed); + return retval; } -static void +static int parse_conflicts (Package *pkg, const char *str, const char *path) { - char *trimmed; + char *trimmed = NULL; + int retval = 0; + int errval = 0; if (pkg->conflicts) { verbose_error ("Conflicts field occurs twice in '%s'\n", path); - exit (1); + retval = -1; + goto cleanup; } trimmed = trim_and_sub (pkg, str, path); - pkg->conflicts = parse_module_list (pkg, trimmed, path); - g_free (trimmed); + if (trimmed == NULL) + { + retval = -1; + goto cleanup; + } + + pkg->conflicts = parse_module_list (pkg, trimmed, path, &errval); + if (errval < 0) + retval = -1; + +cleanup: + if (trimmed != NULL) + g_free (trimmed); + return retval; } static char *strdup_escape_shell(const char *s) @@ -683,12 +749,12 @@ static void _do_parse_libs (Package *pkg } -static void +static int parse_libs (Package *pkg, const char *str, const char *path) { /* Strip out -l and -L flags, put them in a separate list. */ - char *trimmed; + char *trimmed = NULL; char **argv = NULL; int argc = 0; GError *error = NULL; @@ -697,17 +763,20 @@ parse_libs (Package *pkg, const char *st { verbose_error ("Libs field occurs twice in '%s'\n", path); - exit (1); + return -1; } trimmed = trim_and_sub (pkg, str, path); + if (trimmed == NULL) + return -1; - if (trimmed && *trimmed && + if (*trimmed && !g_shell_parse_argv (trimmed, &argc, &argv, &error)) { verbose_error ("Couldn't parse Libs field into an argument vector: %s\n", error ? error->message : "unknown"); - exit (1); + g_free(trimmed); + return -1; } _do_parse_libs(pkg, argc, argv); @@ -715,9 +784,10 @@ parse_libs (Package *pkg, const char *st g_free (trimmed); g_strfreev (argv); pkg->libs_num++; + return 0; } -static void +static int parse_libs_private (Package *pkg, const char *str, const char *path) { /* @@ -741,17 +811,20 @@ parse_libs_private (Package *pkg, const { verbose_error ("Libs.private field occurs twice in '%s'\n", path); - exit (1); + return -1; } trimmed = trim_and_sub (pkg, str, path); + if (trimmed == NULL) + return -1; - if (trimmed && *trimmed && + if ( *trimmed && !g_shell_parse_argv (trimmed, &argc, &argv, &error)) { verbose_error ("Couldn't parse Libs.private field into an argument vector: %s\n", error ? error->message : "unknown"); - exit (1); + g_free(trimmed); + return -1; } _do_parse_libs(pkg, argc, argv); @@ -760,9 +833,10 @@ parse_libs_private (Package *pkg, const g_free (trimmed); pkg->libs_private_num++; + return 0; } -static void +static int parse_cflags (Package *pkg, const char *str, const char *path) { /* Strip out -I flags, put them in a separate list. */ @@ -777,17 +851,20 @@ parse_cflags (Package *pkg, const char * { verbose_error ("Cflags field occurs twice in '%s'\n", path); - exit (1); + return -1; } trimmed = trim_and_sub (pkg, str, path); + if (! trimmed) + return -1; - if (trimmed && *trimmed && + if (*trimmed && !g_shell_parse_argv (trimmed, &argc, &argv, &error)) { verbose_error ("Couldn't parse Cflags field into an argument vector: %s\n", error ? error->message : "unknown"); - exit (1); + g_free(trimmed); + return -1; } i = 0; @@ -840,19 +917,23 @@ parse_cflags (Package *pkg, const char * g_strfreev (argv); g_free (trimmed); + return 0; } -static void +static int parse_url (Package *pkg, const char *str, const char *path) { if (pkg->url != NULL) { verbose_error ("URL field occurs twice in '%s'\n", path); - exit (1); + return -1; } pkg->url = trim_and_sub (pkg, str, path); + if (pkg->url == NULL) + return -1; + return 0; } #ifdef G_OS_WIN32 @@ -873,7 +954,7 @@ pathnamecmp (const char *a, } #endif -static void +static int parse_line (Package *pkg, const char *untrimmed, const char *path, gboolean ignore_requires, gboolean ignore_private_libs, gboolean ignore_requires_private) @@ -881,6 +962,7 @@ parse_line (Package *pkg, const char *un char *str; char *p; char *tag; + int retval = 0; debug_spew (" line>%s\n", untrimmed); @@ -889,7 +971,7 @@ parse_line (Package *pkg, const char *un if (*str == '\0') /* empty line */ { g_free(str); - return; + return retval; } p = str; @@ -914,35 +996,94 @@ parse_line (Package *pkg, const char *un ++p; if (strcmp (tag, "Name") == 0) - parse_name (pkg, p, path); - else if (strcmp (tag, "Description") == 0) - parse_description (pkg, p, path); + { + if ( parse_name (pkg, p, path) < 0) + { + retval = -1; + goto cleanup; + } + } + else if (strcmp (tag, "Description") == 0 ) + { + if( parse_description (pkg, p, path) < 0) + { + retval = -1; + goto cleanup; + } + } else if (strcmp (tag, "Version") == 0) - parse_version (pkg, p, path); - else if (strcmp (tag, "Requires.private") == 0) + { + if (parse_version (pkg, p, path) < 0) + { + retval = -1; + goto cleanup; + } + } + else if (strcmp (tag, "Requires.private") == 0) { - if (!ignore_requires_private) - parse_requires_private (pkg, p, path); + if (!ignore_requires_private + && parse_requires_private (pkg, p, path) < 0) + { + retval = -1; + goto cleanup; + } } else if (strcmp (tag, "Requires") == 0) { if (ignore_requires == FALSE) - parse_requires (pkg, p, path); - else + { + if (parse_requires (pkg, p, path) <0 ) + { + retval = -1; + goto cleanup; + } + } else goto cleanup; } - else if ((strcmp (tag, "Libs.private") == 0) && - ignore_private_libs == FALSE) - parse_libs_private (pkg, p, path); + else if ( strcmp (tag, "Libs.private") == 0 + && ignore_private_libs == FALSE) + { + if (parse_libs_private (pkg, p, path) < 0) + { + retval = -1; + goto cleanup; + } + } + else if (strcmp (tag, "Libs") == 0) - parse_libs (pkg, p, path); - else if (strcmp (tag, "Cflags") == 0 || + { + if (parse_libs (pkg, p, path) < 0) + { + retval = -1; + goto cleanup; + } + } + else if (strcmp (tag, "Cflags") == 0 || strcmp (tag, "CFlags") == 0) - parse_cflags (pkg, p, path); + { + if (parse_cflags (pkg, p, path) < 0) + { + retval = -1; + goto cleanup; + } + } + else if (strcmp (tag, "Conflicts") == 0) - parse_conflicts (pkg, p, path); - else if (strcmp (tag, "URL") == 0) - parse_url (pkg, p, path); + { + if (parse_conflicts (pkg, p, path) < 0) + { + retval = -1; + goto cleanup; + } + } + else if (strcmp (tag, "URL") == 0 ) + { + if (parse_url (pkg, p, path) < 0 ) + { + retval = -1; + goto cleanup; + } + } else { /* we don't error out on unknown keywords because they may @@ -1042,11 +1183,17 @@ parse_line (Package *pkg, const char *un verbose_error ("Duplicate definition of variable '%s' in '%s'\n", tag, path); - exit (1); + retval = -1; + goto cleanup; } varname = g_strdup (tag); varval = trim_and_sub (pkg, p, path); + if ( varval == NULL ) { + g_free(varname); + retval = -1; + goto cleanup; + } debug_spew (" Variable declaration, '%s' has value '%s'\n", varname, varval); @@ -1057,6 +1204,8 @@ parse_line (Package *pkg, const char *un cleanup: g_free (str); g_free (tag); + + return retval; } Package* @@ -1099,8 +1248,13 @@ parse_package_file (const char *path, gb { one_line = TRUE; - parse_line (pkg, str->str, path, ignore_requires, ignore_private_libs, - ignore_requires_private); + if ( parse_line (pkg, str->str, path, ignore_requires, ignore_private_libs, + ignore_requires_private) < 0) { + g_free(pkg); + g_string_free (str, TRUE); + fclose(f); + return NULL; + } g_string_truncate (str, 0); } Index: pkg-config/parse.h =================================================================== --- pkg-config.orig/parse.h +++ pkg-config/parse.h @@ -26,7 +26,8 @@ Package *parse_package_file (const char gboolean ignore_private_libs, gboolean ignore_requires_private); -GList *parse_module_list (Package *pkg, const char *str, const char *path); +GList *parse_module_list (Package *pkg, const char *str, const char *path, + int* errval); #endif Index: pkg-config/pkg.c =================================================================== --- pkg-config.orig/pkg.c +++ pkg-config/pkg.c @@ -40,7 +40,7 @@ #include #include -static void verify_package (Package *pkg); +static int verify_package (Package *pkg); static GHashTable *packages = NULL; static GHashTable *locations = NULL; @@ -366,7 +366,7 @@ internal_get_package (const char *name, { verbose_error ("Package '%s', required by '%s', not found\n", ver->name, pkg->key); - exit (1); + return NULL; } if (pkg->required_versions == NULL) @@ -390,7 +390,7 @@ internal_get_package (const char *name, { verbose_error ("Package '%s', required by '%s', not found\n", ver->name, pkg->key); - exit (1); + return NULL; } if (pkg->required_versions == NULL) @@ -407,7 +407,8 @@ internal_get_package (const char *name, pkg->requires = g_list_reverse (pkg->requires); pkg->requires_private = g_list_reverse (pkg->requires_private); - verify_package (pkg); + if ( verify_package (pkg) < 0) + return NULL; return pkg; } @@ -672,7 +673,7 @@ add_env_variable_to_list (GList *list, c return list; } -static void +static int verify_package (Package *pkg) { GList *requires = NULL; @@ -691,28 +692,28 @@ verify_package (Package *pkg) { fprintf (stderr, "Internal pkg-config error, package with no key, please file a bug report\n"); - exit (1); + return -1; } if (pkg->name == NULL) { verbose_error ("Package '%s' has no Name: field\n", pkg->key); - exit (1); + return -1; } if (pkg->version == NULL) { verbose_error ("Package '%s' has no Version: field\n", pkg->key); - exit (1); + return -1; } if (pkg->description == NULL) { verbose_error ("Package '%s' has no Description: field\n", pkg->key); - exit (1); + return -1; } /* Make sure we have the right version for all requirements */ @@ -742,7 +743,7 @@ verify_package (Package *pkg) verbose_error ("You may find new versions of %s at %s\n", req->name, req->url); - exit (1); + return -1; } } @@ -780,7 +781,7 @@ verify_package (Package *pkg) ver->owner->key, ver->owner->version); - exit (1); + return -1; } conflicts_iter = g_list_next (conflicts_iter); @@ -925,6 +926,7 @@ verify_package (Package *pkg) pkg->libs = g_list_remove (pkg->libs, NULL); --count; } + return 0; } /* Create a merged list of required packages and retrieve the flags from them.