Article about that unit was published in The Delphi Magazine, April 1999. Parts of this article are reprinted below.
Free for personal and commercial use.
(Original article was published in The Delphi Magazine. Selected parts reprinted with permission.)
TSafeWinSocketStream is TWinSocketStream descendant that fixes one hard-to-find, hard-to-reproduce, but very dangerous problem.
TWinSocketStream is a specialised streaming class, derived from TStream, intended for blocking mode socket communication.
To demonstrate a problem with TWinSocketStream, let's take a look at Read function. It takes two parameters - Buffer and Count. At most Count bytes will be read into Buffer and then Read will return. Read will return after some time even if not enough data were read. Function result is either number of bytes read or 0 in the latter (timeout) case.
The implementation of TWinSocketStream.Read is very neat and effective. First, Overlapped memory structure is prepared. Than ReadFile is called. We already know Buffer and Count parameters, Socket is, well, socket handle, into Result the number of bytes read will be returned and Overlapped specifies that read operation is asynchronous (note that asynchronous operations with sockets are supported even in Windows 95). Program will continue execution and event FEvent (specified in Overlapped.hEvent) will be signalled after all data is read. Exception is raised if ReadFile fails.
Read then waits at least FTimeOut milliseconds (that is timeout value specified in a call to constructor) for FEvent to become signalled. If timeout occurs, 0 is returned (failure), otherwise GetOverlappedResult is called to retrieve the result of ReadFile operation and that result is returned. FEvent is then reset.
So where is the problem? It usually occurs when communication is extremely slow (for example on slow modem lines with lots of line noise). In that case, FEvent.WaitFor may timeout. TWinSocketStream.Read then returns 0 but that does not cancel out pending asynchronous ReadFile request. Some time later all data may arrive. When that happens, ReadFile tries to put received data into Buffer. But Buffer may not be there anymore! Using TWinSocketStream.Read can cause memory overwrite, data corruption, program malfunction and all other nasty things including Access Violations!
TWinSocketStream.Write is implemented in a similar manner and can cause same problems as TWinSocketStream.Read. Even more, Write can send random data to the socket and as such presents a security threat!
|Last update: 2010-12-25|