WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Bagnon causes restricted enviroment lock? (https://www.wowinterface.com/forums/showthread.php?t=52911)

MunkDev 11-24-15 05:27 PM

Bagnon causes restricted environment lock?
 
I'm currently using some table manipulation inside the secure environment, where I gather unit frames by recursively scanning the UIParent and inserting all protected frames with a unit attribute assigned into a restricted table.

This works flawlessly - until I open interface settings. After that, attempting to run the snippet that gathers nodes results in this error:
Lua Code:
  1. 1x FrameXML\RestrictedExecution.lua:397: Call failed: FrameXML\RestrictedExecution.lua:397: Call failed: FrameXML\RestrictedExecution.lua:397: Call failed: FrameXML\RestrictedInfrastructure.lua:365: Cannot create restricted tables from insecure code
  2. [C]: ?
  3. FrameXML\RestrictedExecution.lua:397: in function <FrameXML\RestrictedExecution.lua:390>
  4. (tail call): ?
  5. (tail call): ?
  6. FrameXML\SecureHandlers.lua:283: in function <FrameXML\SecureHandlers.lua:277>
  7. (tail call): ?
  8.  
  9. Locals:
  10. workingEnv = <userdata>
  11. ctrlHandle = <userdata>
  12. pcallFlag = false
  13. LOCAL_Function_Environment_Manager = <function> defined @FrameXML\RestrictedExecution.lua:209
  14. error = <function> defined =[C]:-1
  15. tostring = <function> defined =[C]:-1

Naturally, I turned to the trustworthy taint log to see what the hell happend. After sifting through all the bloat I found this:
Code:

11/25 00:02:09.812  Execution tainted by Bagnon while reading BagnonFrameinventory - Interface\FrameXML\UIParent.lua:2784
11/25 00:02:09.812      securecall()
11/25 00:02:09.812      Interface\FrameXML\UIParent.lua:2824 CloseWindows()
11/25 00:02:09.812      Interface\FrameXML\UIParent.lua:2852
11/25 00:02:09.812      securecall()
11/25 00:02:09.812      Interface\FrameXML\UIParent.lua:3532 ToggleGameMenu()
11/25 00:02:09.812      TOGGLEGAMEMENU:1
11/25 00:02:09.812  Execution tainted by Bagnon while reading BagnonFrameinventory - Interface\FrameXML\UIParent.lua:2784
11/25 00:02:09.812      securecall()
11/25 00:02:09.812      Interface\FrameXML\UIParent.lua:2824
11/25 00:02:09.812      securecall()
11/25 00:02:09.812      Interface\FrameXML\UIParent.lua:1966 <unnamed>:ShowUIPanel()
11/25 00:02:09.812      Interface\FrameXML\UIParent.lua:1880
11/25 00:02:09.812      <unnamed>:SetAttribute()
11/25 00:02:09.812      Interface\FrameXML\UIParent.lua:2630 ShowUIPanel()
11/25 00:02:09.812      Interface\FrameXML\UIParent.lua:3543 ToggleGameMenu()
11/25 00:02:09.812      TOGGLEGAMEMENU:1

By disabling Bagnon, the errors disappear and I can continue to securely manipulate tables after opening the interface settings. So far, I've had no taint issues with Bagnon, but attempting to manipulate tables after viewing the interface settings seems to cause a complete meltdown.

So what I'm really asking here is:
  1. Can I prevent this from happening or is the problem only related to Bagnon?
  2. Can I determine whether I'm running a tainted execution path and thereby circumvent the lockdown?

Here's the actual code, but it's all executed within a secure enviroment and using secure buttons to trigger changes within.
It works regardless of combat state and hasn't broken down in any other scenario thus far.

jaliborc 11-24-15 06:55 PM

The only thing I can think of is that Bagnon uses the ColorPickerFrame in the configuration panel.

Resike 11-24-15 09:38 PM

What are you trying to accomplish? Trying to hook the functionalty of every unit frame from the UIParent?

MunkDev 11-24-15 10:48 PM

Quote:

Originally Posted by Resike (Post 311953)
What are you trying to accomplish? Trying to hook the functionalty of every unit frame from the UIParent?


Four secure buttons are each given a direction, which is used to find the most appropriate selection from a table of unit frames. The wrapped pre-body generates a unit attribute, which is then attached to the button and fired immediately afterwards. The result is a one button press to both find the next unit frame and "click" that unit frame. The most appropriate unit frame is determined by looking at where the unit frames are drawn on screen. The cursor you see in that gif is just smoke and mirrors.
I'm not actually hooking anything.

MunkDev 11-25-15 12:16 AM

Quote:

Originally Posted by jaliborc (Post 311948)
The only thing I can think of is that Bagnon uses the ColorPickerFrame in the configuration panel.

Is that normally a culprit in issues like these?
I can't say for sure that Bagnon is causing the issue, but disabling it solves the problem.

This is the part where shit hits the fan:
Lua Code:
  1. local children = newtable(self:GetFrameRef("UIParent"):GetChildren())

MunkDev 11-25-15 01:40 AM

I figured out a workaround, which involves scanning the children of UIParent outside the secure environment and then pushing the frames onto a stack one by one if they are protected.

Attempting to insert something tainted into a table created in the secure environment is most likely what caused the problem. Since InterfaceOptionsFrame is a child of UIParent, it would be included in the table if the scan is done outside of combat. Why specifically Bagnon seemed to be the culprit, I'm not sure. But this solution works:

Lua Code:
  1. function ConsolePort:UpdateSecureFrameStack()
  2.     if not InCombatLockdown() then
  3.         for i, child in pairs({UIParent:GetChildren()}) do
  4.             if not child:IsForbidden() and child:IsProtected() then
  5.                 UIHandle:SetFrameRef("NewChild", child)
  6.                 UIHandle:Execute([[
  7.                     FrameStack[self:GetFrameRef("NewChild")] = true
  8.                 ]])
  9.             end
  10.         end
  11.     end
  12. end

Lua Code:
  1. -- Changed this to only scan a predefined table instead of creating a new one
  2. UIHandle:Execute([[
  3.     UpdateFrameStack = [=[
  4.         Nodes = wipe(Nodes)
  5.         for Frame in pairs(FrameStack) do
  6.             CurrentNode = Frame
  7.             self:Run(GetNodes)
  8.         end
  9.     ]=]
  10. ]])

semlar 11-25-15 01:50 AM

The taint log is pointing to bagnon inserting its frame into the UISpecialFrames table which is read by the CloseSpecialWindows function in UIParent.lua.

Your error itself is being caused by "newtable" being called from a tainted execution path, and frankly I don't know how that's even possible.

MunkDev 11-25-15 02:21 AM

Quote:

Originally Posted by semlar (Post 311961)
Your error itself is being caused by "newtable" being called from a tainted execution path, and frankly I don't know how that's even possible.

It's possible because handle:GetChildren() will still return unprotected frames in the secure environment when you're not in combat. Since they are unprotected, they can very well be tainted. It's kind of a trojan horse in the secure environment. :p

semlar 11-25-15 02:48 AM

Quote:

Originally Posted by MunkDev (Post 311962)
It's possible because handle:GetChildren() will still return unprotected frames in the secure environment when you're not in combat. Since they are unprotected, they can very well be tainted. It's kind of a trojan horse in the secure environment. :rolleyes:

Any frame created by an addon that isn't secure is, by definition, tainted, so unless bagnon is the only thing you're running with a child of UIParent something else would also trigger it.

Here's an example that outputs all unprotected children of UIParent when you mouse over a unit. If you're in combat, GetChildren() will simply not include those frames, it doesn't freak out about a tainted execution path.
Lua Code:
  1. local f = CreateFrame('frame', nil, UIParent, 'SecureHandlerStateTemplate')
  2. f:SetAttribute('_onstate-mousestate', [[
  3.     if newstate == 'on' then
  4.         for i, f in pairs(newtable(self:GetParent():GetChildren())) do
  5.             if not f:IsProtected() and f:GetName() then
  6.                 print(f:GetName())
  7.             end
  8.         end
  9.     end
  10. ]])
  11. RegisterStateDriver(f, 'mousestate', '[@mouseover,exists] on; off')

MunkDev 11-25-15 02:59 AM

Quote:

Originally Posted by semlar (Post 311963)
Here's an example that outputs all unprotected children of UIParent when you mouse over a unit. If you're in combat, GetChildren() will simply not include those frames, it doesn't freak out about a tainted execution path.
...

This example triggers the same shitstorm when only Bagnon is running. Only happens after opening the interface settings, though. I think my workaround is somewhat more robust anyway, but maybe the developer(s) of Bagnon should look into it.

semlar 11-25-15 03:02 AM

Quote:

Originally Posted by MunkDev (Post 311964)
This example triggers the same shitstorm when only Bagnon is running. Only happens after opening the interface settings, though. I think my workaround is somewhat more robust anyway, but maybe the developer(s) of Bagnon should look into it.

Alright, apparently the version of Bagnon that's on wowinterface is a different version than what's on curse.

The version that's on curse does cause this error, so it's something they've managed to do between the version that's on here and the version that's on curse.

MunkDev 11-25-15 03:13 AM

Quote:

Originally Posted by semlar (Post 311965)
I can't reproduce this, running Bagnon. You're just opening the escape menu and clicking on the Interface button?

Yes. I even disabled WowLua as well to make sure, which was the only other addon I had running.
To reproduce, try this: run the code you posted, then open Interface, head to the Addons tab, then close the frame. After that, mouseover triggers the error.
I ran this compressed version since I disabled WowLua:
Lua Code:
  1. /run local f = CreateFrame('frame',nil, UIParent,'SecureHandlerStateTemplate') f:SetAttribute('_onstate-mousestate', [[local t = newtable(self:GetParent():GetChildren())]]) RegisterStateDriver(f,'mousestate','[@mouseover,exists] on; off')

Quote:

Originally Posted by semlar (Post 311965)
Also, since the error you posted doesn't point to any specific cause outside of blizzard's code, I don't know how you know what's triggering it.

ConsolePort has a binding manager in the interface options, and I went in to edit bindings which is when I discovered the error. After reading the taint log, I went ahead and tried to disable Bagnon and that worked. I'm using the latest version of Bagnon.

MunkDev 11-25-15 03:20 AM

Quote:

Originally Posted by semlar (Post 311965)
Alright, apparently the version of Bagnon that's on wowinterface is a different version than what's on curse.

The version that's on curse does cause this error, so it's something they've managed to do between the version that's on here and the version that's on curse.

I see. The question is now whether I leave my workaround in place or go back to the way it was before. The downside of my current approach is that it can't find unit frames created while in combat. But is that even possible, come to think of it?

semlar 11-25-15 03:21 AM

Well, I've identified that the first version of Bagnon with this issue is 6.0.20, which was a "complete rewrite" according to the change log.

I'd like to know exactly what they did to cause this, because I'm pretty sure it shouldn't be possible, but that will take some more investigating.

Quote:

Originally Posted by MunkDev (Post 311967)
I see. The question is now whether I leave my workaround in place or go back to the way it was before. The downside of my current approach is that it can't find unit frames created while in combat. But is that even possible, come to think of it?

Secure frames can't be created in combat, at least not by addons, but existing frames can have their attributes changed (like which unit they're pointing to).

Since even the default blizzard raid frames break when a player joins or leaves in combat, I doubt it's something you need to account for.

edit: The issue is being caused from Bagnon_Config importing "sushi" from bagnon\libs.

MunkDev 11-25-15 03:34 AM

Quote:

Originally Posted by semlar (Post 311968)
Well, I've identified that the first version of Bagnon with this issue is 6.0.20, which was a "complete rewrite" according to the change log.

I'd like to know exactly what they did to cause this, because I'm pretty sure it shouldn't be possible, but that will take some more investigating.

Secure frames can't be created in combat, at least not by addons, but existing frames can have their attributes changed (like which unit they're pointing to).

Since even the default blizzard raid frames break when a player joins or leaves in combat, I doubt it's something you need to account for.

Well, at least it wasn't my fault! :p

I use a bunch of secure code to accomplish the functionality of ConsolePort and its innate gimmicks, so I'm somewhat versed in the SecureHeaders, but never had this problem happen before. I'll just leave the workaround in place for now, since it's not really necessary to scan every child of UIParent whenever my fake cursor is toggled on.

semlar 11-25-15 03:44 AM

The offending file appears to be Bagnon\libs\Sushi-3.0\Classes\TextureDropdown.lua calling SushiGroup() which is executing something in Group.lua

Oh good god, it's from his poncho library doing unspeakable things to his frame's metatable. I'm going to let him fix this himself.

MunkDev 11-25-15 04:25 AM

Quote:

Originally Posted by semlar (Post 311970)
The offending file appears to be Bagnon\libs\Sushi-3.0\Classes\TextureDropdown.lua calling SushiGroup() which is executing something in Group.lua

Oh good god, it's from his poncho library doing unspeakable things to his frame's metatable. I'm going to let him fix this himself.

Lol. You're quite the detective. :D
I agree this needs to be fixed asap, since it can potentially break many other addons in its wake. Knowing I can't use restricted tables safely when Bagnon is running makes me want to disable it until it's fixed.

Lombra 11-25-15 10:01 AM

Quote:

Originally Posted by semlar (Post 311968)
Secure frames can't be created in combat, at least not by addons, but existing frames can have their attributes changed (like which unit they're pointing to).

Since even the default blizzard raid frames break when a player joins or leaves in combat, I doubt it's something you need to account for.

Raid frames can be created in combat for addons using secure group header thingies, no? (I know the addon itself isn't creating the frame, that's beside the point)

semlar 11-25-15 10:24 AM

Quote:

Originally Posted by Lombra (Post 311974)
Raid frames can be created in combat for addons using secure group header thingies, no? (I know the addon itself isn't creating the frame, that's beside the point)

Group headers are designed to automate the creation of these frames; however, I have yet to see an addon, including blizzard's own raid frames, not break when someone joins the raid while you're in combat.

I haven't personally done anything with them, so it's quite possible I'm mistaken. It's not something simple to test without involving other people.

MunkDev 11-25-15 10:38 AM

Quote:

Originally Posted by semlar (Post 311976)
It's not something simple to test without involving other people.

Somehow getting into combat in Proving Grounds and then starting the healer challenge?

Anyway, I would ideally like to employ the most dynamic solution, but Bagnon currently craps all over that. The trade-off when gathering nodes outside the secure environment is not finding secure frames created in combat (assuming that's not entirely fictional), but at least it deals with this wonky issue.

I've never been much for libraries since I like to do things the hard way and learn something in the process, but is this a Poncho thing or only related to Bagnon? What is Poncho even used for? Is it popular?


All times are GMT -6. The time now is 08:43 PM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI