Article View: borland.public.cppbuilder.internet.socket
Article #341Error handling in Indy 10
From: Dennis Cote
Date: Wed, 16 Apr 2008 17:10
Date: Wed, 16 Apr 2008 17:10
123 lines
6367 bytes
6367 bytes
Hi All,
I have an application that has recently been converted to use Indy 10.
This application runs correctly on Win XP. I am now testing the
application under Vista. It does not work under Vista and I believe the
issue has to do with Administrator rights, but that is not the immediate
concern.
My concern is with the nature of the error checking being done in the
Indy code. A failure to open a socket is generating a RangeError exception.
Just before it fails my application ends up in NewSocketHandle while
trying to open an TIdICMPClient. This function is copied below.
function TIdStackBSDBase.NewSocketHandle(const ASocketType:TIdSocketType;
const AProtocol: TIdSocketProtocol;
const AIPVersion: TIdIPVersion = ID_DEFAULT_IP_VERSION;
const AOverlapped: Boolean = False): TIdStackSocketHandle;
begin
Result := CheckForSocketError(WSSocket(IdIPFamily[AIPVersion],
ASocketType, AProtocol, AOverlapped));
end;
I have stepped through the assembly code of this routine to track the
problem. This routine is essentially the one line.
IdStackBSDBase.pas.389: Result :=
CheckForSocketError(WSSocket(IdIPFamily[AIPVersion], ASocketType,
00837321 8B45FC mov eax,[ebp-$04]
00837324 50 push eax
00837325 0FB64508 movzx eax,[ebp+$08]
00837329 50 push eax
0083732A 8BCE mov ecx,esi
0083732C 85C9 test ecx,ecx
0083732E 7905 jns $00837335
00837330 E8F35FE9FF call System::__linkproc__ BoundErr()
00837335 0FB6450C movzx eax,[ebp+$0c]
00837339 8B1485246E9900 mov edx,[eax*4+$996e24]
00837340 8BC3 mov eax,ebx
00837342 8B30 mov esi,[eax]
00837344 FF96C4000000 call dword ptr [esi+$000000c4]
0083734A 8BD0 mov edx,eax
0083734C 85D2 test edx,edx
0083734E 7905 jns $00837355
00837350 E8D35FE9FF call System::__linkproc__ BoundErr()
00837355 8BC3 mov eax,ebx
00837357 E81C0D0000 call Idstack::TIdStack::CheckForSocketError(int)
0083735C 85C0 test eax,eax
0083735E 7905 jns $00837365
00837360 E8C35FE9FF call System::__linkproc__ BoundErr()
This code pushes the arguments to WSSocket() and then makes the virtual
function call at 00837344. This ends up at WSSocket in the Windows stack.
function TIdStackWindows.WSSocket(AFamily, AStruct, AProtocol: Integer;
const AOverlapped: Boolean = False): TIdStackSocketHandle;
begin
if AOverlapped then begin
Result := WSASocket(AFamily, AStruct,
AProtocol,nil,0,WSA_FLAG_OVERLAPPED);
end else begin
Result := IdWinsock2.Socket(AFamily, AStruct, AProtocol);
end;
end;
The argument AOverlapped is false, so it makes the call to
IdWinsock2.Socket().
IdStackWindows.pas.600: Result := IdWinsock2.Socket(AFamily, AStruct,
AProtocol);
00835494 50 push eax
00835495 51 push ecx
00835496 52 push edx
00835497 A12CF19900 mov eax,[$0099f12c]
0083549C 8B00 mov eax,[eax]
0083549E FFD0 call eax
IdStackWindows.pas.602: end;
008354A0 5D pop ebp
008354A1 C20800 ret $0008
This function is failing (probably because of administrator rights) and
returning a value of 0xFFFFFFFF (or -1) in the ax register to
NewSocketHandle.
NewSocketHandle now does a range check on the result at 0083734A through
0083734E. I'm not sure if that is correct but it seems like it might be
(see below). In any case, the range check is failing because the result
is negative (i.e the sign flag is set by the test instruction). This
causes the code to call System::BoundErr() which generates the
RangeError exception. The result of WSSocket() never makes it to the
function CheckForSocketError() which is obviously intended to check this
result because of this range check.
Now I'm no Delphi expert (i.e. it took me quite a while to confirm that
LongWord and Longword are the same type because Delphi is case
insensitive) but I tracked the types to see why this range check is
being done. It seems reasonable to me, but I may be mistaken.
WSSocket() is defined to return a TIdStackSocketHandle result. This type
is defined as a TSocket at line 115 of IdStatckConsts.pas. This type is
in turn defined as PtrUint at line 219 of IdWinsock2.pas. Finally this
type is defined as LongWord at line 674 of IdGlobal.pas.
The type of the argumnet to function CheckForSocketError() is defined as
Integer at line 571 of IdStack.pas.
So NewSocketHandle() is trying to pass the LongWord result from
WSSocket() to the Integer argument of CheckForSocketError(). Since
LongWord is an unsiged type, its range is larger than the Integer
arguments type. Hence the range check is required.
It seems to me that this range check will always fail if WSSocket
returns 0xFFFFFFFF (or -1) for a failure, and hence we will never get to
see the real reason for the failure that CheckForSocketError() is
supposed to produce. I think some type casting must be needed to tell
the compiler not to check the range of the result before passing it to
CheckForSocketError(), but I'm not sure how that is done in Delphi. I
also suspect this same error may exist in other places in the code.
Can anyone say if this analysis is correct, and if so how the result
should be cast from unsigned to signed without the range check?
Dennis Cote
Technical Details
Message-ID:
<480632fb$1@newsgroups.borland.com>Path:
arc1-ca.pugleaf.net!g2news1.google.com!news4.google.com!feeder.news-service.com!newsfeed.freenet.de!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mailShow Full Headers
Complete Article Headers
X-Google-Thread: 11508e,9330c485b2d28336,start X-Google-Attributes: gid11508e,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Date: Wed, 16 Apr 2008 11:10:20 -0600 From: Dennis Cote <denniscote@gmail.com> User-Agent: Thunderbird 2.0.0.12 (Windows/20080213) MIME-Version: 1.0 Newsgroups: borland.public.cppbuilder.internet.socket Subject: Error handling in Indy 10 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit NNTP-Posting-Host: 142.179.167.5 Message-ID: <480632fb$1@newsgroups.borland.com> X-Trace: newsgroups.borland.com 1208365819 142.179.167.5 (16 Apr 2008 10:10:19 -0700) Lines: 130 Path: arc1-ca.pugleaf.net!g2news1.google.com!news4.google.com!feeder.news-service.com!newsfeed.freenet.de!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail