View Issue Details

IDProjectCategoryView StatusLast Update
0000689LDMud 3.3Runtimepublic2011-02-23 22:22
ReporterBardioc Assigned ToGnomi  
PrioritynormalSeveritycrashReproducibilityrandom
Status resolvedResolutionfixed 
Product Version3.3.718 
Target Version3.3.720Fixed in Version3.3.720 
Summary0000689: Crash: Mapping entry didn't hash to the same spot.
DescriptionThe driver (Version 3.5.0-2573) crashes with "Mapping entry didn't hash to the same spot.". Curently this is only reproducible within our mudlib, all "small" examples work as expected.

The following piece of code contains the bug in the marked line:

public mixed * mkset(mixed * arr)
{
    check(arr, IS_ARRAY);

    if (sizeof(arr) < 2)
    {
        return arr;
    }

    mapping set = mkmapping(arr);

    // walk through all entries in the array and if found in the mapping, remove it from there, if
    // not found in the mapping, remove it from the array
    for (int i = 0; i < sizeof(arr); i++)
    {
        if (member(set, arr[i]))
        {
            m_delete(set, arr[i]); <---- THE GAME CRASHES HERE
        }
        else
        {
            arr[i..i] = ({});

            --i;
        }
    }

    return arr;
}

The stack trace is:

2009.10.05 18:33:12 LDMud ready for users.
2009.10.05 18:54:56 Mapping entry didn't hash to the same spot.
2009.10.05 18:54:56 Current object was kernel/simul_efun
kernel/simul_efun kernel/simul_efuns/lpc.c line 1231
0x843a33f: 16 const1 (2: 65) line 1231
0x843a340: 42 + (3: 66)
0x843a341: 186 no_warn_deprecated (2: 65)
0x843a342: 61 index (2: 65)
0x843a343: 199 pointerp (1: 64)
0x843a344: 38 && (1: 64)
0x843a352: 38 && (1: 64) line 1232
0x843a39e: 107 branch_when_zero (1: 64) line 1234
0x843a3bc: 30 0 local (0: 63) line 1240
0x843a3be: 30 3 local (1: 64)
0x843a3c0: 186 no_warn_deprecated (2: 65)
0x843a3c1: 61 index (2: 65)
0x843a3c2: 30 0 local (1: 64)
0x843a3c4: 30 3 local (2: 65)
0x843a3c6: 16 const1 (3: 66)
0x843a3c7: 42 + (4: 67)
0x843a3c8: 186 no_warn_deprecated (3: 66)
0x843a3c9: 61 index (3: 66)
0x843a3ca: 168 2 aggregate (2: 65)
0x843a3cd: 168 1 aggregate (1: 64)
0x843a3d0: 125 2 push_local_variable_lvalue (1: 64)
0x843a3d2: 78 (void)+= (2: 65)
0x843a3d3: 18 2 clit (0: 63) line 1229
0x843a3d5: 125 3 push_local_variable_lvalue (1: 64)
0x843a3d7: 78 (void)+= (2: 65)
0x843a3d8: 30 3 local (0: 63)
0x843a3da: 30 0 local (1: 64)
0x843a3dc: 202 sizeof (2: 65)
0x843a3dd: 49 < (2: 65)
0x843a3de: 110 164 bbranch_when_non_zero (1: 64)
0x843a3e0: 97 259 clear_locals (0: 63) line 1245
0x843a3e3: 125 3 push_local_variable_lvalue (0: 63)
0x843a3e5: 30 2 local (1: 64)
0x843a3e7: 177 foreach (2: 65)
0x843a7ac: 180 foreach_next (0: 67) line 1457
0x843a3eb: 97 1028 clear_locals (0: 67) line 1250
0x843a3ee: 18 2 clit (0: 67)
0x843a3f0: 16 const1 (1: 68)
0x843a3f1: 18 3 clit (2: 69)
0x843a3f3: 18 3 clit (3: 70)
0x843a3f5: 18 4 clit (4: 71)
0x843a3f7: 18 4 clit (5: 72)
0x843a3f9: 18 5 clit (6: 73)
0x843a3fb: 18 5 clit (7: 74)
0x843a3fd: 18 7 clit (8: 75)
0x843a3ff: 18 6 clit (9: 76)
0x843a401: 18 8 clit (10: 77)
0x843a403: 18 7 clit (11: 78)
0x843a405: 18 6 clit (12: 79)
0x843a407: 18 8 clit (13: 80)
0x843a409: 18 11 clit (14: 81)
0x843a40b: 18 9 clit (15: 82)
0x843a40d: 170 264 m_caggregate (16: 83)
0x843a410: 30 3 local (1: 68)
0x843a412: 15 const0 (2: 69)
0x843a413: 186 no_warn_deprecated (3: 70)
0x843a414: 61 index (3: 70)
0x843a415: 211 typeof (2: 69)
0x843a416: 186 no_warn_deprecated (2: 69)
0x843a417: 61 index (2: 69)
0x843a418: 125 4 push_local_variable_lvalue (1: 68)
0x843a41a: 41 (void)= (2: 69)
0x843a41b: 30 3 local (0: 67) line 1254
0x843a41d: 16 const1 (1: 68)
0x843a41e: 186 no_warn_deprecated (2: 69)
0x843a41f: 61 index (2: 69)
0x843a420: 125 5 push_local_variable_lvalue (1: 68)
0x843a422: 41 (void)= (2: 69)
0x843a423: 30 5 local (0: 67) line 1255
0x843a425: 199 pointerp (1: 68)
0x843a426: 108 8 branch_when_non_zero (1: 68)
0x843a428: 30 5 local (0: 67) line 1257
0x843a42a: 168 1 aggregate (1: 68)
0x843a42d: 125 5 push_local_variable_lvalue (1: 68)
0x843a42f: 41 (void)= (2: 69)
0x843a430: 15 const0 (0: 67) line 1260
0x843a431: 125 6 push_local_variable_lvalue (1: 68)
0x843a433: 41 (void)= (2: 69)
0x843a434: 168 0 aggregate (0: 67) line 1261
0x843a437: 125 7 push_local_variable_lvalue (1: 68)
0x843a439: 41 (void)= (2: 69)
0x843a43a: 97 264 clear_locals (0: 67) line 1264
0x843a43d: 15 const0 (0: 67)
0x843a43e: 125 8 push_local_variable_lvalue (1: 68)
0x843a440: 41 (void)= (2: 69)
0x843a441: 103 lbranch (0: 67)
0x843a774: 30 8 local (0: 67)
0x843a776: 30 5 local (1: 68)
0x843a778: 202 sizeof (2: 69)
0x843a779: 49 < (2: 69)
0x843a77a: 105 lbranch_when_non_zero (1: 68)
0x843a444: 30 5 local (0: 67) line 1268
0x843a446: 30 8 local (1: 68)
0x843a448: 186 no_warn_deprecated (2: 69)
0x843a449: 61 index (2: 69)
0x843a44a: 199 pointerp (1: 68)
0x843a44b: 104 lbranch_when_zero (1: 68)
0x843a64f: 30 5 local (0: 67) line 1364
0x843a651: 30 8 local (1: 68)
0x843a653: 186 no_warn_deprecated (2: 69)
0x843a654: 61 index (2: 69)
0x843a655: 18 11 clit (1: 68)
0x843a657: 51 == (2: 69) line 1367
0x843a658: 107 branch_when_zero (1: 68)
0x843a663: 30 5 local (0: 67) line 1372
0x843a665: 30 8 local (1: 68)
0x843a667: 186 no_warn_deprecated (2: 69)
0x843a668: 61 index (2: 69)
0x843a669: 30 4 local (1: 68)
0x843a66b: 51 == (2: 69) line 1374
0x843a66c: 107 106 branch_when_zero (1: 68)
0x843a66e: 30 4 local (0: 67)
0x843a670: 16 const1 (1: 68)
0x843a671: 52 != (2: 69)
0x843a672: 38 5 && (1: 68)
0x843a674: 30 4 local (0: 67)
0x843a676: 18 6 clit (1: 68)
0x843a678: 52 != (2: 69) line 1377
0x843a679: 107 82 branch_when_zero (1: 68)
0x843a67b: 30 3 local (0: 67)
0x843a67d: 15 const0 (1: 68)
0x843a67e: 186 no_warn_deprecated (2: 69)
0x843a67f: 61 index (2: 69)
0x843a680: 15 const0 (1: 68)
0x843a681: 51 == (2: 69) line 1379
0x843a682: 107 branch_when_zero (1: 68)
0x843a6c2: 15 const0 (0: 67) line 1385
0x843a6c3: 125 6 push_local_variable_lvalue (1: 68) line 1387
0x843a6c5: 41 (void)= (2: 69)
0x843a6c6: 102 fbranch (0: 67)
0x843a77d: 30 6 local (0: 67) line 1444
0x843a77f: 107 branch_when_zero (1: 68)
0x843a7a9: 125 1 push_local_variable_lvalue (0: 67) line 1456
0x843a7ab: 32 ++ (1: 68)
0x843a7ac: 180 964 foreach_next (0: 67) line 1457
0x843a7af: 181 foreach_end (0: 67)
0x843a7b0: 25 return0 (0: 63) line 1458
0x843a7f6: 99 restore_arg_frame (2: 53) line 1512
0x843a7f7: 92 pop_value (1: 52)
0x843a7f8: 30 0 local (0: 51) line 1514
0x843a7fa: 202 sizeof (1: 52)
0x843a7fb: 18 2 clit (1: 52)
0x843a7fd: 49 < (2: 53)
0x843a7fe: 107 402660867 branch_when_zero (1: 52)
0x843a803: 97 257 clear_locals (0: 51) line 1519
0x843a806: 98 save_arg_frame (0: 51)
0x843a807: 30 0 local (1: 52)
0x843a809: 451 40 mkmapping (2: 53)
0x843a80b: 99 restore_arg_frame (2: 53)
0x843a80c: 125 1 push_local_variable_lvalue (1: 52)
0x843a80e: 41 (void)= (2: 53)
0x843a80f: 97 258 clear_locals (0: 51) line 1523
0x843a812: 15 const0 (0: 51)
0x843a813: 125 2 push_local_variable_lvalue (1: 52)
0x843a815: 41 (void)= (2: 53)
0x843a816: 106 branch (0: 51)
0x843a845: 30 2 local (0: 51)
0x843a847: 30 0 local (1: 52)
0x843a849: 202 sizeof (2: 53)
0x843a84a: 49 < (2: 53)
0x843a84b: 110 bbranch_when_non_zero (1: 52)
0x843a818: 98 save_arg_frame (0: 51) line 1525
0x843a819: 30 1 local (1: 52)
0x843a81b: 30 0 local (2: 53)
0x843a81d: 30 2 local (3: 54)
0x843a81f: 186 no_warn_deprecated (4: 55)
0x843a820: 61 index (4: 55)
0x843a821: 449 38 member (3: 54)
0x843a823: 99 restore_arg_frame (2: 53)
0x843a824: 107 13 branch_when_zero (1: 52)
0x843a826: 30 1 local (0: 51) line 1527
0x843a828: 30 0 local (1: 52)
0x843a82a: 30 2 local (2: 53)
0x843a82c: 186 no_warn_deprecated (3: 54)
0x843a82d: 61 index (3: 54)
0x843a82e: 366 23 m_delete (2: 53)
0x843a830: 92 pop_value (1: 52)
0x843a831: 106 branch (0: 51) line 1529
0x843a842: 125 2 push_local_variable_lvalue (0: 51) line 1523
0x843a844: 32 ++ (1: 52)
0x843a845: 30 2 local (0: 51)
0x843a847: 30 0 local (1: 52)
0x843a849: 202 sizeof (2: 53)
0x843a84a: 49 < (2: 53)
0x843a84b: 110 bbranch_when_non_zero (1: 52)
0x843a818: 98 save_arg_frame (0: 51) line 1525
0x843a819: 30 1 local (1: 52)
0x843a81b: 30 0 local (2: 53)
0x843a81d: 30 2 local (3: 54)
0x843a81f: 186 no_warn_deprecated (4: 55)
0x843a820: 61 index (4: 55)
0x843a821: 449 38 member (3: 54)
0x843a823: 99 restore_arg_frame (2: 53)
0x843a824: 107 13 branch_when_zero (1: 52)
0x843a826: 30 1 local (0: 51) line 1527
0x843a828: 30 0 local (1: 52)
0x843a82a: 30 2 local (2: 53)
0x843a82c: 186 no_warn_deprecated (3: 54)
0x843a82d: 61 index (3: 54)
0x843a82e: 366 m_delete (2: 53)
0x843a830: 92 106 15 168 0 0 30 2
' heart_beat' in ' class/npc/npc.c' ('domains/skeleton/npc/hobgoblin#254') line 288
' heart_beat' in 'class/living/living.c' ('domains/skeleton/npc/hobgoblin#254') line 472
'heart_beat_addon' in 'class/living/modules/combat.c' ('domains/skeleton/npc/hobgoblin#254') line 5409
' do_attack' in 'class/living/modules/combat.c' ('domains/skeleton/npc/hobgoblin#254') line 4707
' damage' in 'class/living/living.c' ('class/interactive/interactive#190') line 1019
' damage' in 'class/living/modules/body.c' ('class/interactive/interactive#190') line 2242
' inform' in 'kernel/simul_efuns/lpc.c' (' kernel/simul_efun') line 918
' mkset' in 'kernel/simul_efuns/lpc.c' (' kernel/simul_efun') line 1527
2009.10.05 18:54:56 LDMud aborting on fatal error.

Program received signal SIGSEGV, Segmentation fault.
fatal (fmt=0x81131fc "Mapping entry didn't hash to the same spot.\n") at simulate.c:587
587 *((char*)0) = 0/a;

I tracked down the array that has been send to this method, that makes the game crash. However, if one recreates an array like this, the game works as expected:

({ /* 0000001, size: 12 */
  /class/interactive/interactive#105,
  0,
  /domains/skeleton/npc/hobgoblin#295,
  /class/container/base/bag#114,
  /class/item/base/flintstones#113,
  /class/item/base/money#112,
  /class/item/base/torch#111,
  /domains/adventurers/obj/amulet#110,
  /domains/human/town/obj/sells/ferry_ticket_time#108,
  /domains/human/town/obj/sells/ferry_ticket_time#109,
  /domains/system/startup_item/cleric_robe#107,
  /domains/system/startup_item/staff#106
})

As soon as possible I will add a smaller example that reproduces the problem. For now, maybe someone has an idea. The bug does not occur in the 3.3.x driver.
TagsNo tags attached.
Attached Files
bug689.diff (1,581 bytes)   
Index: trunk/test/t-mantis.c
===================================================================
--- trunk/test/t-mantis.c	(Revision 2764)
+++ trunk/test/t-mantis.c	(Arbeitskopie)
@@ -326,6 +326,30 @@
         :)
     }),
 #endif // __XML_DOM__
+    ({ "0000689", 0,
+        (:
+            // Each pass will crash with approx. 40% propability.
+            // So let's make that a sure thing:
+            foreach(int i: 1000)
+            {
+                mapping xm = ([
+                    clone_object(this_object()),
+                    clone_object(this_object())
+                ]);
+                object * x = m_indices(xm);
+
+                destruct(x[0]);
+                destruct(x[1]);
+
+                // This will crash when there is a destructed object with the
+                // same hash value as '0' and would have another hash value
+                // with being '0' instead of a destructed object.
+                m_delete(mkmapping(x),0);
+            }
+
+            return 1;
+        :)
+    }),
 });
 
 void run_test()
Index: trunk/src/mapping.c
===================================================================
--- trunk/src/mapping.c	(Revision 2764)
+++ trunk/src/mapping.c	(Arbeitskopie)
@@ -821,6 +821,11 @@
         map_index->u.str = make_tabled(map_index->u.str);
     }
 
+    /* Check if it's a destructed object.
+     */
+    if (destructed_object_ref(map_index))
+        assign_svalue(map_index, &const0);
+
     /* Generate secondary information for types which usually
      * have none (required for hashing).
      */
bug689.diff (1,581 bytes)   

Activities

Bardioc

2009-10-05 14:12

reporter   ~0001468

Testcase that reproduces the problem (maybe not at first try, but at second or third)

public mixed * _mkset(mixed * arr)
{
    if (sizeof(arr) < 2)
    {
        return arr;
    }

    mapping set = mkmapping(arr);

    // walk through all entries in the array and if found in the mapping, remove it from there, if
    // not found in the mapping, remove it from the array
    for (int i = 0; i < sizeof(arr); i++)
    {
        if (member(set, arr[i]))
        {
            m_delete(set, arr[i]);
        }
        else
        {
            arr[i..i] = ({});

            --i;
        }
    }

    return arr;
}

public void test()
{
    object * x = ({});

    for (int i = 0; i < 50; i++)
    {
        for (int j = 0; j < 25; j++)
        {
            x += ({ clone_object("/class/item/base/torch") });
        }

        destruct(x[random(25)]);

        _mkset(x);
    }
}

simply call test() multiple times, it crashes at the m_delete() in _mkset()

Gnomi

2009-10-07 01:37

manager   ~0001508

I attached a patch that fixes this (the patch is already committed for 3.5 as r2765 and will be committed for 3.3 after review).

The problem was that the destructed object was replaced by zero after its hash was calculated and thus the hash wouldn't fit anymore.

Gnomi

2009-11-10 14:19

manager   ~0001616

Committed as r2804.

Issue History

Date Modified Username Field Change
2009-10-05 12:44 Bardioc New Issue
2009-10-05 14:12 Bardioc Note Added: 0001468
2009-10-06 03:34 Gnomi Assigned To => Gnomi
2009-10-06 03:34 Gnomi Status new => confirmed
2009-10-07 01:20 Gnomi File Added: bug689.diff
2009-10-07 01:37 Gnomi Note Added: 0001508
2009-11-10 14:18 Gnomi Project LDMud => LDMud 3.3
2009-11-10 14:19 Gnomi Note Added: 0001616
2009-11-10 14:19 Gnomi Status confirmed => resolved
2009-11-10 14:19 Gnomi Fixed in Version => 3.3.720
2009-11-10 14:19 Gnomi Resolution open => fixed
2011-02-23 22:22 zesstra Target Version => 3.3.720