| 11-07-2009, 01:27 AM | #1 |
Well I perused common.j and found that indeed the return bug is back. This new trick relies on this feller here:: Zinc:type fogstate extends handle Zinc:native ConvertFogState(integer i)->fogstate So what you can now do is create a handle, Get its handle Id and upconvert it to a fogstate. But what's the point? You can use hashtables to convert it from an integer back to the type you'd like:: Zinc:
local hashtable ht = InitHashtable();
local unit u = CreateUnit(Player(0),'hfoo',0,0,0)
local integer handleID = GetHandleId(u);
local fogstate h = ConvertFogState(handleID);
local agent a;
call SaveFogStateHandle(ht, 0,0,h);
set a = LoadUnitHandle(ht, 0, 0);
call BJDebugMsg(I2S(GetHandleId(a)));
Is this useless? Maybe. It might help people still using handlevars. It also might get Vex to agree that type information is USEFUL. Blizzard taketh away, but they giveth back. The hashtable is truly awesome. |
| 11-07-2009, 01:49 AM | #2 |
There's also a return bug that deals with functions that return nothing somehow returning a value or the like to manipulate the stack in such a way that you can pop an arbitrary value off the stack as any type you want. http://www.thehelper.net/forums/show....php?p=1120230 Arbitrary casting bugs are bad, and should be avoided, as it's quite possible they'll be fixed if the new I2Code is found to cause more vulnerabilities... Edit: and for the record, GetConverted____(int) functions are all native I2H(). I do believe Player() is too, but not strait I2H() as Player(0) != null. |
| 11-07-2009, 01:53 AM | #3 |
It's been back. |
| 11-07-2009, 01:55 AM | #4 |
Player is not. I checked it returns different values sometimes. The point is this is pretty damn useful as now you can ignore that worthless agent type and just use handle again as converting ints<->handle and back is possible. We can now do any sort of cast (with the exception of code obviously). The code bug is interesting, but it only works during preload if I understand as bliz blocks code reading int arrays at gametime. What would've been neat is emiting and executing dynamic code, but at last the technique only came into be after it became abolished. Edit: Yes, okay I get it I'm not the first, where as that will most certainly get fixed if blizzard actually cares about people running arbitrary code, I seriously doubt there going to restructure the bucketing of their HTs. |
| 11-07-2009, 02:15 AM | #5 |
Here is a litte framework for anyone who wants to use this; Set NOT_HANDLE to true if the return value is not a hande (integer may be the only thing that works). JASS:library Typecast globals private hashtable HASH = InitHashtable() endglobals //! textmacro TYPECAST_MACRO takes NAME, HANDLE, RETURN, HASHFUNC, NOT_HANDLE function $NAME$ takes $HANDLE$ var returns $RETURN$ static if ($NOT_HANDLE$) then call SaveFogStateHandle(HASH, 0,0, ConvertFogState(var)) return $HASHFUNC$(HASH, 0, 0) else call SaveFogStateHandle(HASH, 0, 0, ConvertFogState(GetHandleId(var))) return $HASHFUNC$(HASH, 0, 0) endif endfunction //! endtextmacro //! runtextmacro TYPECAST_MACRO("I2U", "integer", "unit", "LoadUnitHandle", "true") endlibrary |
| 11-07-2009, 02:31 AM | #6 |
The return bug is lame and just using hashtables as intended is way more awesome. The only real use this has is that it can save maps totally overgrown of I2H abuse that hashtables alone cannot save. |
| 11-08-2009, 01:22 AM | #7 |
I agree with Dusk. The only reason why Blizzard tried to get rid of the return bug in the first place was because people were putting viruses and related things in maps using them. Does this mean that it can happen again using these other return bugs, though? If not, then I'm pretty sure Blizzard wouldn't care much. If so, I guess you could bring it up to them if anyone already hasn't. |
| 11-08-2009, 03:19 AM | #8 |
And this method can't save code. But it does open up a nifty replacement of SaveAgentHandle with a SaveHandleHandle Zinc:function SaveHandleHandle(hashtable ht,int pk,int ck,handle h)->boolean { return SaveFogStateHandle(ht,pk,ck, ConvertFogState(GetHandleId(h))); } I'm pretty sure they created agent just to avoid the mess of opening up the return bug on all types, but oh well. |
| 11-08-2009, 03:28 AM | #9 |
When they were going to make the hash table natives without anything like SaveHandleHandle, I asked why did they do that considering that SaveWidgetHandle existed, they told me only 'real handles' store type information, and thus allowing the type safety with the load natives. I then asked, why not just create a new type for the real handles and allow that type to be saved... I just wish they would have actually made triggeraction extend agent... Can stuff stored with SaveHandleHandle actually be loaded? (Edit: apparently it can) Blizz showed interest in fixing the "nothing" bug for some reason, so they'll likely fix this as well. I actually think handle stack corruption can lead to exploits that we don't know about and that's the reason they spent time into fixing the whole return bug instead of just disabling returns code from the syntax... I am yet to find an old map in which replacing SetHandleHandle with a version that takes agent didn't just work. Old code just didn't mess with pseudo-handles that much, and new code does not need to rely on these things to accomplish stuff. |
| 11-08-2009, 04:06 AM | #10 | |
I wish no one had ever reported this fog thing, because now it might actually get fixed. Quote:
|
| 11-08-2009, 11:42 AM | #11 |
In all this time it should have already been possible for you to simply replace the SetHandleHandle calls. |
| 11-08-2009, 11:58 AM | #12 |
I seriously doubt they're fixing this. The way that the hashtable is implemented is a different bucket for types, unless they remove the fogstate (which I have no idea why you'd ever need to save it), or create a "faux" handle bucket, it'll probably never be fixed. |
| 11-08-2009, 04:38 PM | #13 | |
Quote:
|
| 11-08-2009, 06:28 PM | #14 |
Yep, but now you can just use that new SaveHandleHandle I posted and be done with it. I can't use any of my code as I was too trying to avoid the calls to Handle var like systems and did things like:: Zinc:function Hero_getBag takes unit h return item return GetStoredInteger(udg_gc,I2S(H2I(h)),"m_bag") return null endfunction |
