From b295636604b44b68ddaf386eda25a9d417e5aedc Mon Sep 17 00:00:00 2001 From: Ari Johnson Date: Mon, 25 Feb 2008 16:52:39 +0000 Subject: [PATCH] Detect and prevent division loops; fix division loops in @dbck (cherry picked from commit 67490a4535890fb6f9e01b6032abb6859559d0b1) --- hdrs/conf.h | 1 + src/destroy.c | 30 ++++++++++++++++++++++-------- src/division.c | 25 +++++++++++++++---------- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/hdrs/conf.h b/hdrs/conf.h index f9c5141..7792de5 100644 --- a/hdrs/conf.h +++ b/hdrs/conf.h @@ -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 '*' diff --git a/src/destroy.c b/src/destroy.c index aca63ae..822b38a 100644 --- a/src/destroy.c +++ b/src/destroy.c @@ -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); diff --git a/src/division.c b/src/division.c index 58ae367..6595a59 100644 --- a/src/division.c +++ b/src/division.c @@ -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; } -- 2.30.2