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>
Wed, 4 Apr 2007 05:49:46 +0000 (05:49 +0000)
(cherry picked from commit 67490a4535890fb6f9e01b6032abb6859559d0b1)

hdrs/conf.h
src/destroy.c
src/division.c

index 2bbd23c49130b368572afd5f51bd07dec6667744..552902c42b03ee71f41cd6ad55fdddeb4c5c4086 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 e5a5e8f20b1d9a403c5317a5dd0a63a1886225ef..4befd2b6ad986ff0295730ab829b2fd4debc2f87 100644 (file)
@@ -1050,16 +1050,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 cab566fa0dc05f63a9617925bb4914fb033c075f..19a94618e29772cfea0d832948cf722182ff62df 100644 (file)
@@ -1462,7 +1462,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;
 
@@ -1513,9 +1513,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...
@@ -1677,6 +1679,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;
@@ -1702,14 +1705,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;
 }