From 7e9aa7e1fc07f0d660a08b89b8a3d732b8686a72 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 8 Aug 2022 09:56:28 +0000 Subject: [PATCH] pkg: do not break cycles across dependency lists --- libpkgconf/libpkgconf.h | 1 + libpkgconf/pkg.c | 29 ++++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/libpkgconf/libpkgconf.h b/libpkgconf/libpkgconf.h index d198828..a883384 100644 --- a/libpkgconf/libpkgconf.h +++ b/libpkgconf/libpkgconf.h @@ -266,6 +266,7 @@ PKGCONF_API void pkgconf_cross_personality_deinit(pkgconf_cross_personality_t *p #define PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES 0x10000 #define PKGCONF_PKG_DEPF_INTERNAL 0x1 +#define PKGCONF_PKG_DEPF_PRIVATE 0x2 #define PKGCONF_PKG_ERRF_OK 0x0 #define PKGCONF_PKG_ERRF_PACKAGE_NOT_FOUND 0x1 diff --git a/libpkgconf/pkg.c b/libpkgconf/pkg.c index 52535da..90a2d34 100644 --- a/libpkgconf/pkg.c +++ b/libpkgconf/pkg.c @@ -154,6 +154,17 @@ pkgconf_pkg_parser_internal_dependency_func(pkgconf_client_t *client, pkgconf_pk pkgconf_dependency_parse(client, pkg, dest, value, PKGCONF_PKG_DEPF_INTERNAL); } +/* a variant of pkgconf_pkg_parser_dependency_func which colors the dependency node as an "internal" dependency. */ +static void +pkgconf_pkg_parser_private_dependency_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value) +{ + (void) keyword; + (void) lineno; + + pkgconf_list_t *dest = (pkgconf_list_t *)((char *) pkg + offset); + pkgconf_dependency_parse(client, pkg, dest, value, PKGCONF_PKG_DEPF_PRIVATE); +} + /* keep this in alphabetical order */ static const pkgconf_pkg_parser_keyword_pair_t pkgconf_pkg_parser_keyword_funcs[] = { {"CFLAGS", pkgconf_pkg_parser_fragment_func, offsetof(pkgconf_pkg_t, cflags)}, @@ -167,7 +178,7 @@ static const pkgconf_pkg_parser_keyword_pair_t pkgconf_pkg_parser_keyword_funcs[ {"Provides", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, provides)}, {"Requires", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, required)}, {"Requires.internal", pkgconf_pkg_parser_internal_dependency_func, offsetof(pkgconf_pkg_t, requires_private)}, - {"Requires.private", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, requires_private)}, + {"Requires.private", pkgconf_pkg_parser_private_dependency_func, offsetof(pkgconf_pkg_t, requires_private)}, {"Version", pkgconf_pkg_parser_version_func, offsetof(pkgconf_pkg_t, version)}, }; @@ -1478,12 +1489,20 @@ pkgconf_pkg_walk_list(pkgconf_client_t *client, * the list, so that we dont create a situation where * memory is leaked due to circular ownership. * i.e: A owns B owns A + * + * TODO(ariadne): Breaking circular references between Requires and Requires.private + * lists causes problems. Find a way to refactor the Requires.private list out. */ - pkgconf_warn(client, "%s: breaking circular reference (%s -> %s -> %s)\n", - parent->id, parent->id, pkgdep->id, parent->id); + if (!(depnode->flags & PKGCONF_PKG_DEPF_PRIVATE) && + !(parent->flags & PKGCONF_PKG_PROPF_VIRTUAL)) + { + pkgconf_warn(client, "%s: breaking circular reference (%s -> %s -> %s)\n", + parent->id, parent->id, pkgdep->id, parent->id); + + pkgconf_node_delete(node, deplist); + pkgconf_dependency_unref(client, depnode); + } - pkgconf_node_delete(node, deplist); - pkgconf_dependency_unref(client, depnode); goto next; }