Announcement

Collapse

Forum Rules

  • No flaming or derogatory remarks, directly or through insinuation.
  • No discussion, sharing or referencing illegal software such as hacks, keygen, cracks and pirated software.
  • No offensive contents, including but not limited to, racism, gore or pornography.
  • No excessive spam/meme, i.e. copious one liners in a short period of time, typing with all caps or posting meme responses (text/image).
  • No trolling, including but not limited to, flame incitation, user provocation or false information distribution.
  • No link spamming or signature advertisements for content not specific to Dota 2.
  • No Dota 2 key requests, sell, trade etc.
  • You may not create multiple accounts for any purpose, including ban evasion, unless expressly permitted by a moderator.

  • Please search before posting. One thread per issue. Do not create another thread if there is an existing one already.
  • Before posting anything, make sure you check out all sticky threads (e.g., this). Do not create new threads about closed ones.
  • It is extremely important that you post in correct forum section.

  • Balance discussion only in Misc.
  • All art related (such as hero model) feedbacks go to Art Feedback Forum.
  • All matchmaking feedback should go here: Matchmaking Feedback
  • All report/low priority issues should go here: Commend/Report/Ban Feedback
  • No specific workshop item feedback. These should go to workshop page of that item.
  • When posting in non-bugs section (such as this), use [Bugs], [Discussion] or [Suggestion] prefix in your thread name.



In case you object some action by a moderator, please contact him directly through PM and explain your concerns politely. If you are still unable to resolve the issue, contact an administrator. Do not drag these issues in public.



All rules are meant to augment common sense, please use them when not conflicted with aforementioned policies.
See more
See less

[CRASH BUG] CustomGameEventManager Crash Related to the Internal Lua Table Order

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • [CRASH BUG] CustomGameEventManager Crash Related to the Internal Lua Table Order

    Hello,

    Through extensive testing I have been able to find and reproduce a crash bug relating to the CustomGameEventManager:Send_ServerToPlayer function and (very peculiarly) the internal lua table order representation.

    The Bug
    It is possible to crash the game by sending a lua table, while a lua table with identical content does not crash the game, with the only difference being the ordering of table fields as shown by iterating the table. This has been tested in tools mode only.

    The following code will NOT crash the game, and assumes that Player 0 is an active and connected player.
    Code:
    local player =PlayerResource:GetPlayer(0)
    local tt = {
         buttons={},
         headerText="Container Test",
         id=0,
         layout={2,3,4},
         ptID="cont_0",
         rowStarts={1,3,6},
         size=9,
         skins={HourGlass=true, Something=true},
         slot4=255,
         slot9=256}
    
    tt = {name="cont_0", table=tt}
    
    DeepPrintTable(tt)
    
    CustomGameEventManager:Send_ServerToPlayer(player, "pt_table_full_update", tt )
    DeepPrintTable in this code reports the contents of table 'tt' as:
    Code:
    [   VScript        ]: {
    [   VScript        ]:    name                            	= "cont_0" (string)
    [   VScript        ]:    table                           	= table: 0x0026e0d8 (table)
    [   VScript        ]:    {
    [   VScript        ]:       rowStarts                       	= table: 0x002660a8 (array table)
    [   VScript        ]:       [
    [   VScript        ]:          1                               	= 1 (number)
    [   VScript        ]:          2                               	= 3 (number)
    [   VScript        ]:          3                               	= 6 (number)
    [   VScript        ]:       ]
    [   VScript        ]:       skins                           	= table: 0x0026b660 (table)
    [   VScript        ]:       {
    [   VScript        ]:          HourGlass                       	= true (boolean)
    [   VScript        ]:          Something                       	= true (boolean)
    [   VScript        ]:       }
    [   VScript        ]:       id                              	= 0 (number)
    [   VScript        ]:       layout                          	= table: 0x0026b610 (array table)
    [   VScript        ]:       [
    [   VScript        ]:          1                               	= 2 (number)
    [   VScript        ]:          2                               	= 3 (number)
    [   VScript        ]:          3                               	= 4 (number)
    [   VScript        ]:       ]
    [   VScript        ]:       buttons                         	= table: 0x0026b588 (table)
    [   VScript        ]:       {
    [   VScript        ]:       }
    [   VScript        ]:       slot9                           	= 256 (number)
    [   VScript        ]:       slot4                           	= 255 (number)
    [   VScript        ]:       headerText                      	= "Container Test" (string)
    [   VScript        ]:       ptID                            	= "cont_0" (string)
    [   VScript        ]:       size                            	= 9 (number)
    [   VScript        ]:    }
    [   VScript        ]: }

    The following code WILL crash the game, despite the table being equivalent in content to the above table:
    Code:
    local player =PlayerResource:GetPlayer(0)
    local tt = {
      id=0,
      ptID="cont_0",
      layout={2,3,4},
      size=0,
      rowStarts={},
      skins={},
      buttons={},
      headerText="Container Test"
    }
    
    tt.size = 9
    table.insert(tt.rowStarts, 1)
    table.insert(tt.rowStarts, 3)
    table.insert(tt.rowStarts, 6)
    
    tt.skins["HourGlass"] = true
    tt.skins["Something"] = true
    
    tt["slot4"] = 255
    tt["slot9"] = 256
    
    tt = {name="cont_0", table=tt}
    
    DeepPrintTable(tt)
    
    CustomGameEventManager:Send_ServerToPlayer(player, "pt_table_full_update", tt )
    The DeepPrintTable for this table is
    Code:
    [   VScript        ]: {
    [   VScript        ]:    name                            	= "cont_0" (string)
    [   VScript        ]:    table                           	= table: 0x002716d0 (table)
    [   VScript        ]:    {
    [   VScript        ]:       ptID                            	= "cont_0" (string)
    [   VScript        ]:       size                            	= 9 (number)
    [   VScript        ]:       headerText                      	= "Container Test" (string)
    [   VScript        ]:       layout                          	= table: 0x002717c0 (array table)
    [   VScript        ]:       [
    [   VScript        ]:          1                               	= 2 (number)
    [   VScript        ]:          2                               	= 3 (number)
    [   VScript        ]:          3                               	= 4 (number)
    [   VScript        ]:       ]
    [   VScript        ]:       buttons                         	= table: 0x00271860 (table)
    [   VScript        ]:       {
    [   VScript        ]:       }
    [   VScript        ]:       slot9                           	= 256 (number)
    [   VScript        ]:       slot4                           	= 255 (number)
    [   VScript        ]:       rowStarts                       	= table: 0x00271810 (array table)
    [   VScript        ]:       [
    [   VScript        ]:          1                               	= 1 (number)
    [   VScript        ]:          2                               	= 3 (number)
    [   VScript        ]:          3                               	= 6 (number)
    [   VScript        ]:       ]
    [   VScript        ]:       skins                           	= table: 0x00271838 (table)
    [   VScript        ]:       {
    [   VScript        ]:          HourGlass                       	= true (boolean)
    [   VScript        ]:          Something                       	= true (boolean)
    [   VScript        ]:       }
    [   VScript        ]:       id                              	= 0 (number)
    [   VScript        ]:    }
    [   VScript        ]: }
    As you can see, the key-value contents of both tables are equivalent, but one causes a crash when pushed through the CustomGameEventManager and the other does not. In tools mode I am able to reproduce this in all cases, and hope that such reproducibility will yield a relatively simple fix-action. I have run into crashes related to CustomGameEventManager events before, but adjusting my event table structure was sufficient for them to stop happening. In this case, however, the variable structure is necessary in order to support my library for an events system simulating player-specific NetTables, and all systems that are subsequently based on that.

    Thanks for your attention on this matter.
    --BMD

  • #2
    I have also encountered this very difficult to track bug. I determined that the issue had something to do with the naming of the table keys but did not have enough information to provide a detailed bug report. Nice work finding more info about the crash. Unfortunately not having access to the serializer/parser code for custom events, and the fact that the issue hard crashes the client with no errors, makes debugging quite difficult and time consuming.

    Comment


    • #3
      As an update, I have done some more testing to further clarify what causes a crash and what does not. While order matters, I have also been able to determine that the system cannot crash so long as at every "node" in the tree of tables sent, there are never any tables AND non-tables (string, number) data present at the same node level. The crash only occurs when tables and non-tables are present in the same level, at which point the order begins to matter.

      I can send a table containing only strings/number types of any length, keysize, key characters, etc. I can send a table containing only tables, which themselves contain only strings/number types.

      For example, the following hastebin link shows a table which does not crash, by effectively wrapping all "string"/"number" types in a 1-length array table so that they can never be present in "raw" form alongside a table.
      http://hastebin.com/vojixoqoga.coffee

      I still hope that this issue can be resolved, as it is quite stupid to have to wrap all string/number types before sending them in order to ensure functionality.

      --BMD

      Comment


      • #4
        Additionally, I have determined that you can mix strings/tables, numbers/tables, and strings/numbers within a node and it does not appear to crash, but mixing numbers, tables, and strings can cause the crash.
        --BMD

        Comment


        • #5
          As a (hopefully short-term) workaround, I have put together a means of processing the event data tables so that they seem unable to crash the game (at least when using normal table structures with only number/string/table types). It is possible to process the table to strip and separate all of the "string" types into their own mirrored table structure within the base table. The following function can be used to perform the transformation.
          Code:
          function ProcessTable(t, strings)
            local st = strings or {}
            if t == nil then return t end
          
            if strings == nil then
              t = PlayerTables:copy(t)
            end
          
            for k,v in pairs(t) do
              if type(v) == "string" then
                st[k] = v
                t[k] = nil
              elseif type(v) == "table" then
                st[k] = {}
                ProcessTable(v, st[k])
              end
            end
          
            if strings == nil then
              t["__strings__"] = st
              return t
            end
          end
          This function takes the normal table and returns the processed form with strings separated into a "__strings__" table. For example, it can be called as follows:
          Code:
          local someTable = {str="string", num=0.5, tab={moreStuff={}, moreStrings="asdf"}}
          CustomGameEventManager:Send_ServerToPlayer(player, "some_event_whatever", ProcessTable(someTable)} )
          On the receiving (javascript) end, it is possible to "unprocess" the incoming table back into its original form with the following function:
          Code:
          function UnprocessTable(t, strings){
            if (!t)
              return t;
            
            var st = t["__strings__"] || strings;
            if (!st)
              return t;
          
            delete t["__strings__"];
          
            for (var k in st){
              if (typeof(st[k]) == "string"){
                t[k] = st[k];
              }
              else if (typeof(st[k]) == "object"){
                UnprocessTable(t[k], st[k])
              }
            }
          
            if (!strings){
              return t;
            }
          }
          For example, to subscribe to and receive the above event, you can use:
          Code:
          function ReceiveEvent(event){
            event = UnprocessTable(event);
            $.Msg(event);
          }
          
          GameEvents.Subscribe( "some_event_whatever", ReceiveEvent);
          After unprocessing, the event should be in the correct original form that it should have been sent with, without crashing the game.
          --BMD

          Comment


          • #6
            Thanks for the detailed repro information! We have a fix for this that will ship in an upcoming update.

            Comment


            • #7
              This is great news. Thanks for helping on this issue.

              Comment


              • #8
                For anyone who is interested, I didn't see a direct patch note indicating that this issue has been fixed, but it seems that it has been. It is no longer necessary to process multi-type tables before sending them to avoid crashes.

                Comment

                Working...
                X