mIRC Home    About    Download    Register    News    Help

Print Thread
if '&' operator regression #266536 23/12/19 03:19 PM
Joined: Apr 2004
Posts: 845
Sat Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Apr 2004
Posts: 845
It took me several years to notice, but one of my older scripts broke due to what seems to be a regression. The following code works correctly in mIRC 6.35, but not in the two mIRC 7 versions I tested (7.58 and 7.22):

Code
if (2147483648 & 1) echo -ag This should not trigger

These values are within the basic 32-bit range also supported by other bitwise functions ($and etc.), so I am sure the original behavior was the right one..


Saturn, QuakeNet staff
Re: if '&' operator regression [Re: Sat] #266538 23/12/19 09:49 PM
Joined: Dec 2002
Posts: 4,639
Khaled Offline
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 4,639
Thanks for your bug report. I was able to reproduce this issue. The code used for "&" in newer versions of mIRC is actually identical to v6.35.

After v6.35, I upgraded to the Visual C++ 2008 compiler. This compiler handles invalid/out-of-range values differently. In older versions of Visual C++, atoi() will wrap around an overflow/underflow value and return that as a result. In newer versions of Visual C++, or at least, Visual C++ 2008, atoi() does not do that - it returns the maximum/minimum value allowed by the integer type.

There is a discussion about atoi() on stackoverflow. The conclusion seems to be that for out-of-range values, the result is undefined behaviour, as defined by the POSIX/C99/C11 standards.

That said, I could make "&":
1) check for an atoi() overflow/underflow error and make it return 0. However, that would still break scripts like yours that expect the old overflow wrap-around behaviour.
2) use INT64 values to allow a larger range of values but this would still not be backwards compatible.
3) switch to using strtol() which should return an overflow value, like the older atoi(). However, this may be compiler-specific as some people report seeing the same behaviour as atoi(). When I update to a newer version of Visual C++, the issue may return.
4) use a custom implementation of atoi() that reproduces the overflow/underflow behaviour you are expecting. Generally something I would avoid as I prefer to use standard functions.

So, technically, your script is depending on an undefined overflow/underflow behaviour.

Update: I just tested strtol() and it behaves like atoi(). So scratch option 3.

Last edited by Khaled; 24/12/19 12:58 PM.
Re: if '&' operator regression [Re: Khaled] #266540 24/12/19 06:51 PM
Joined: Apr 2004
Posts: 845
Sat Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Apr 2004
Posts: 845
Thank you for the elaborate reply. To be clear, though: what I am expecting is that the full unsigned 32-bit range be supported, for overall consistency with the built-in bitwise identifiers. That is a much more constrained issue to resolve than restoring any previous general overflow/underflow behavior, which at this point is no longer all that interesting I think (nobody else complained, after all). Given your explanation, I guess that is now more of a feature request than a bug report, but I still think that supporting the full unsigned 32-bit range makes sense. I have changed my script to use $isbit though, so leaving everything as is is also fine with me.


Saturn, QuakeNet staff
Re: if '&' operator regression [Re: Sat] #266576 29/12/19 12:02 AM
Joined: Dec 2002
Posts: 4,639
Khaled Offline
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 4,639
Right, ideally, it should have been working on unsigned 32-bit integers, like the bit-handling identifiers. It's an old feature but I can't see how changing it to using unsigned 32-bit integers will cause a backward compatiblity issue at this point, so this change will be in the next beta.

Re: if '&' operator regression [Re: Khaled] #266581 29/12/19 12:05 PM
Joined: Apr 2004
Posts: 845
Sat Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Apr 2004
Posts: 845
That sounds good, thank you!


Saturn, QuakeNet staff
Re: if '&' operator regression [Re: Khaled] #266587 29/12/19 06:08 PM
Joined: Jan 2004
Posts: 1,260
maroon Offline
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2004
Posts: 1,260
Will the signed-int32 behavior be changed in other places? Other examples I can think of offhand are:

1. /bset writes each byte as the lowest 8 bits of the number if it's less than 2^31, but always 0 if 2^31 or greater

Code
//bset &v 1 $calc(2^31) | echo -a $bvar(&v,1-) is 255 for n > 2^31-1

returns: 255 is 255 for n > 2^31-1

2. /timer doesn't permit interval greater than 2^31-1 ticks, approx 24 days. I know older OS didn't like system uptime exceeding 2^32 ticks, but I've seen mIRC in win7 correctly reporting the $ticks value when uptime exceeds 2^32.

Code
//timertest -m 1 $calc(2^31-1) noop  | echo -a max interval: $duration($timer(test).secs)

//echo -a invalid interval: | timertest -m 1 $calc(2^31) noop



3. And for a signed-int fix that would help virtually nobody outside of those having terabyte-size files, unless this has implications for other file handling issues I'm not thinking of at the moment. I created a large file consisting entirely of 2^31 $chr(13)'s, then checked for the output from $lines(). It took around 4 hours to report that there are -2147483648 lines (negative). Haven't tested to see what $read or /write think of an attempt to read/write at line 2^31, in case it dutifully freezes again for hours while searching for that file pointer. It's not likely that anyone would ever need to have that many rows in a real file, but since the count shouldn't ever be negative, the counter could be uint32 instead of signed.

Re: if '&' operator regression [Re: maroon] #266588 29/12/19 06:41 PM
Joined: Dec 2002
Posts: 4,639
Khaled Offline
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 4,639
Quote
Will the signed-int32 behavior be changed in other places?

No, this will not be changed anywhere else at this time.