pkgsrc-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

pkg/45077: pkgtools/pkg_install catch circular dependencies in add/perform.c



>Number:         45077
>Category:       pkg
>Synopsis:       pkgtools/pkg_install catch circular dependencies in 
>add/perform.c
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Jun 17 14:30:00 +0000 2011
>Originator:     Thomas Cort
>Release:        N/A
>Organization:
Minix3
>Environment:
Minix 192.168.122.210 3.2.0 i686
>Description:
During the porting of pkgsrc to Minix, a developer ran into an issue 
where the pkg_do() function in add/perform.c would go into an infinite 
recursion due to a circular dependency. The dependency issue was caused 
by different versions of the pkgsrc tree being used to compile different 
packages.

The patch below adds a counter to pkg_do(). Every time pkg_do() gets
called recursively, the counter is incremented. If the counter exceeds
MAX_PKG_DO_RECURSION_DEPTH it is assumed that a circular dependency
has been detected, a warning is printed, and the recursion is stopped.

This patch was moved from pkg/45047 so that the PR would
only deal with one problem.
>How-To-Repeat:
I wasn't able to recreate the conditions that caused the
circular dependency.
>Fix:
--- a/pkg_install/files/add/perform.c   Thu Jun 16 19:34:17 2011
+++ b/pkg_install/files/add/perform.c   Thu Jun 16 19:38:27 2011
@@ -60,6 +60,8 @@
 #include "add.h"
 #include "version.h"
 
+#define MAX_PKG_DO_RECURSION_DEPTH (1024)
+
 struct pkg_meta {
        char *meta_contents;
        char *meta_comment;
@@ -126,7 +128,7 @@
        { 0, NULL, 0, 0 },
 };
 
-static int pkg_do(const char *, int, int);
+static int pkg_do(const char *, int, int, int);
 
 static int
 end_of_version(const char *opsys, const char *version_end)
@@ -738,7 +740,7 @@
                        continue;
 
                case PLIST_CMD:
-                       if (format_cmd(cmd, sizeof(cmd), p->name, pkg->prefix, 
last_file))
+                       if (format_cmd(cmd, sizeof(cmd), p->name, 
pkg->install_prefix, last_file))
                                return -1;
                        printf("Executing '%s'\n", cmd);
                        if (!Fake && system(cmd))
@@ -1093,7 +1095,7 @@
 }
 
 static int
-check_dependencies(struct pkg_task *pkg)
+check_dependencies(struct pkg_task *pkg, int depth)
 {
        plist_t *p;
        char *best_installed;
@@ -1124,7 +1126,7 @@
                                    p->name);
                                continue;
                        }
-                       if (pkg_do(p->name, 1, 0)) {
+                       if (pkg_do(p->name, 1, 0, depth)) {
                                if (ForceDepends) {
                                        warnx("Can't install dependency %s, "
                                            "continuing", p->name);
@@ -1373,12 +1375,17 @@
  * Install a single package.
  */
 static int
-pkg_do(const char *pkgpath, int mark_automatic, int top_level)
+pkg_do(const char *pkgpath, int mark_automatic, int top_level, int depth)
 {
        char *archive_name;
        int status, invalid_sig;
        struct pkg_task *pkg;
 
+       if (++depth > MAX_PKG_DO_RECURSION_DEPTH) {
+               warnx("circular dependency detected");
+               return -1;
+       }
+
        pkg = xcalloc(1, sizeof(*pkg));
 
        status = -1;
@@ -1490,7 +1497,7 @@
                        pkg->install_logdir_real = NULL;
                }
 
-               if (check_dependencies(pkg))
+               if (check_dependencies(pkg, depth))
                        goto nuke_pkgdb;
        } else {
                /*
@@ -1498,7 +1505,7 @@
                 * Install/update dependencies first and
                 * write the current package to disk afterwards.
                 */ 
-               if (check_dependencies(pkg))
+               if (check_dependencies(pkg, depth))
                        goto clean_memory;
 
                if (write_meta_data(pkg))
@@ -1582,7 +1589,7 @@
        lpkg_t *lpp;
 
        while ((lpp = TAILQ_FIRST(pkgs)) != NULL) {
-               if (pkg_do(lpp->lp_name, Automatic, 1))
+               if (pkg_do(lpp->lp_name, Automatic, 1, 0))
                        ++errors;
                TAILQ_REMOVE(pkgs, lpp, lp_link);
                free_lpkg(lpp);



Home | Main Index | Thread Index | Old Index