Detect and prevent division loops; fix division loops in @dbck
authorAri Johnson <ari@cobramush.org>
Mon, 25 Feb 2008 16:52:39 +0000 (16:52 +0000)
committerAri Johnson <ari@cobramush.org>
Mon, 25 Feb 2008 16:52:39 +0000 (16:52 +0000)
hdrs/conf.h
src/destroy.c
src/division.c

index f9c51416b8881b397a954fc0af28247eedddb888..7792de53a7d40664b7ebd9b7422f0ef249ca5c0a 100644 (file)
@@ -36,6 +36,7 @@
 #define COMMAND_NAME_LIMIT 64
 #define MAX_ZONES      30
 #define NUM_SWITCH_BYTES 22
+#define MAX_DIVISION_DEPTH 1000
 
 /* magic cookies */
 #define LOOKUP_TOKEN '*'
index aca63aeeec4800c3d7426c278ad1e55022a0756b..822b38ad6c8c0e493e1a08ac56fd77c647c7a39f 100644 (file)
@@ -1051,16 +1051,30 @@ check_divisions(void) {
        Division(i) = Location(i);
        Parent(i) = Location(i);
       }
-      /* make sure their division is set correctly. */
-      if(SDIV(i).object != -1 && SDIV(i).object == i) {
-       do_rawlog(LT_ERR, T("ERROR: Bad Master-Division."));
-        SDIV(i).object = -1;   
-      }
+
       /* make sure their division is a valid object */
-      if((!GoodObject(Division(i)) && Division(i) != NOTHING) || IsGarbage(Division(i))) {
-       Division(i) = -1;
-       do_rawlog(LT_ERR, T("ERROR: Bad Division(#%d) set on object #%d"), Division(i), i);
+      if((!GoodObject(Division(i)) && Division(i) != NOTHING)
+        || IsGarbage(Division(i))) {
+       Division(i) = NOTHING;
+       do_rawlog(LT_ERR, T("ERROR: Bad Division(#%d) set on object #%d"),
+                 Division(i), i);
       }
+
+      /* check for division loops */
+      if(GoodObject(Division(i))) {
+        dbref tmp;
+        unsigned j;
+
+        for(tmp = Division(i), j = 0; GoodObject(tmp) && j < MAX_DIVISION_DEPTH;
+           tmp = Division(tmp), j++) {
+          if(tmp == i) {
+            do_rawlog(LT_ERR, T("ERROR: Division loop detected at #%d"), i);
+            Division(i) = NOTHING;
+            Parent(i) = NOTHING;
+          }
+        }
+      }
+
       /* now check parent tree */
       if(Division(i) != -1)
        Parent(i) = Division(i);
index 58ae367d233ece24979c28556d761d774eb3cbf4..6595a59a2a9f72d36672db66026144cbaffc541d 100644 (file)
@@ -1458,7 +1458,7 @@ division_set(dbref exec, dbref target, const char *arg2)
   ATTR *divrcd;
   char *p_buf[BUFFER_LEN / 2];
   char buf[BUFFER_LEN], *bp;
-  dbref cur_obj, divi;
+  dbref cur_obj, divi, tmp;
   struct power_group_list *pg_l;
   int cnt;
 
@@ -1509,9 +1509,11 @@ division_set(dbref exec, dbref target, const char *arg2)
     return;
   }
 
-  if (divi == target) {
-    notify(exec, T("Can't division something to itself."));
-    return;
+  for (tmp = divi; GoodObject(tmp); tmp = Division(tmp)) {
+    if (tmp == target) {
+      notify(exec, T("Can't create loops in division tree."));
+      return;
+    }
   }
 
   /* Make sure the receiving division has the quota to receive all of this crapp...
@@ -1673,6 +1675,7 @@ div_inscope(dbref scoper, dbref scopee)
 {
 /* check if scopee is in the divscope of scoper */
   dbref div1, div2;
+  unsigned i;
 
   if (!GoodObject(scopee))
     return 0;
@@ -1698,14 +1701,16 @@ div_inscope(dbref scoper, dbref scopee)
   if (div2 == NOTHING)          /*  they're automatically at the bottom of the divtree */
     return 1;
 
-  for (; div1 != div2; div2 = SDIV(div2).object)
+  for (i = 0; i < MAX_DIVISION_DEPTH && div1 != div2;
+       div2 = SDIV(div2).object, i++)
     if (div2 == NOTHING)        /* went off the tree */
       return 0;
-    else if (div2 == SDIV(div2).object) {       /* detect & fix bad division tree */
-      do_log(LT_ERR, scoper, scopee,
-             T("Bad Master Division(#%d).  Corrected."), div2);
-      SDIV(div2).object = NOTHING;
-    }
+
+  if (div1 != div2) {    /* maximum depth reached without finding it */
+    do_rawlog(LT_ERR, T("Caught probable division loop circa #%d"), div1);
+    return 0;
+  }
+
   return 1;
 }