diff --git a/ChangeLog.txt b/ChangeLog.txt index 1384b197a4..7ae4b88bea 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,53 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2016-09-28 19:55 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * contrib/hbssl/hbssl.h + * contrib/hbssl/ssl_sock.c + * contrib/hbssl/ssl_inet.c + + added new 'PHB_ITEM pSSL' parameter to hb_sockexNewSSL() and + hb_ssl_socketNew() C functions - it allows to bind harbour item + with SSL pointer which should not be released before connection + is closed. In new OpenSSL version such tricks can be replaced + by SSL_up_ref() + This modification also fixes possible GPF trap when SSL filter + socket was create dynamically from C code without SSL pointer + item on HVM stack in 2-nd parameter and removes old hack which + saved internally 2-nd HVM stack parameter. + + allow to pass SSL_CTX instead of SSL in "ssl", "ctx" or "key" items + of hash array used to initialize SSL socket filter. Using SSL_CTX + allows to use the same hash array to set SSL socket filter for + different connections + + allow to use codeblocks or function pointers as "ssl", "ctx" or + "key" items of hash array used to initialize SSL socket filter + + * contrib/hbssl/hbssl.h + * contrib/hbssl/sslctx.c + + added new C function: + SSL_CTX * hb_SSL_CTX_itemGet( PHB_ITEM pItem ) + + * contrib/hbssl/ssl_sock.c + * src/rtl/hbcom.c + * src/rtl/hbsocket.c + ! fixed timeout checking in select()/poll() + + * src/rtl/hbsockhb.c + ! fixed possible GPF trap when socket filter refuse to create new + socket wrapper + + * include/hbinit.h + * in GCC C++ builds for startup code use GCC constructor function + attribute instead of static variable initialization to avoid + warnings in new GCC versions + + * src/rtl/hbntos.c + ! fixed missing '-' in result of negative integer numbers - thanks + to Luigi Ferraris + + * src/common/hbstr.c + + added code to round integer part when the size of number is greater + then double precision (~16 digits). + 2016-09-23 11:00 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * contrib/gtqtc/gtqtc1.cpp * removed unnecessary casting after recent modification diff --git a/contrib/hbssl/hbssl.h b/contrib/hbssl/hbssl.h index 970865008c..c70bebc348 100644 --- a/contrib/hbssl/hbssl.h +++ b/contrib/hbssl/hbssl.h @@ -170,9 +170,9 @@ struct _HB_SSLSTREAM; typedef struct _HB_SSLSTREAM * PHB_SSLSTREAM; extern PHB_SOCKEX hb_sockexNewSSL( HB_SOCKET sd, SSL * ssl, HB_BOOL fServer, - HB_MAXINT timeout ); + HB_MAXINT timeout, PHB_ITEM pSSL ); extern PHB_SSLSTREAM hb_ssl_socketNew( HB_SOCKET sd, SSL * ssl, HB_BOOL fServer, - HB_MAXINT timeout, int * piResult ); + HB_MAXINT timeout, PHB_ITEM pSSL, int * piResult ); extern void hb_ssl_socketClose( PHB_SSLSTREAM pStream ); extern const char * hb_ssl_socketErrorStr( int iError ); extern long hb_ssl_socketRead( PHB_SSLSTREAM pStream, HB_SOCKET sd, @@ -188,6 +188,7 @@ extern BIO * hb_BIO_par( int iParam ); extern void * hb_SSL_CTX_is( int iParam ); extern SSL_CTX * hb_SSL_CTX_par( int iParam ); +extern SSL_CTX * hb_SSL_CTX_itemGet( PHB_ITEM pItem ); extern void * hb_SSL_is( int iParam ); extern SSL * hb_SSL_par( int iParam ); diff --git a/contrib/hbssl/ssl_inet.c b/contrib/hbssl/ssl_inet.c index 1ab702b905..fa6c34b101 100644 --- a/contrib/hbssl/ssl_inet.c +++ b/contrib/hbssl/ssl_inet.c @@ -113,8 +113,9 @@ static void hb_inetStartSSL( HB_BOOL fServer ) { HB_MAXINT timeout = HB_ISNUM( 3 ) ? hb_parnint( 3 ) : hb_znetInetTimeout( pItem, HB_FALSE ); - PHB_SSLSTREAM pStream = hb_ssl_socketNew( sd, ssl, fServer, - timeout, &iResult ); + PHB_SSLSTREAM pStream = hb_ssl_socketNew( sd, ssl, fServer, timeout, + hb_param( 2, HB_IT_POINTER ), + &iResult ); if( pStream ) { if( ! hb_znetInetInitialize( pItem, ( PHB_ZNETSTREAM ) pStream, diff --git a/contrib/hbssl/ssl_sock.c b/contrib/hbssl/ssl_sock.c index 68887e834f..1e5cd04abf 100644 --- a/contrib/hbssl/ssl_sock.c +++ b/contrib/hbssl/ssl_sock.c @@ -260,12 +260,16 @@ long hb_ssl_socketWrite( PHB_SSLSTREAM pStream, HB_SOCKET sd, void hb_ssl_socketClose( PHB_SSLSTREAM pStream ) { SSL_shutdown( pStream->ssl ); - hb_itemRelease( pStream->pSSL ); + if( pStream->pSSL ) + hb_itemRelease( pStream->pSSL ); + else + SSL_free( pStream->ssl ); hb_xfree( pStream ); } PHB_SSLSTREAM hb_ssl_socketNew( HB_SOCKET sd, SSL * ssl, HB_BOOL fServer, - HB_MAXINT timeout, int * piResult ) + HB_MAXINT timeout, PHB_ITEM pSSL, + int * piResult ) { int iResult; @@ -276,7 +280,7 @@ PHB_SSLSTREAM hb_ssl_socketNew( HB_SOCKET sd, SSL * ssl, HB_BOOL fServer, timer = timeout <= 0 ? 0 : hb_dateMilliSeconds(); pStream->ssl = ssl; - pStream->pSSL = hb_itemNew( hb_param( 2, HB_IT_POINTER ) ); + pStream->pSSL = pSSL ? hb_itemNew( pSSL ) : NULL; pStream->blocking = timeout < 0; if( hb_socketSetBlockingIO( sd, pStream->blocking ) < 0 ) pStream->blocking = !pStream->blocking; @@ -307,6 +311,8 @@ PHB_SSLSTREAM hb_ssl_socketNew( HB_SOCKET sd, SSL * ssl, HB_BOOL fServer, if( timecurr > timer ) { timeout -= timecurr - timer; + if( timeout < 0 ) + timeout = 0; timer = timecurr; } @@ -345,26 +351,62 @@ PHB_SSLSTREAM hb_ssl_socketNew( HB_SOCKET sd, SSL * ssl, HB_BOOL fServer, /* socket filter */ +static SSL * s_SSL_itemGet( PHB_ITEM pItem, PHB_ITEM * pSSL, HB_BOOL * pfFree ) +{ + SSL * ssl = NULL; + + if( pItem ) + { + PHB_ITEM pRelease = NULL; + + if( HB_IS_EVALITEM( pItem ) ) + pItem = pRelease = hb_itemDo( pItem, 0 ); + + ssl = hb_SSL_itemGet( pItem ); + if( ssl == NULL ) + { + SSL_CTX * ssl_ctx = hb_SSL_CTX_itemGet( pItem ); + if( ssl_ctx ) + { + ssl = SSL_new( ssl_ctx ); + if( pRelease ) + hb_itemRelease( pRelease ); + pItem = pRelease = NULL; + } + } + if( ssl ) + { + * pSSL = pItem; + * pfFree = pRelease != NULL; + } + else if( pRelease ) + hb_itemRelease( pRelease ); + } + return ssl; +} + #define HB_SSLSOCK_GET( p ) ( ( PHB_SSLSTREAM ) p->cargo ) #define HB_SSLSOCK_READAHEAD 0x40 static PHB_SOCKEX s_sockexNew( HB_SOCKET sd, PHB_ITEM pParams ) { PHB_SOCKEX pSock; - HB_BOOL fServer = HB_FALSE; + HB_BOOL fServer = HB_FALSE, fFree = HB_FALSE; HB_MAXINT timeout = -1; + PHB_ITEM pSSL = NULL; SSL * ssl = NULL; if( pParams && HB_IS_HASH( pParams ) ) { PHB_ITEM pItem; - if( ssl == NULL && ( pItem = hb_hashGetCItemPtr( pParams, "ssl" ) ) != NULL ) - ssl = hb_SSL_itemGet( pItem ); - if( ssl == NULL && ( pItem = hb_hashGetCItemPtr( pParams, "ctx" ) ) != NULL ) - ssl = hb_SSL_itemGet( pItem ); - if( ssl == NULL && ( pItem = hb_hashGetCItemPtr( pParams, "key" ) ) != NULL ) - ssl = hb_SSL_itemGet( pItem ); + if( ssl == NULL ) + ssl = s_SSL_itemGet( hb_hashGetCItemPtr( pParams, "ssl" ), &pSSL, &fFree ); + if( ssl == NULL ) + ssl = s_SSL_itemGet( hb_hashGetCItemPtr( pParams, "ctx" ), &pSSL, &fFree ); + if( ssl == NULL ) + ssl = s_SSL_itemGet( hb_hashGetCItemPtr( pParams, "key" ), &pSSL, &fFree ); + if( ( pItem = hb_hashGetCItemPtr( pParams, "timeout" ) ) != NULL && HB_IS_NUMERIC( pItem ) ) timeout = hb_itemGetNInt( pItem ); @@ -376,9 +418,11 @@ static PHB_SOCKEX s_sockexNew( HB_SOCKET sd, PHB_ITEM pParams ) fServer = ! hb_itemGetL( pItem ); } - pSock = hb_sockexNewSSL( sd, ssl, fServer, timeout ); + pSock = hb_sockexNewSSL( sd, ssl, fServer, timeout, pSSL ); if( pSock ) hb_socekxParamsInit( pSock, pParams ); + if( fFree ) + hb_itemRelease( pSSL ); return pSock; } @@ -405,11 +449,7 @@ static int s_sockexClose( PHB_SOCKEX pSock, HB_BOOL fClose ) int iResult; if( pSock->cargo ) - { - SSL_shutdown( HB_SSLSOCK_GET( pSock )->ssl ); - hb_itemRelease( HB_SSLSOCK_GET( pSock )->pSSL ); - hb_xfree( pSock->cargo ); - } + hb_ssl_socketClose( HB_SSLSOCK_GET( pSock ) ); iResult = hb_sockexRawClear( pSock, fClose ); hb_xfree( pSock ); @@ -527,13 +567,13 @@ static const HB_SOCKET_FILTER s_sockFilter = }; PHB_SOCKEX hb_sockexNewSSL( HB_SOCKET sd, SSL * ssl, HB_BOOL fServer, - HB_MAXINT timeout ) + HB_MAXINT timeout, PHB_ITEM pSSL ) { PHB_SOCKEX pSock = NULL; if( sd != HB_NO_SOCKET && ssl ) { - PHB_SSLSTREAM pStream = hb_ssl_socketNew( sd, ssl, fServer, timeout, NULL ); + PHB_SSLSTREAM pStream = hb_ssl_socketNew( sd, ssl, fServer, timeout, pSSL, NULL ); if( pStream ) { pSock = ( PHB_SOCKEX ) hb_xgrabz( sizeof( HB_SOCKEX ) ); @@ -558,7 +598,7 @@ static void s_sslSocketNew( HB_BOOL fServer ) SSL * ssl = hb_SSL_par( 2 ); if( ssl ) - pSock = hb_sockexNewSSL( sd, ssl, fServer, hb_parnintdef( 3, - 1 ) ); + pSock = hb_sockexNewSSL( sd, ssl, fServer, hb_parnintdef( 3, - 1 ), hb_param( 2, HB_IT_ANY ) ); else if( HB_ISHASH( 2 ) ) pSock = hb_sockexNew( sd, s_sockFilter.pszName, hb_param( 2, HB_IT_ANY ) ); else diff --git a/contrib/hbssl/sslctx.c b/contrib/hbssl/sslctx.c index d979578ebf..43b48f92a4 100644 --- a/contrib/hbssl/sslctx.c +++ b/contrib/hbssl/sslctx.c @@ -88,6 +88,13 @@ SSL_CTX * hb_SSL_CTX_par( int iParam ) return ph ? ( SSL_CTX * ) *ph : NULL; } +SSL_CTX * hb_SSL_CTX_itemGet( PHB_ITEM pItem ) +{ + void ** ph = ( void ** ) hb_itemGetPtrGC( pItem, &s_gcSSL_CTX_funcs ); + + return ph ? ( SSL_CTX * ) *ph : NULL; +} + const SSL_METHOD * hb_ssl_method_id_to_ptr( int n ) { const SSL_METHOD * p; diff --git a/include/hbinit.h b/include/hbinit.h index 31c9a71ad2..c358ed4a7f 100644 --- a/include/hbinit.h +++ b/include/hbinit.h @@ -55,10 +55,13 @@ extern HB_EXPORT PHB_SYMB hb_vmProcessSymbols( PHB_SYMB pSymbols, HB_USHORT uiSy #define HB_INIT_SYMBOLS_END( func ) HB_INIT_SYMBOLS_EX_END( func, __FILE__, 0L, 0x0000 ) -/* By default in all C++ builds use static vars initialization as startup code */ +/* By default in all C++ builds use static variable initialization as startup + code with the exception for GCC which new versions show warning about + defined but not used static variable initialized with this method. */ #if defined( __cplusplus ) && ! defined( HB_STATIC_STARTUP ) && \ ! defined( HB_PRAGMA_STARTUP ) && ! defined( HB_GNUC_STARTUP ) && \ - ! defined( HB_INITSEG_STARTUP ) && ! defined( HB_DATASEG_STARTUP ) + ! defined( HB_INITSEG_STARTUP ) && ! defined( HB_DATASEG_STARTUP ) && \ + ! defined( __GNUC__ ) #define HB_STATIC_STARTUP #endif diff --git a/src/common/hbstr.c b/src/common/hbstr.c index 106043c316..fc0f6d6aef 100644 --- a/src/common/hbstr.c +++ b/src/common/hbstr.c @@ -843,10 +843,18 @@ char * hb_dblToStr( char * szBuf, HB_SIZE nSize, double dNumber, int iMaxDec ) szResult = szBuf; if( dNumber < 0 ) { - if( --iLen == 0 ) - return NULL; - *szBuf++ = '-'; dFract = modf( -dNumber, &dInt ); + if( --iLen == 0 ) + { + if( dInt < 1 && dFract < 0.5 ) + { + szBuf[ 0 ] = '0'; + szBuf[ 1 ] = '\0'; + return szBuf; + } + return NULL; + } + *szBuf++ = '-'; } else dFract = modf( dNumber, &dInt ); @@ -854,18 +862,14 @@ char * hb_dblToStr( char * szBuf, HB_SIZE nSize, double dNumber, int iMaxDec ) iPos = iLen; do { + if( iPos == 0 ) + return NULL; dDig = modf( dInt / doBase + 0.01, &dInt ) * doBase; szBuf[ --iPos ] = '0' + ( char ) ( dDig + 0.01 ); - if( iPos == 0 ) - { - if( dInt >= 1 ) - return NULL; - break; - } } while( dInt >= 1 ); if( iPos > 0 ) - memmove( szBuf, szBuf + iPos, HB_MIN( iLen - iPos, iPrec ) ); + memmove( szBuf, szBuf + iPos, HB_MIN( iLen - iPos, iPrec + 1 ) ); iPos = iLen - iPos; fFirst = iPos > 1 || szBuf[ 0 ] != '0'; @@ -873,22 +877,36 @@ char * hb_dblToStr( char * szBuf, HB_SIZE nSize, double dNumber, int iMaxDec ) { if( iPos >= iPrec ) { - while( iPrec < iPos ) - szBuf[ iPrec++ ] = '0'; + fFirst = iPos == iPrec ? dFract >= 0.5 : szBuf[ iPrec ] >= '5'; + if( iPrec < iPos ) + memset( szBuf + iPrec , '0', iPos - iPrec ); + if( fFirst ) + { + for( ;; ) + { + if( --iPrec < 0 ) + { + if( iPos == iLen ) + return NULL; + memmove( szBuf + 1, szBuf, iPos ); + *szBuf = '1'; + ++iPos; + break; + } + if( szBuf[ iPrec ] != '9' ) + { + ++szBuf[ iPrec ]; + break; + } + szBuf[ iPrec ] = '0'; + } + } iPrec = 0; } else iPrec -= iPos; } - while( dInt >= 1 ) - { - if( iPos >= iLen ) - return NULL; - dDig = modf( dInt / doBase + 0.01, &dInt ) * doBase; - szBuf[ iPos++ ] = iPrec-- > 0 ? '0' + ( char ) ( dDig + 0.01 ) : '0'; - } - if( iPrec > 0 && iLen - iPos > 1 && iMaxDec != 0 && dFract > 0 ) { int iDec = iPos; diff --git a/src/rtl/hbcom.c b/src/rtl/hbcom.c index 785e9f7637..6bcc3918d2 100644 --- a/src/rtl/hbcom.c +++ b/src/rtl/hbcom.c @@ -576,7 +576,10 @@ static int hb_comCanRead( PHB_COM pCom, HB_MAXINT timeout ) { timeout -= timecurr - timer; if( timeout > 0 ) + { + timer = timecurr; continue; + } } } } @@ -680,7 +683,10 @@ static int hb_comCanWrite( PHB_COM pCom, HB_MAXINT timeout ) { timeout -= timecurr - timer; if( timeout > 0 ) + { + timer = timecurr; continue; + } } } } diff --git a/src/rtl/hbntos.c b/src/rtl/hbntos.c index 9982d8644b..7793be90cc 100644 --- a/src/rtl/hbntos.c +++ b/src/rtl/hbntos.c @@ -97,12 +97,14 @@ HB_FUNC( HB_NTOC ) nNumber /= 10; } while( nNumber != 0 ); + if( fNeg ) + szBuffer[ --iPos ] = '-'; hb_retc( szBuffer + iPos ); } else hb_retc( hb_dblToStr( szBuffer, sizeof( szBuffer ), - hb_itemGetND( pNumber ), hb_parnidef( 2, 20 ) ) ); + hb_itemGetND( pNumber ), hb_parnidef( 2, -1 ) ) ); } else hb_retc_null(); diff --git a/src/rtl/hbsocket.c b/src/rtl/hbsocket.c index e5c3fb5422..a2fc3b64af 100644 --- a/src/rtl/hbsocket.c +++ b/src/rtl/hbsocket.c @@ -1666,7 +1666,10 @@ static int hb_socketSelectRD( HB_SOCKET sd, HB_MAXINT timeout ) { timeout -= timecurr - timer; if( timeout > 0 ) + { + timer = timecurr; continue; + } } } } @@ -1775,7 +1778,10 @@ static int hb_socketSelectWR( HB_SOCKET sd, HB_MAXINT timeout ) { timeout -= timecurr - timer; if( timeout > 0 ) + { + timer = timecurr; continue; + } } } } @@ -1884,7 +1890,10 @@ static int hb_socketSelectWRE( HB_SOCKET sd, HB_MAXINT timeout ) { timeout -= timecurr - timer; if( timeout > 0 ) + { + timer = timecurr; continue; + } } } } @@ -3196,7 +3205,10 @@ int hb_socketSelect( PHB_ITEM pArrayRD, HB_BOOL fSetRD, { timeout -= timecurr - timer; if( timeout > 0 ) + { + timer = timecurr; continue; + } } } } diff --git a/src/rtl/hbsockhb.c b/src/rtl/hbsockhb.c index 21a0e7d14b..ed019f4f5d 100644 --- a/src/rtl/hbsockhb.c +++ b/src/rtl/hbsockhb.c @@ -580,8 +580,11 @@ PHB_SOCKEX hb_sockexNew( HB_SOCKET sd, const char * pszFilter, PHB_ITEM pParams pFilters[ i ]->Next( pSock, pParams ); if( pSockNew == NULL ) { - hb_sockexClose( pSock, HB_FALSE ); - pSock = NULL; + if( pSock ) + { + hb_sockexClose( pSock, HB_FALSE ); + pSock = NULL; + } break; } pSock = pSockNew;