Jump to content
david_navigator

Range Check Error ERangeError

Recommended Posts

The following code (which has been in my 32 bit app for about 10 years) has just started to throw a range check error for one tester.
All I can think of is that the cast of TObject to an Integer is the issue, but in that case why would it only affect one user ?
The only difference between this user and others is that he's running under WINE, but I don't know why that would make a difference ?

 

procedure TEqlistFrm.VenueEditMainKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  PostMessage(Handle, CM_SEARCH, Integer(Sender), Key);
end;

 

Share this post


Link to post

In Windows.pas:

type
  WPARAM = UINT_PTR;

 

Then:

UINT_PTR = System.UIntPtr;  // NativeUInt;

UIntPtr = NativeUInt;

 

So just change the typecast to WPARAM should be enough. Now it probably would not work fine in 64 bits?

 

Share this post


Link to post
1 hour ago, david_navigator said:

All I can think of is that the cast of TObject to an Integer is the issue, but in that case why would it only affect one user ?

32bit vs 64bit?

 

You really should not be casting to Integer at all.  Cast to WPARAM instead, which is what PostMessage() is expecting

procedure TEqlistFrm.VenueEditMainKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  PostMessage(Handle, CM_SEARCH, WPARAM(Sender), LPARAM(Key));
end;

 

  • Like 1

Share this post


Link to post
2 minutes ago, Remy Lebeau said:

32bit vs 64bit?

32bit

 

 

Quote

You really should not be casting to Integer at all.  Cast to WPARAM instead, which is what PostMessage() is expecting

It's a colleagues code who's currently on furlough so I'm a bit hesitant to change the code, especially as 

1. there are 44 instances where Sender is cast as an Integer and I don't know if they'll be any "gotchas" ?
2. I don't even know if this is the reason for the ERangeCheck as I can't reproduce.

Share this post


Link to post

Don't blame the developer - blame the poor hints - taken from Delphi XE and 10.4:

 

image.thumb.png.4e4fd01b53691ea30ee667a53501a7f7.png

 

image.thumb.png.eff755085cb152c3847a249e25b1095e.png

 

Before anyone tells me to report it - been there, done it! https://quality.embarcadero.com/browse/RSP-17110 

 

The cast to Integer is indeed wrong - see the assembly code with Bounds checking enabled:

 

Unit2.pas.31: PostMessage(Handle, CM_SEARCH, Integer(Sender), Key);
0060F70F 8B45F4           mov eax,[ebp-$0c]
0060F712 0FB700           movzx eax,[eax]
0060F715 50               push eax
0060F716 8B45F8           mov eax,[ebp-$08]
0060F719 85C0             test eax,eax
0060F71B 7905             jns $0060f722
0060F71D E80686DFFF       call @BoundErr
0060F722 50               push eax
0060F723 6800CA9A3B       push $3b9aca00
0060F728 8B45FC           mov eax,[ebp-$04]
0060F72B E8406EF4FF       call TWinControl.GetHandle
0060F730 50               push eax
0060F731 E82A67E0FF       call PostMessage

With cast to WPARAM:

 

Unit2.pas.31: PostMessage(Handle, CM_SEARCH, WPARAM(Sender), Key);
0060F70F 8B45F4           mov eax,[ebp-$0c]
0060F712 0FB700           movzx eax,[eax]
0060F715 50               push eax
0060F716 8B45F8           mov eax,[ebp-$08]
0060F719 50               push eax
0060F71A 6800CA9A3B       push $3b9aca00
0060F71F 8B45FC           mov eax,[ebp-$04]
0060F722 E8496EF4FF       call TWinControl.GetHandle
0060F727 50               push eax
0060F728 E83367E0FF       call PostMessage

 

To reproduce try enabling top down memory allocation in your windows which will cause the Sender pointer to be large enough that it will be negative when cast to Integer

Edited by Stefan Glienke
  • Like 2

Share this post


Link to post
1 minute ago, Attila Kovacs said:

then why are you asking?

If I was 100% certain that this was the reason for the RangeCheck error, then obviously I'd update the code and spend a load of time testing there were no side effects, but is it ?
As I said the code's been like this for 10 years, it's code that executes around the world 1000's of times a day and I've only had a report from one user.

Share this post


Link to post

This is the very same analogy as 10 billion flies can't be wrong.

You should really go like @Remy Lebeau suggested.

Optionally you could read up signed and unsigned data.

Edited by Attila Kovacs

Share this post


Link to post
5 minutes ago, Stefan Glienke said:

Don't blame the developer - blame the poor hints - taken from Delphi XE and 10.4:

 

image.thumb.png.4e4fd01b53691ea30ee667a53501a7f7.png

 

image.thumb.png.eff755085cb152c3847a249e25b1095e.png

 

The cast to Integer is indeed wrong - see the assembly code with Bounds checking enabled:

 

With cast to WPARAM:

 

 

Thanks. That makes sense. So now I need to update all of his code 🙂

 

Share this post


Link to post
5 minutes ago, Attila Kovacs said:

@Stefan Glienke I can't reproduce the yellow one in Berlin. Strange.

What exactly is strange about it? They changed WPARAM from INT_PTR to UINT_PTR in XE2.

 

The point is that the hint still does not show the actual alias name being used in the declaration of the routine but the actual type it aliases.

And that is wrong because that causes these kinds of defects when the alias changes because people of course did a cast to the type being shown in code insight.

Edited by Stefan Glienke

Share this post


Link to post
Guest

 

33 minutes ago, david_navigator said:

So now I need to update all of his code 🙂

Before updating anything try to reproduce the error first.

 

43 minutes ago, david_navigator said:

1. there are 44 instances where Sender is cast as an Integer and I don't know if they'll be any "gotchas" ?
2. I don't even know if this is the reason for the ERangeCheck as I can't reproduce.

It is way easier than you think to reproduce, all what you need is to make sure the address are higher than MaxInt, so use FastMM4 from here https://github.com/pleriche/FastMM4

and notice this option AlwaysAllocateTopDown here https://github.com/pleriche/FastMM4/blob/ca64b52ac6d918f4dbd06c20c28e8f961a7e450f/FastMM4Options.inc#L178

leave it on, and you will catch them all red handed.

Share this post


Link to post

This is exactly the case when devs do things wrong, not following OS vendor's recommended way, and it kinda works for years but then BADABOOM happens.

All external functions must use their own typedefs. If WinAPI header says it wants DWORD and WPARAM, don't try using Cardinal/Integer

Share this post


Link to post

This Discussion made me run a grep for this construct across code that we use and I found that some of the ICS demos are using an integer cast in PostMessage() instead of WPARAM. Maybe @Remy Lebeau wants to take a look? :)

  • Like 1

Share this post


Link to post

I've found some cardinal() casts in some legacy code for pointers 😉

@luebbe are those casts in ICS Demo also for pointers or for integer numbers?

Edited by Attila Kovacs

Share this post


Link to post

I didn't look at the code in the IDE, just what grepwin spat out, but I'd say:

            smtpQuit : PostMessage(Form1.Handle, WM_REMOVEOBJ, Integer(Sender), 0);

probably casts a pointer to integer. And there are more of these.

  • Like 1

Share this post


Link to post
3 hours ago, luebbe said:

This Discussion made me run a grep for this construct across code that we use and I found that some of the ICS demos are using an integer cast in PostMessage() instead of WPARAM. Maybe @Remy Lebeau wants to take a look? 🙂

Remy maintains Indy, ICS is maintained by Francois and Angus.

Anyway, all sources should be examined for such casts

Share this post


Link to post
21 hours ago, Kas Ob. said:

 

Before updating anything try to reproduce the error first.

 

It is way easier than you think to reproduce, all what you need is to make sure the address are higher than MaxInt, so use FastMM4 from here https://github.com/pleriche/FastMM4

and notice this option AlwaysAllocateTopDown here https://github.com/pleriche/FastMM4/blob/ca64b52ac6d918f4dbd06c20c28e8f961a7e450f/FastMM4Options.inc#L178

leave it on, and you will catch them all red handed.

Thanks. That did indeed reproduce the error and also proved that the fix worked. Many thanks 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×