Bug 367736 - make nsEscape more efficient and clean up some signed/unsigned issues to prevent theoretical overflow, r=bsmedberg+dveditz

This commit is contained in:
Michal Novotny 2008-08-19 09:57:12 -04:00
Родитель 6d3e56583d
Коммит 62aa8dca96
1 изменённых файлов: 24 добавлений и 7 удалений

Просмотреть файл

@ -75,25 +75,42 @@ const int netCharType[256] =
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
static char* nsEscapeCount( static char* nsEscapeCount(
const char * str, const char * str,
PRInt32 len,
nsEscapeMask flags, nsEscapeMask flags,
PRInt32* out_len) size_t* out_len)
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
{ {
if (!str) if (!str)
return 0; return 0;
int i, extra = 0; size_t i, len = 0, charsToEscape = 0;
static const char hexChars[] = "0123456789ABCDEF"; static const char hexChars[] = "0123456789ABCDEF";
register const unsigned char* src = (const unsigned char *) str; register const unsigned char* src = (const unsigned char *) str;
for (i = 0; i < len; i++) while (*src)
{ {
len++;
if (!IS_OK(*src++)) if (!IS_OK(*src++))
extra += 2; /* the escape, plus an extra byte for each nibble */ charsToEscape++;
} }
char* result = (char *)nsMemory::Alloc(len + extra + 1); // calculate how much memory should be allocated
// original length + 2 bytes for each escaped character + terminating '\0'
// do the sum in steps to check for overflow
size_t dstSize = len + 1 + charsToEscape;
if (dstSize <= len)
return 0;
dstSize += charsToEscape;
if (dstSize < len)
return 0;
// fail if we need more than 4GB
// size_t is likely to be long unsigned int but nsMemory::Alloc(size_t)
// calls NS_Alloc_P(size_t) which calls PR_Malloc(PRUint32), so there is
// no chance to allocate more than 4GB using nsMemory::Alloc()
if (dstSize > PR_UINT32_MAX)
return 0;
char* result = (char *)nsMemory::Alloc(dstSize);
if (!result) if (!result)
return 0; return 0;
@ -144,7 +161,7 @@ NS_COM char* nsEscape(const char * str, nsEscapeMask flags)
{ {
if(!str) if(!str)
return NULL; return NULL;
return nsEscapeCount(str, (PRInt32)strlen(str), flags, NULL); return nsEscapeCount(str, flags, NULL);
} }
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------