зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1170794 - Improve the length check of the input in nsUnicode*::GetMaxLength, r=dveditz
This commit is contained in:
Родитель
59999b8656
Коммит
45578e03fa
|
@ -103,10 +103,12 @@ public:
|
|||
* @param aSrcLength [IN] the length of source data buffer
|
||||
* @param aDestLength [OUT] the needed size of the destination buffer
|
||||
* @return NS_EXACT_LENGTH if an exact length was computed
|
||||
* NS_ERROR_OUT_OF_MEMORY if OOM
|
||||
* NS_OK is all we have is an approximation
|
||||
*/
|
||||
NS_IMETHOD GetMaxLength(const char * aSrc, int32_t aSrcLength,
|
||||
int32_t * aDestLength) = 0;
|
||||
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char * aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t * aDestLength) = 0;
|
||||
|
||||
/**
|
||||
* Resets the charset converter so it may be recycled for a completely
|
||||
|
|
|
@ -45,41 +45,6 @@ public:
|
|||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIUnicharEncoder, NS_IUNICHARENCODER_IID)
|
||||
|
||||
//
|
||||
// Malloc an Encoder (unicode -> charset) buffer if the
|
||||
// result won't fit in the static buffer
|
||||
//
|
||||
// p = the buffer pointer (char*)
|
||||
// e = encoder (nsIUnicodeEncoder*)
|
||||
// s = string (char16_t*)
|
||||
// l = string length (int32_t)
|
||||
// sb = static buffer (char[])
|
||||
// sbl = static buffer length (uint32_t)
|
||||
// al = actual buffer length (int32_t)
|
||||
//
|
||||
#define ENCODER_BUFFER_ALLOC_IF_NEEDED(p,e,s,l,sb,sbl,al) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (e \
|
||||
&& NS_SUCCEEDED((e)->GetMaxLength((s), (l), &(al)))\
|
||||
&& ((al) > (int32_t)(sbl)) \
|
||||
&& (nullptr!=((p)=(char*)moz_xmalloc((al)+1))) \
|
||||
) { \
|
||||
} \
|
||||
else { \
|
||||
(p) = (char*)(sb); \
|
||||
(al) = (sbl); \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
//
|
||||
// Free the Encoder buffer if it was allocated
|
||||
//
|
||||
#define ENCODER_BUFFER_FREE_IF_NEEDED(p,sb) \
|
||||
PR_BEGIN_MACRO \
|
||||
if ((p) != (char*)(sb)) \
|
||||
free(p); \
|
||||
PR_END_MACRO
|
||||
|
||||
/**
|
||||
* Interface for a Converter from Unicode into a Charset.
|
||||
*
|
||||
|
@ -156,10 +121,12 @@ public:
|
|||
* @param aSrcLength [IN] the length of source data buffer
|
||||
* @param aDestLength [OUT] the needed size of the destination buffer
|
||||
* @return NS_OK_UENC_EXACTLENGTH if an exact length was computed
|
||||
* NS_ERROR_OUT_OF_MEMORY if OOM
|
||||
* NS_OK if all we have is an approximation
|
||||
*/
|
||||
NS_IMETHOD GetMaxLength(const char16_t * aSrc, int32_t aSrcLength,
|
||||
int32_t * aDestLength) = 0;
|
||||
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char16_t * aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t * aDestLength) = 0;
|
||||
|
||||
/**
|
||||
* Resets the charset converter so it may be recycled for a completely
|
||||
|
|
|
@ -24,9 +24,9 @@ public:
|
|||
char16_t* aDest,
|
||||
int32_t* aDestLength);
|
||||
|
||||
NS_IMETHOD GetMaxLength(const char* aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t* aDestLength);
|
||||
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char* aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t* aDestLength) override;
|
||||
|
||||
NS_IMETHOD Reset();
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "nsUCSupport.h"
|
||||
#include "nsUTF8ToUnicode.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/SSE.h"
|
||||
#include "nsCharTraits.h"
|
||||
#include <algorithm>
|
||||
|
@ -52,7 +53,14 @@ NS_IMETHODIMP nsUTF8ToUnicode::GetMaxLength(const char * aSrc,
|
|||
int32_t aSrcLength,
|
||||
int32_t * aDestLength)
|
||||
{
|
||||
*aDestLength = aSrcLength + 1;
|
||||
mozilla::CheckedInt32 length = aSrcLength;
|
||||
length += 1;
|
||||
|
||||
if (!length.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aDestLength = length.value();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,8 +49,9 @@ protected:
|
|||
//--------------------------------------------------------------------
|
||||
// Subclassing of nsDecoderSupport class [declaration]
|
||||
|
||||
NS_IMETHOD GetMaxLength(const char * aSrc, int32_t aSrcLength,
|
||||
int32_t * aDestLength);
|
||||
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char * aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t * aDestLength) override;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Subclassing of nsBasicDecoderSupport class [declaration]
|
||||
|
|
|
@ -6,29 +6,40 @@
|
|||
//----------------------------------------------------------------------
|
||||
// Global functions and data [declaration]
|
||||
#include "nsUnicodeToUTF8.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsUnicodeToUTF8, nsIUnicodeEncoder)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsUnicodeToUTF8 class [implementation]
|
||||
|
||||
NS_IMETHODIMP nsUnicodeToUTF8::GetMaxLength(const char16_t * aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t * aDestLength)
|
||||
NS_IMETHODIMP nsUnicodeToUTF8::GetMaxLength(const char16_t* aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t* aDestLength)
|
||||
{
|
||||
MOZ_ASSERT(aDestLength);
|
||||
|
||||
// aSrc is interpreted as UTF16, 3 is normally enough.
|
||||
// But when previous buffer only contains part of the surrogate pair, we
|
||||
// But when previous buffer only contains part of the surrogate pair, we
|
||||
// need to complete it here. If the first word in following buffer is not
|
||||
// in valid surrogate range, we need to convert the remaining of last buffer
|
||||
// to 3 bytes.
|
||||
*aDestLength = 3*aSrcLength + 3;
|
||||
mozilla::CheckedInt32 length = aSrcLength;
|
||||
length *= 3;
|
||||
length += 3;
|
||||
|
||||
if (!length.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aDestLength = length.value();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsUnicodeToUTF8::Convert(const char16_t * aSrc,
|
||||
int32_t * aSrcLength,
|
||||
char * aDest,
|
||||
int32_t * aDestLength)
|
||||
NS_IMETHODIMP nsUnicodeToUTF8::Convert(const char16_t * aSrc,
|
||||
int32_t * aSrcLength,
|
||||
char * aDest,
|
||||
int32_t * aDestLength)
|
||||
{
|
||||
const char16_t * src = aSrc;
|
||||
const char16_t * srcEnd = aSrc + *aSrcLength;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#define NS_UNICODETOUTF8_CONTRACTID "@mozilla.org/intl/unicode/encoder;1?charset=UTF-8"
|
||||
|
||||
//#define NS_ERROR_UCONV_NOUNICODETOUTF8
|
||||
//#define NS_ERROR_UCONV_NOUNICODETOUTF8
|
||||
// NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_UCONV, 0x31)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -41,19 +41,20 @@ public:
|
|||
*/
|
||||
nsUnicodeToUTF8() {mHighSurrogate = 0;}
|
||||
|
||||
NS_IMETHOD Convert(const char16_t * aSrc,
|
||||
int32_t * aSrcLength,
|
||||
char * aDest,
|
||||
NS_IMETHOD Convert(const char16_t * aSrc,
|
||||
int32_t * aSrcLength,
|
||||
char * aDest,
|
||||
int32_t * aDestLength) override;
|
||||
|
||||
NS_IMETHOD Finish(char * aDest, int32_t * aDestLength) override;
|
||||
|
||||
NS_IMETHOD GetMaxLength(const char16_t * aSrc, int32_t aSrcLength,
|
||||
int32_t * aDestLength) override;
|
||||
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char16_t * aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t * aDestLength) override;
|
||||
|
||||
NS_IMETHOD Reset() override {mHighSurrogate = 0; return NS_OK;}
|
||||
|
||||
NS_IMETHOD SetOutputErrorBehavior(int32_t aBehavior,
|
||||
NS_IMETHOD SetOutputErrorBehavior(int32_t aBehavior,
|
||||
nsIUnicharEncoder * aEncoder, char16_t aChar) override {return NS_OK;}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "nsUTF16ToUnicode.h"
|
||||
#include "nsCharTraits.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/Endian.h"
|
||||
|
||||
enum {
|
||||
|
@ -181,8 +182,18 @@ NS_IMETHODIMP
|
|||
nsUTF16ToUnicodeBase::GetMaxLength(const char * aSrc, int32_t aSrcLength,
|
||||
int32_t * aDestLength)
|
||||
{
|
||||
mozilla::CheckedInt32 length = aSrcLength;
|
||||
|
||||
if (STATE_HALF_CODE_POINT & mState) {
|
||||
length += 1;
|
||||
}
|
||||
|
||||
if (!length.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// the left-over data of the previous run have to be taken into account.
|
||||
*aDestLength = (aSrcLength + ((STATE_HALF_CODE_POINT & mState) ? 1 : 0)) / 2;
|
||||
*aDestLength = length.value() / 2;
|
||||
if (mOddHighSurrogate)
|
||||
(*aDestLength)++;
|
||||
if (mOddLowSurrogate)
|
||||
|
|
|
@ -20,12 +20,13 @@ protected:
|
|||
int32_t * aSrcLength, char16_t * aDest,
|
||||
int32_t * aDestLength, bool aSwapBytes);
|
||||
|
||||
public:
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
// Subclassing of nsDecoderSupport class [declaration]
|
||||
|
||||
NS_IMETHOD GetMaxLength(const char * aSrc, int32_t aSrcLength,
|
||||
int32_t * aDestLength);
|
||||
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char * aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t * aDestLength) override;
|
||||
NS_IMETHOD Reset();
|
||||
|
||||
protected:
|
||||
|
@ -44,7 +45,7 @@ class nsUTF16BEToUnicode : public nsUTF16ToUnicodeBase
|
|||
public:
|
||||
|
||||
NS_IMETHOD Convert(const char * aSrc, int32_t * aSrcLength,
|
||||
char16_t * aDest, int32_t * aDestLength);
|
||||
char16_t * aDest, int32_t * aDestLength);
|
||||
};
|
||||
|
||||
// UTF-16 little endian
|
||||
|
@ -53,7 +54,7 @@ class nsUTF16LEToUnicode : public nsUTF16ToUnicodeBase
|
|||
public:
|
||||
|
||||
NS_IMETHOD Convert(const char * aSrc, int32_t * aSrcLength,
|
||||
char16_t * aDest, int32_t * aDestLength);
|
||||
char16_t * aDest, int32_t * aDestLength);
|
||||
};
|
||||
|
||||
// UTF-16 with BOM
|
||||
|
@ -63,14 +64,14 @@ public:
|
|||
|
||||
nsUTF16ToUnicode() { Reset();}
|
||||
NS_IMETHOD Convert(const char * aSrc, int32_t * aSrcLength,
|
||||
char16_t * aDest, int32_t * aDestLength);
|
||||
char16_t * aDest, int32_t * aDestLength);
|
||||
|
||||
NS_IMETHOD Reset();
|
||||
|
||||
private:
|
||||
|
||||
enum Endian {kUnknown, kBigEndian, kLittleEndian};
|
||||
Endian mEndian;
|
||||
Endian mEndian;
|
||||
bool mFoundBOM;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsUnicodeToUTF16.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include <string.h>
|
||||
|
||||
NS_IMETHODIMP nsUnicodeToUTF16BE::Convert(const char16_t * aSrc, int32_t * aSrcLength,
|
||||
|
@ -54,10 +55,19 @@ needmoreoutput:
|
|||
NS_IMETHODIMP nsUnicodeToUTF16BE::GetMaxLength(const char16_t * aSrc, int32_t aSrcLength,
|
||||
int32_t * aDestLength)
|
||||
{
|
||||
if(0 != mBOM)
|
||||
*aDestLength = 2*(aSrcLength+1);
|
||||
else
|
||||
*aDestLength = 2*aSrcLength;
|
||||
mozilla::CheckedInt32 length = 2;
|
||||
|
||||
if(0 != mBOM) {
|
||||
length *= (aSrcLength+1);
|
||||
} else {
|
||||
length *= aSrcLength;
|
||||
}
|
||||
|
||||
if (!length.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aDestLength = length.value();
|
||||
return NS_OK_UENC_EXACTLENGTH;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,9 @@ public:
|
|||
|
||||
NS_IMETHOD Convert(const char16_t * aSrc, int32_t * aSrcLength,
|
||||
char * aDest, int32_t * aDestLength);
|
||||
NS_IMETHOD GetMaxLength(const char16_t * aSrc, int32_t aSrcLength,
|
||||
int32_t * aDestLength);
|
||||
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char16_t * aSrc,
|
||||
int32_t aSrcLength,
|
||||
int32_t * aDestLength);
|
||||
NS_IMETHOD Finish(char * aDest, int32_t * aDestLength);
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD SetOutputErrorBehavior(int32_t aBehavior,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "nsUCSupport.h"
|
||||
#include "nsUnicodeDecodeHelper.h"
|
||||
#include "nsUnicodeEncodeHelper.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include <algorithm>
|
||||
|
||||
#define DEFAULT_BUFFER_CAPACITY 16
|
||||
|
@ -185,7 +186,15 @@ NS_IMETHODIMP nsBufferDecoderSupport::GetMaxLength(const char* aSrc,
|
|||
int32_t* aDestLength)
|
||||
{
|
||||
NS_ASSERTION(mMaxLengthFactor != 0, "Must override GetMaxLength!");
|
||||
*aDestLength = aSrcLength * mMaxLengthFactor;
|
||||
|
||||
mozilla::CheckedInt32 length = aSrcLength;
|
||||
length *= mMaxLengthFactor;
|
||||
|
||||
if (!length.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aDestLength = length.value();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -551,7 +560,14 @@ nsEncoderSupport::GetMaxLength(const char16_t * aSrc,
|
|||
int32_t aSrcLength,
|
||||
int32_t * aDestLength)
|
||||
{
|
||||
*aDestLength = aSrcLength * mMaxLengthFactor;
|
||||
mozilla::CheckedInt32 length = aSrcLength;
|
||||
length *= mMaxLengthFactor;
|
||||
|
||||
if (!length.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aDestLength = length.value();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -211,19 +211,25 @@ nsUnicharStreamLoader::WriteSegmentFun(nsIInputStream *,
|
|||
uint32_t haveRead = self->mBuffer.Length();
|
||||
int32_t srcLen = aCount;
|
||||
int32_t dstLen;
|
||||
self->mDecoder->GetMaxLength(aSegment, srcLen, &dstLen);
|
||||
|
||||
nsresult rv = self->mDecoder->GetMaxLength(aSegment, srcLen, &dstLen);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint32_t capacity = haveRead + dstLen;
|
||||
if (!self->mBuffer.SetCapacity(capacity, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
DebugOnly<nsresult> rv =
|
||||
self->mDecoder->Convert(aSegment,
|
||||
&srcLen,
|
||||
self->mBuffer.BeginWriting() + haveRead,
|
||||
&dstLen);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
rv = self->mDecoder->Convert(aSegment,
|
||||
&srcLen,
|
||||
self->mBuffer.BeginWriting() + haveRead,
|
||||
&dstLen);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(srcLen == static_cast<int32_t>(aCount));
|
||||
haveRead += dstLen;
|
||||
|
||||
|
|
|
@ -241,7 +241,12 @@ nsresult nsScanner::Append(const char* aBuffer, uint32_t aLen,
|
|||
nsresult res = NS_OK;
|
||||
if (mUnicodeDecoder) {
|
||||
int32_t unicharBufLen = 0;
|
||||
mUnicodeDecoder->GetMaxLength(aBuffer, aLen, &unicharBufLen);
|
||||
|
||||
nsresult rv = mUnicodeDecoder->GetMaxLength(aBuffer, aLen, &unicharBufLen);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsScannerString::Buffer* buffer = nsScannerString::AllocBuffer(unicharBufLen + 1);
|
||||
NS_ENSURE_TRUE(buffer,NS_ERROR_OUT_OF_MEMORY);
|
||||
char16_t *unichars = buffer->DataStart();
|
||||
|
|
|
@ -716,7 +716,13 @@ void ConvertHTMLtoUCS2(guchar * data, int32_t dataLength,
|
|||
}
|
||||
decoder = EncodingUtils::DecoderForEncoding(encoding);
|
||||
// converting
|
||||
decoder->GetMaxLength((const char *)data, dataLength, &outUnicodeLen);
|
||||
nsresult rv = decoder->GetMaxLength((const char *)data, dataLength,
|
||||
&outUnicodeLen);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
outUnicodeLen = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// |outUnicodeLen| is number of chars
|
||||
if (outUnicodeLen) {
|
||||
*unicodeData = reinterpret_cast<char16_t*>
|
||||
|
|
|
@ -208,7 +208,11 @@ nsPrimitiveHelpers :: ConvertPlatformPlainTextToUnicode ( const char* inText, in
|
|||
|
||||
// Estimate out length and allocate the buffer based on a worst-case estimate, then do
|
||||
// the conversion.
|
||||
decoder->GetMaxLength(inText, inTextLen, outUnicodeLen); // |outUnicodeLen| is number of chars
|
||||
rv = decoder->GetMaxLength(inText, inTextLen, outUnicodeLen); // |outUnicodeLen| is number of chars
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if ( *outUnicodeLen ) {
|
||||
*outUnicode = reinterpret_cast<char16_t*>(moz_xmalloc((*outUnicodeLen + 1) * sizeof(char16_t)));
|
||||
if ( *outUnicode ) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче