Author: cgutman Date: Mon Aug 2 21:31:50 2010 New Revision: 48424
URL: http://svn.reactos.org/svn/reactos?rev=48424&view=rev Log: [WS2_32]: Fix buffer overrun in getservbyname. Patch by Alexander Yastrebov - menone7 at gmail dot com
Modified: trunk/reactos/dll/win32/ws2_32/misc/ns.c
Modified: trunk/reactos/dll/win32/ws2_32/misc/ns.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ws2_32/misc/ns.c?... ============================================================================== --- trunk/reactos/dll/win32/ws2_32/misc/ns.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ws2_32/misc/ns.c [iso-8859-1] Mon Aug 2 21:31:50 2010 @@ -1172,11 +1172,11 @@ PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */ PCHAR ServicesFileLocation = "\drivers\etc\services"; PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0, - ProtocolStr = 0, Comment = 0; + ProtocolStr = 0, Comment = 0, EndValid; PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 }; UINT i,SizeNeeded = 0, SystemDirSize = sizeof(ServiceDBData) - 1; - DWORD ReadSize = 0, ValidData = 0; + DWORD ReadSize = 0; PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
if( !p ) @@ -1215,43 +1215,56 @@ WSASetLastError( WSANO_RECOVERY ); return NULL; } - + /* Scan the services file ... - * - * We will read up to BUFSIZ bytes per pass, until the buffer does not - * contain a full line, then we will try to read more. - * - * We fall from the loop if the buffer does not have a line terminator. - */ - + * + * We will be share the buffer on the lines. If the line does not fit in + * the buffer, then moving it to the beginning of the buffer and read + * the remnants of line from file. + */ + /* Initial Read */ - while(!Found && - ReadFile(ServicesFile, - ServiceDBData + ValidData, - sizeof( ServiceDBData ) - ValidData, - &ReadSize, - NULL)) - { - ValidData += ReadSize; - ReadSize = 0; - NextLine = ThisLine = ServiceDBData; - - /* Find the beginning of the next line */ - while(NextLine < ServiceDBData + ValidData && - *NextLine != '\r' && *NextLine != '\n' ) + ReadFile(ServicesFile, + ServiceDBData, + sizeof( ServiceDBData ) - 1, + &ReadSize, NULL ); + ThisLine = NextLine = ServiceDBData; + EndValid = ServiceDBData + ReadSize; + ServiceDBData[sizeof(ServiceDBData) - 1] = '\0'; + + while(ReadSize) + { + for(; *NextLine != '\r' && *NextLine != '\n'; NextLine++) { - NextLine++; + if(NextLine == EndValid) + { + int LineLen = NextLine - ThisLine; + + if(ThisLine == ServiceDBData) + { + WS_DbgPrint(MIN_TRACE,("Line too long")); + WSASetLastError( WSANO_RECOVERY ); + return NULL; + } + + memmove(ServiceDBData, ThisLine, LineLen); + + ReadFile(ServicesFile, ServiceDBData + LineLen, + sizeof( ServiceDBData )-1 - LineLen, + &ReadSize, NULL ); + + EndValid = ServiceDBData + LineLen + ReadSize; + NextLine = ServiceDBData + LineLen; + ThisLine = ServiceDBData; + + if(!ReadSize) break; + } } - - /* Zero and skip, so we can treat what we have as a string */ - if( NextLine > ServiceDBData + ValidData ) - break; - - *NextLine = 0; NextLine++; - + + *NextLine = '\0'; Comment = strchr( ThisLine, '#' ); - if( Comment ) *Comment = 0; /* Terminate at comment start */ - + if( Comment ) *Comment = '\0'; /* Terminate at comment start */ + if(DecodeServEntFromString(ThisLine, &ServiceName, &PortNumberStr, @@ -1268,22 +1281,8 @@ (NextLine - ThisLine); break; } - - /* Get rid of everything we read so far */ - while( NextLine <= ServiceDBData + ValidData && - isspace( *NextLine ) ) - { - NextLine++; - } - - WS_DbgPrint(MAX_TRACE,("About to move %d chars\n", - ServiceDBData + ValidData - NextLine)); - - memmove(ServiceDBData, - NextLine, - ServiceDBData + ValidData - NextLine ); - ValidData -= NextLine - ServiceDBData; - WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData)); + NextLine++; + ThisLine = NextLine; }
/* This we'll do no matter what */