diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 522da11079..826485ce6a 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,24 @@ 2008-12-31 13:59 UTC+0100 Foo Bar */ +2008-07-24 18:02 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/source/rtl/hbinet.c + ! fixed possible data file corruption due to wrong use of 0 handle. + 0 handle is perfectly valid. By default it points to stdin but + it can be closed and then reused for any other thing, f.e. data + file. In such case any data written to socket was written to + such file and this situation was very easy to replicate with + old hbinet code. + ! fixed resource leak due to unclosed handles in few cases + ! fixed possible double close of the some handle what could cause + that other object handles reusing the same handle number between + first and second close (f.e. data files) was wrongly closed + ! fixed s_inetRecvPattern()/HB_INETRECVLINE() - the end pattern + was wrongly checked and the code didn't detect end pattern in + streams like: "...\r\r\n" when end pattern was "\r\n" + NOTE: this code needs some general cleanup. IMHO it should be + joined with adding hbinet C API. + 2008-07-24 03:42 UTC+0200 Viktor Szakats (harbour.01 syenar hu) * contrib/hbcurl/hbcurl.c ! Disabled string hashing for curl_formadd() with diff --git a/harbour/source/rtl/hbinet.c b/harbour/source/rtl/hbinet.c index df73854f88..7351fb5cf9 100644 --- a/harbour/source/rtl/hbinet.c +++ b/harbour/source/rtl/hbinet.c @@ -150,7 +150,7 @@ s = ( HB_SOCKET_STRUCT *) hb_gcAlloc( sizeof( HB_SOCKET_STRUCT ), hb_inetSocketFinalize );\ p = hb_itemPutPtrGC( p, s );\ HB_SOCKET_ZERO_ERROR( s );\ - s->com = 0;\ + s->com = ( HB_SOCKET_T ) -1;\ s->count = 0;\ s->timeout = -1;\ s->timelimit = -1;\ @@ -224,12 +224,6 @@ static void hb_inetLinuxSigusrHandle( int sig ) } #endif -/* some compilers has missing this define */ -#ifndef SOCKET_ERROR -#define SOCKET_ERROR (-1) -#endif - - /* JC1: we need it volatile to be minimally thread safe. */ static volatile int s_iSessions = 0; @@ -325,6 +319,8 @@ static struct hostent * hb_getHosts( char * name, HB_SOCKET_STRUCT *Socket ) { struct hostent *Host = NULL; + /* TOFIX: make it MT safe */ + /* let's see if name is an IP address; not necessary on linux */ #if defined(HB_OS_WIN_32) || defined(HB_OS_OS2) ULONG ulAddr; @@ -481,7 +477,7 @@ static HB_GARBAGE_FUNC( hb_inetSocketFinalize ) { HB_SOCKET_STRUCT *Socket = ( HB_SOCKET_STRUCT *) Cargo; - if( Socket->com > 0 ) + if( Socket->com != ( HB_SOCKET_T ) -1 ) { #if defined( HB_OS_WIN_32 ) shutdown( Socket->com, SD_BOTH ); @@ -492,6 +488,7 @@ static HB_GARBAGE_FUNC( hb_inetSocketFinalize ) #endif HB_INET_CLOSE( Socket->com ); + Socket->com = ( HB_SOCKET_T ) -1; } if( Socket->caPeriodic != NULL ) @@ -555,7 +552,7 @@ HB_FUNC( HB_INETCLOSE ) if( Socket == NULL ) hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); - else if( Socket->com ) + else if( Socket->com != ( HB_SOCKET_T ) -1 ) { #if defined( HB_OS_WIN_32 ) shutdown( Socket->com, SD_BOTH ); @@ -566,8 +563,8 @@ HB_FUNC( HB_INETCLOSE ) #endif hb_retni( HB_INET_CLOSE( Socket->com ) ); + Socket->com = ( HB_SOCKET_T ) -1; - Socket->com = 0; #ifdef HB_OS_LINUX kill( 0, HB_INET_LINUX_INTERRUPT ); #endif @@ -586,7 +583,7 @@ HB_FUNC( HB_INETFD ) { hb_retnint( Socket->com ); if( ISLOG( 2 ) && hb_parl( 2 ) ) - Socket->com = 0; + Socket->com = ( HB_SOCKET_T ) -1; } } @@ -602,7 +599,7 @@ HB_FUNC( HB_INETSTATUS ) hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); else /* TODO: hb_retni( Socket->status ); */ - hb_retni( Socket->com == 0 ? -1 : 1 ); + hb_retni( Socket->com == ( HB_SOCKET_T ) -1 ? -1 : 1 ); } /* Prepared, but still not used; being in wait for comments @@ -970,10 +967,8 @@ static void s_inetRecvPattern( char *szPattern ) char cChar; char *Buffer; int iAllocated, iBufferSize, iMax; - int iLen = 0; + int iLen = 0, iPatLen; int iPos = 0, iTimeElapsed; - ULONG ulPatPos; - if( Socket == NULL ) { @@ -1004,8 +999,8 @@ static void s_inetRecvPattern( char *szPattern ) Buffer = (char *) hb_xgrab( iBufferSize ); iAllocated = iBufferSize; iTimeElapsed = 0; + iPatLen = ( int ) strlen( szPattern ); - ulPatPos = 0; do { if( iPos == iAllocated - 1 ) @@ -1025,7 +1020,7 @@ static void s_inetRecvPattern( char *szPattern ) hb_execFromArray( Socket->caPeriodic ); /* do we continue? */ if( hb_parl( -1 ) && - ( Socket->timelimit == -1 || iTimeElapsed < Socket->timelimit ) ) + ( Socket->timelimit == -1 || iTimeElapsed < Socket->timelimit ) ) { continue; } @@ -1037,21 +1032,13 @@ static void s_inetRecvPattern( char *szPattern ) if( iLen > 0 ) { - /* verify endsequence recognition automata status */ - if( cChar == szPattern[ ulPatPos ] ) - { - ulPatPos ++; - if( ! szPattern[ ulPatPos ] ) - { - break; - } - } - else - { - ulPatPos = 0; - } - Buffer[ iPos++ ] = cChar; + /* verify endsequence recognition automata status */ + if( iPos >= iPatLen && + memcmp( Buffer + iPos - iPatLen, szPattern, iPatLen ) == 0 ) + { + break; + } } else { @@ -1086,7 +1073,7 @@ static void s_inetRecvPattern( char *szPattern ) { if( iMax == 0 || iPos < iMax ) { - iPos--; + iPos -= iPatLen; Socket->count = iPos; if( pResult ) @@ -1320,11 +1307,11 @@ HB_FUNC( HB_INETRECVENDBLOCK ) HB_FUNC( HB_INETDATAREADY ) { HB_SOCKET_STRUCT *Socket = HB_PARSOCKET( 1 ); - int iLen; + int iVal; fd_set rfds; struct timeval tv = {0,0}; - if( Socket == NULL || ( hb_pcount() == 2 && ! ISNUM( 2 ) ) ) + if( Socket == NULL || ( hb_pcount() > 1 && ! ISNUM( 2 ) ) ) { hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); return; @@ -1333,25 +1320,25 @@ HB_FUNC( HB_INETDATAREADY ) HB_SOCKET_ZERO_ERROR( Socket ); /* Watch our socket. */ - if( hb_pcount() == 2 ) + if( hb_pcount() > 1 ) { - iLen = hb_parni( 2 ); - tv.tv_sec = iLen / 1000; - tv.tv_usec = (iLen % 1000) * 1000; + iVal = hb_parni( 2 ); + tv.tv_sec = iVal / 1000; + tv.tv_usec = (iVal % 1000) * 1000; } FD_ZERO(&rfds); FD_SET(Socket->com, &rfds); - iLen = select(Socket->com + 1, &rfds, NULL, NULL, &tv); + iVal = select( Socket->com + 1, &rfds, NULL, NULL, &tv ); /* Don't rely on the value of tv now! */ - if( iLen < 0 ) + if( iVal < 0 ) { HB_SOCKET_SET_ERROR( Socket ); } - hb_retni( iLen ); + hb_retni( iVal ); } @@ -1548,18 +1535,18 @@ HB_FUNC( HB_INETSERVER ) if( Socket->com == ( HB_SOCKET_T ) -1 ) { HB_SOCKET_SET_ERROR( Socket ); - Socket->com = 0; if( pSocket ) hb_itemReturnRelease( pSocket ); else hb_itemReturn( hb_param( 2, HB_IT_ANY ) ); + return; } /* we'll be using only nonblocking sockets */ /* hb_socketSetNonBlocking( Socket ); */ /* Reusable socket; under unix, do not wait it is unused */ - setsockopt( Socket->com, SOL_SOCKET, SO_REUSEADDR, (const char *) &iOpt, sizeof( iOpt )); + setsockopt( Socket->com, SOL_SOCKET, SO_REUSEADDR, (const char *) &iOpt, sizeof( iOpt ) ); iPort = htons( hb_parni( 1 ) ); @@ -1575,11 +1562,13 @@ HB_FUNC( HB_INETSERVER ) { HB_SOCKET_SET_ERROR( Socket ); HB_INET_CLOSE( Socket->com ); + Socket->com = ( HB_SOCKET_T ) -1; } else if( listen( Socket->com, iListen ) ) { HB_SOCKET_SET_ERROR( Socket ); HB_INET_CLOSE( Socket->com ); + Socket->com = ( HB_SOCKET_T ) -1; } if( pSocket ) @@ -1795,7 +1784,7 @@ HB_FUNC( HB_INETDGRAMBIND ) char * szAddress; /* Parameter error checking */ - if( iPort == 0 || ( hb_pcount() == 4 && ! ISCHAR(4) ) ) + if( iPort == 0 || ( hb_pcount() > 3 && ! ISCHAR( 4 ) ) ) { hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); return; @@ -1810,10 +1799,9 @@ HB_FUNC( HB_INETDGRAMBIND ) Socket->com = socket( PF_INET, SOCK_DGRAM, 0 ); #endif - if( Socket->com == (HB_SOCKET_T)-1 ) + if( Socket->com == ( HB_SOCKET_T ) -1 ) { HB_SOCKET_SET_ERROR( Socket ); - Socket->com = 0; hb_itemReturnRelease( pSocket ); return; } @@ -1841,9 +1829,9 @@ HB_FUNC( HB_INETDGRAMBIND ) { HB_SOCKET_SET_ERROR( Socket ); HB_INET_CLOSE( Socket->com ); + Socket->com = ( HB_SOCKET_T ) -1; } - - if( hb_pcount() == 4 ) + else if( hb_pcount() > 3 ) { #ifndef IP_ADD_MEMBERSHIP #define IP_ADD_MEMBERSHIP 5 /* which header should this be in? */ @@ -1871,12 +1859,9 @@ HB_FUNC( HB_INETDGRAMBIND ) # define IPPROTO_IP 0 #endif - if( setsockopt( Socket->com, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *) &mreq, sizeof( mreq )) < 0) + if( setsockopt( Socket->com, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *) &mreq, sizeof( mreq ) ) < 0 ) { HB_SOCKET_SET_ERROR( Socket ); - Socket->com = 0; - hb_itemReturnRelease( pSocket ); - return; } } @@ -1898,10 +1883,9 @@ HB_FUNC( HB_INETDGRAM ) Socket->com = socket( PF_INET, SOCK_DGRAM, 0 ); #endif - if( Socket->com == (HB_SOCKET_T)-1 ) + if( Socket->com == ( HB_SOCKET_T ) -1 ) { HB_SOCKET_SET_ERROR( Socket ); - Socket->com = 0; hb_itemReturnRelease( pSocket ); return; } @@ -1939,13 +1923,13 @@ HB_FUNC( HB_INETDGRAMSEND ) Socket->remote.sin_addr.s_addr = inet_addr( szAddress ); szBuffer = hb_itemGetCPtr( pBuffer ); + iLen = ( int ) hb_itemGetCLen( pBuffer ); if( ISNUM( 5 ) ) { - iLen = hb_parni( 5 ); - } - else - { - iLen = ( int ) hb_itemGetCLen( pBuffer ); + int iMaxLen = hb_parni( 5 ); + + if( iMaxLen < iLen ) + iLen = iMaxLen; } HB_SOCKET_ZERO_ERROR( Socket );