mIRC Homepage

Large number of SendMessages unset &binvars

Posted By: maroon

Large number of SendMessages unset &binvars - 17/07/19 09:19 PM

A large number of received SendMessage's results in destroying the existence of all &binvar. The examples here have each SendMessage executing $bvar(), but it seems to kill the binvars regardless whether it's accessing the same binvar, or a different one each time. The effect is cumulative across separate calls to the .dll within the same lifetime of the binvar in the script thread, and I've found this happening in the current version under Win10 and under v6.35 in Windows7. It is demonstrated by using Saturn's sha2.dll, but as far as I can tell has zero to do with any hash function.

Each sha2.dll call makes a SendMessage of $bvar(&binvar,offset,1037) to read a portion of the binvar, stopping after one of the replies does not return 1037 byte values, so it makes 1 SendMessage for lengths 0-1037, and 2 of them for lengths 1037-2073, etc.

To the best of my knowledge, there isn't a protocol for sharing binary data with a mirc .dll, so the best known workarounds are to either write the data to disk and have the .dll read the binary content from disk - or do like this .dll does, where it uses SendMessage to ask $bvar to fetch the contents of the binvar. It appears that once this latter method has been done 9991 times, the binvar accessed by that 9991'st SendMessage is completely deleted, and isn't available for access even within the script thread context directly.

It's not clear to me whether it matters that $bvar is being called, or just that 9991 SendMessages has the effect of crashing the context data containing the existence of &binvars.


1. Run this command, which works correctly.

//bset &v $calc(1037*9990-1+0) 0 | bset &test 1 1 | echo -a $dll(sha2.dll,sha256,1 &v) test: $bvar(&test) | echo 3 -a binvar $bvar(&v) length is $bvar(&v,0) | echo 4 -a $sha256(&v,1)

It shows the hash of the binvar and the fact that &test still exists, and the green message shows the &v binvar exists after 9990 SendMessages, and the red message shows that the built-in identifier is able to access the &v binvar and arrives at the same answer.

2. Now edit the 9990 into 9991 and repeat. The .dll calculates the correct hash for the slightly longer binvar, but the green message shows that the &v binvar has length zero, and the fact that $bvar(&v) is $null shows the binvar does not exist, not just truncated. It also shows the same thing happened to &test, which now doesn't exist. The &binvar was deleted during the 9991'st SendMessage after correctly returning the contents of that &binvar. When testing in older versions, the $bvar(&v) must be changed to $bvar(&v,0) to avoid invalid syntax for those versions, but otherwise the same binvar deletions happened as old as v6.35.

3. The destruction of the binvars seems related to the number of $bvar() calls made via SendMessage within the script thread, not the number of accessings of a specific binvar and not the number of $dll() calls.

//var %i 0, %list | while (%i isnum 0-10000) { inc %i | var %a &v $+ %i | bset -c %a 123 1 | noop $dll(sha2.dll,sha256,1 %a) | if (!$bvar(%a,0)) { echo -a binvar $bvar(%a) deleted after %i sendmessages | while (%i) { if ($bvar(&v $+ %i)) var %list %list $v1 | dec %i } | echo -a binvars existing: %list | halt } } | echo -a binvar exists after %i loops

This example created a new binvar, named &v1 through &v9991, to be used for each $dll() call where the &binvar is short enough that it makes 1 SendMessage per loop. The SendMessage uses $bvar(&binvar,offset,1037) to read a portion of the binvar, and all binvar's are again deleted after the 9991'st such SendMessage. After finding the binvar missing after the return from the $dll() call, it then checks for the existence of any of the &v1 through &v9991 binvars, and finds they're all gone.

If the binvar's length is edited to be in the 1037-2073 range causing 2 SendMessage's per dll call, the number of loops is halved, showing it's related to the number of SendMessages. If the /noop command is edited to contain the $bvar() call directly instead of via the $dll() call, the binvar does not get deleted. Adding a bunset to delete the binvar's after each usage has no effect, so the number of binvars is not causing a problem.

The issue appears to matter only when 9991 SendMessages are made from within the same script thread. You can repeat the above 9990 SendMessages as 2 separate editbox commands, or from 2 separate timer executions, without problem.

Note: If testing under v6.35, be sure to not edit the content of the binvar, as the v6.35 text buffer for receiving the sendmessage crashes mIRC if exceeding approx length 2100. The following crashes v6.35, but changing the string from 'd' into 'c' does not crash because the length is then shorter enough. Even when the string length is 4150, it hasn't crashed any recent v7 version.

//bset -t &v 1 $str(d,526) | echo -a $dll(sha2.dll,sha256,1 &v ) | echo -a $bvar(&v,1-)

Posted By: Raccoon

Re: Large number of SendMessages unset &binvars - 18/07/19 12:27 AM

Somehow seems related to the recently corrected bug with /url, in that all your sendmessage communications is putting the scripting thread into an asynchronous , that is, losing synchronization.

If accessing the DLL from an On TEXT event, do the event identifiers also become null? $nick, $address, $target, $eventparms, etc?
Posted By: maroon

Re: Large number of SendMessages unset &binvars - 18/07/19 03:01 AM

I tested in the beta 86 which was fixing the url problem. I inserted my topmost example inside ON TEXT, then edited the 9990 into 9991, then inserted a new echo message containing your suggested local identifiers between the green and red messages. While the binvars were still wiped out above it, the local identifiers you suggested all remained having the correct defined strings.
Posted By: Khaled

Re: Large number of SendMessages unset &binvars - 18/07/19 01:13 PM

Thanks for your bug report. This issue has been fixed for the next version.
© 2019 mIRC Discussion Forums