From 77964bedf9cdf2a93a0ae1495a2bce298a96c1fe Mon Sep 17 00:00:00 2001 From: "darin%netscape.com" Date: Thu, 23 May 2002 23:46:01 +0000 Subject: [PATCH] fixes bug 100595 "crash @nsMultiMixedConv::FindToken [was: sandiegozoo.org - this site crashes the browser, every time]" r=dougt sr=rpotts --- .../converters/nsMultiMixedConv.cpp | 204 +++++++++--------- 1 file changed, 97 insertions(+), 107 deletions(-) diff --git a/netwerk/streamconv/converters/nsMultiMixedConv.cpp b/netwerk/streamconv/converters/nsMultiMixedConv.cpp index 02c067000bce..04269983fae1 100644 --- a/netwerk/streamconv/converters/nsMultiMixedConv.cpp +++ b/netwerk/streamconv/converters/nsMultiMixedConv.cpp @@ -42,7 +42,7 @@ #include "nsIServiceManager.h" #include "nsNetUtil.h" #include "nsMimeTypes.h" -#include "nsIByteArrayInputStream.h" +#include "nsIStringStream.h" #include "nsReadableUtils.h" #include "nsIMultiPartChannel.h" #include "nsCRT.h" @@ -420,7 +420,7 @@ nsMultiMixedConv::AsyncConvertData(const PRUnichar *aFromType, const PRUnichar * return NS_OK; } -#define ERR_OUT { nsMemory::Free(buffer); return rv; } +#define ERR_OUT { free(buffer); return rv; } // nsIStreamListener implementation NS_IMETHODIMP @@ -432,35 +432,33 @@ nsMultiMixedConv::OnDataAvailable(nsIRequest *request, nsISupports *context, nsresult rv = NS_OK; char *buffer = nsnull; - PRUint32 bufLen = count, read; + PRUint32 bufLen = 0, read = 0; NS_ASSERTION(request, "multimixed converter needs a request"); nsCOMPtr channel = do_QueryInterface(request, &rv); if (NS_FAILED(rv)) return rv; - - buffer = (char*)nsMemory::Alloc(bufLen); - if (!buffer) return NS_ERROR_OUT_OF_MEMORY; - rv = inStr->Read(buffer, bufLen, &read); - if (NS_FAILED(rv) || read == 0) return rv; - NS_ASSERTION(read == bufLen, "poor data size assumption"); - - if (mBufLen) { - // incorporate any buffered data into the parsing - char *tmp = (char*)nsMemory::Alloc(mBufLen + bufLen); - if (!tmp) { - nsMemory::Free(buffer); + // fill buffer + { + bufLen = count + mBufLen; + buffer = (char *) malloc(bufLen); + if (!buffer) return NS_ERROR_OUT_OF_MEMORY; + + if (mBufLen) { + // incorporate any buffered data into the parsing + memcpy(buffer, mBuffer, mBufLen); + free(mBuffer); + mBuffer = 0; } - memcpy(tmp, mBuffer, mBufLen); - nsMemory::Free(mBuffer); - mBuffer = nsnull; - memcpy(tmp+mBufLen, buffer, bufLen); - nsMemory::Free(buffer); - buffer = tmp; - bufLen += mBufLen; + + rv = inStr->Read(buffer + mBufLen, count, &read); + mBufLen = 0; + + if (NS_FAILED(rv) || read == 0) return rv; + NS_ASSERTION(read == count, "poor data size assumption"); } char *cursor = buffer; @@ -481,18 +479,18 @@ nsMultiMixedConv::OnDataAvailable(nsIRequest *request, nsISupports *context, // skip this check, and try again the next time OnData() // is called. mFirstOnData = PR_TRUE; - } else if (!PL_strnstr(cursor, token, mTokenLen+2)) { - bufLen = read + mTokenLen + 1; - char *tmp = (char*)nsMemory::Alloc(bufLen); - if (!tmp) { - nsMemory::Free(buffer); + } + else if (!PL_strnstr(cursor, token, mTokenLen+2)) { + buffer = (char *) realloc(buffer, bufLen + mTokenLen + 1); + if (!buffer) return NS_ERROR_OUT_OF_MEMORY; - } - memcpy(tmp, token, mTokenLen); - memcpy(tmp+mTokenLen, "\n", 1); - memcpy(tmp+mTokenLen+1, cursor, read); - nsMemory::Free(buffer); - buffer = tmp; + + memmove(buffer+mTokenLen+1, buffer, bufLen); + memcpy(buffer, token, mTokenLen); + buffer[mTokenLen] = '\n'; + + bufLen += (mTokenLen + 1); + // need to reset cursor to the buffer again (bug 100595) cursor = buffer; } @@ -520,12 +518,9 @@ nsMultiMixedConv::OnDataAvailable(nsIRequest *request, nsISupports *context, if (*(token+mTokenLen+1) == '-') { // This was the last delimiter so we can stop processing - bufLen = token - cursor; - rv = SendData(cursor, bufLen); - nsMemory::Free(buffer); + rv = SendData(cursor, token - cursor); + free(buffer); if (NS_FAILED(rv)) return rv; - buffer = nsnull; - bufLen = 0; return SendStop(NS_OK); } @@ -536,6 +531,7 @@ nsMultiMixedConv::OnDataAvailable(nsIRequest *request, nsISupports *context, bufLen -= token - cursor; if (NS_FAILED(rv)) ERR_OUT } + // XXX else NS_ASSERTION(token == cursor, "?"); token += mTokenLen; bufLen -= mTokenLen; tokenLinefeed = PushOverLine(token, bufLen); @@ -550,19 +546,20 @@ nsMultiMixedConv::OnDataAvailable(nsIRequest *request, nsISupports *context, if (done) { rv = SendStart(channel); if (NS_FAILED(rv)) ERR_OUT - } else { + } + else { // we haven't finished processing header info. // we'll break out and try to process later. mProcessingHeaders = PR_TRUE; break; } - } else { + } + else { mNewPart = PR_TRUE; rv = SendStop(NS_OK); if (NS_FAILED(rv)) ERR_OUT - // reset to the token to front. - // this allows us to treat the token - // as a starting token. + // reset the token to front. this allows us to treat + // the token as a starting token. token -= mTokenLen + tokenLinefeed; bufLen += mTokenLen + tokenLinefeed; cursor = token; @@ -575,9 +572,9 @@ nsMultiMixedConv::OnDataAvailable(nsIRequest *request, nsISupports *context, // carry over PRUint32 bufAmt = 0; - if (mProcessingHeaders) { + if (mProcessingHeaders) bufAmt = bufLen; - } else { + else { // if the data ends in a linefeed, and we're in the middle // of a "part" (ie. mPartChannel exists) don't bother // buffering, go ahead and send the data we have. Otherwise @@ -599,8 +596,7 @@ nsMultiMixedConv::OnDataAvailable(nsIRequest *request, nsISupports *context, if (NS_FAILED(rv)) ERR_OUT } - nsMemory::Free(buffer); - + free(buffer); return rv; } @@ -671,7 +667,7 @@ nsMultiMixedConv::OnStopRequest(nsIRequest *request, nsISupports *ctxt, (void) SendData(mBuffer, mBufLen); // don't bother checking the return value here, if the send failed // we're done anyway as we're in the OnStop() callback. - nsMemory::Free(mBuffer); + free(mBuffer); mBuffer = nsnull; mBufLen = 0; } @@ -711,7 +707,7 @@ nsMultiMixedConv::nsMultiMixedConv() { nsMultiMixedConv::~nsMultiMixedConv() { NS_ASSERTION(!mBuffer, "all buffered data should be gone"); if (mBuffer) { - nsMemory::Free(mBuffer); + free(mBuffer); mBuffer = nsnull; } } @@ -720,7 +716,7 @@ nsresult nsMultiMixedConv::BufferData(char *aData, PRUint32 aLen) { NS_ASSERTION(!mBuffer, "trying to over-write buffer"); - char *buffer = (char*)nsMemory::Alloc(aLen); + char *buffer = (char *) malloc(aLen); if (!buffer) return NS_ERROR_OUT_OF_MEMORY; memcpy(buffer, aData, aLen); @@ -814,9 +810,9 @@ nsMultiMixedConv::SendData(char *aBuffer, PRUint32 aLen) { if (!mPartChannel) return NS_ERROR_FAILURE; // something went wrong w/ processing - if (mContentLength != -1) { // make sure that we don't send more than the mContentLength + // XXX why? perhaps the Content-Length header was actually wrong!! if ((aLen + mTotalSent) > PRUint32(mContentLength)) aLen = mContentLength - mTotalSent; @@ -824,41 +820,34 @@ nsMultiMixedConv::SendData(char *aBuffer, PRUint32 aLen) { return NS_OK; } + PRUint32 offset = mTotalSent; mTotalSent += aLen; - char *tmp = (char*)nsMemory::Alloc(aLen); // byteArray stream owns this mem - if (!tmp) return NS_ERROR_OUT_OF_MEMORY; - - memcpy(tmp, aBuffer, aLen); - - nsCOMPtr byteArrayStream; - - rv = NS_NewByteArrayInputStream(getter_AddRefs(byteArrayStream), tmp, aLen); - if (NS_FAILED(rv)) { - nsMemory::Free(tmp); + nsCOMPtr ss( + do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv)); + if (NS_FAILED(rv)) return rv; - } - nsCOMPtr inStream = do_QueryInterface(byteArrayStream, &rv); + rv = ss->ShareData(aBuffer, aLen); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr inStream(do_QueryInterface(ss, &rv)); if (NS_FAILED(rv)) return rv; - PRUint32 len; - rv = inStream->Available(&len); - if (NS_FAILED(rv)) return rv; - - return mFinalListener->OnDataAvailable(mPartChannel, mContext, inStream, 0, len); + return mFinalListener->OnDataAvailable(mPartChannel, mContext, inStream, offset, aLen); } PRInt32 nsMultiMixedConv::PushOverLine(char *&aPtr, PRUint32 &aLen) { PRInt32 chars = 0; - if (*aPtr == nsCRT::CR || *aPtr == nsCRT::LF) { - if (aPtr[1] == nsCRT::LF) + if ((aLen > 0) && (*aPtr == nsCRT::CR || *aPtr == nsCRT::LF)) { + if ((aLen > 1) && (aPtr[1] == nsCRT::LF)) chars++; chars++; + aPtr += chars; + aLen -= chars; } - aPtr += chars; - aLen -= chars; return chars; } @@ -866,36 +855,37 @@ nsresult nsMultiMixedConv::ParseHeaders(nsIChannel *aChannel, char *&aPtr, PRUint32 &aLen, PRBool *_retval) { // NOTE: this data must be ascii. + // NOTE: aPtr is NOT null terminated! nsresult rv = NS_OK; char *cursor = aPtr, *newLine = nsnull; PRUint32 cursorLen = aLen; PRBool done = PR_FALSE; PRUint32 lineFeedIncrement = 1; - mContentLength = -1; - while ( (cursorLen > 0) - && (newLine = PL_strchr(cursor, nsCRT::LF)) ) { + mContentLength = -1; // XXX what if we were already called? + while (cursorLen && (newLine = (char *) memchr(cursor, nsCRT::LF, cursorLen))) { // adjust for linefeeds - if ( (newLine > cursor) && (newLine[-1] == nsCRT::CR) ) { // CRLF - lineFeedIncrement = 2; - newLine--; + if ((newLine > cursor) && (newLine[-1] == nsCRT::CR) ) { // CRLF + lineFeedIncrement = 2; + newLine--; } + else + lineFeedIncrement = 1; // reset if (newLine == cursor) { - // move the newLine beyond the double linefeed marker - if (cursorLen >= lineFeedIncrement) { - newLine += lineFeedIncrement; - } - cursorLen -= (newLine - cursor); - cursor = newLine; + // move the newLine beyond the linefeed marker + NS_ASSERTION(cursorLen >= lineFeedIncrement, "oops!"); + + cursor += lineFeedIncrement; + cursorLen -= lineFeedIncrement; done = PR_TRUE; break; } char tmpChar = *newLine; - *newLine = '\0'; - char *colon = PL_strchr(cursor, ':'); + *newLine = '\0'; // cursor is now null terminated + char *colon = (char *) strchr(cursor, ':'); if (colon) { *colon = '\0'; nsCAutoString headerStr(cursor); @@ -926,12 +916,12 @@ nsMultiMixedConv::ParseHeaders(nsIChannel *aChannel, char *&aPtr, // something like: Content-range: bytes 7000-7999/8000 char* tmpPtr; - tmpPtr = PL_strchr(colon + 1, '/'); + tmpPtr = (char *) strchr(colon + 1, '/'); if (tmpPtr) *tmpPtr = '\0'; // pass the bytes-unit and the SP - char *range = PL_strchr(colon + 2, ' '); + char *range = (char *) strchr(colon + 2, ' '); if (!range) return NS_ERROR_FAILURE; @@ -940,7 +930,7 @@ nsMultiMixedConv::ParseHeaders(nsIChannel *aChannel, char *&aPtr, mByteRangeStart = mByteRangeEnd = 0; } else { - tmpPtr = PL_strchr(range, '-'); + tmpPtr = (char *) strchr(range, '-'); if (!tmpPtr) return NS_ERROR_FAILURE; @@ -960,7 +950,7 @@ nsMultiMixedConv::ParseHeaders(nsIChannel *aChannel, char *&aPtr, newLine += lineFeedIncrement; cursorLen -= (newLine - cursor); cursor = newLine; - } // end while (newLine) + } aPtr = cursor; aLen = cursorLen; @@ -975,27 +965,27 @@ nsMultiMixedConv::FindToken(char *aCursor, PRUint32 aLen) { const char *token = mToken.get(); char *cur = aCursor; - NS_ASSERTION(token && aCursor && *token, "bad data"); + if (!(token && aCursor && *token)) { + NS_WARNING("bad data"); + return nsnull; + } - if( mTokenLen > aLen ) return nsnull; + for (; aLen >= mTokenLen; aCursor++, aLen--) { + if (!memcmp(aCursor, token, mTokenLen) ) { + if ((aCursor - cur) >= 2) { + // back the cursor up over a double dash for backwards compat. + if ((*(aCursor-1) == '-') && (*(aCursor-2) == '-')) { + aCursor -= 2; + aLen += 2; - for( ; aLen >= mTokenLen; aCursor++, aLen-- ) - if( *token == *aCursor) - if(!memcmp(aCursor, token, mTokenLen) ) { - if ( (aCursor - cur) >= 2) { - // back the cursor up over a double dash for backwards compat. - if ( (*(aCursor-1) == '-') && (*(aCursor-2) == '-') ) { - aCursor -= 2; - aLen += 2; - - // we're playing w/ double dash tokens, adjust. - nsCAutoString newToken(NS_LITERAL_CSTRING("--") + mToken); - mToken = newToken; - mTokenLen += 2; - } + // we're playing w/ double dash tokens, adjust. + mToken.Assign(aCursor, mTokenLen + 2); + mTokenLen = mToken.Length(); } - return aCursor; } + return aCursor; + } + } return nsnull; }