Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 45578e0

Browse files
committed
Bug 1170794 - Improve the length check of the input in nsUnicode*::GetMaxLength, r=dveditz
1 parent 59999b8 commit 45578e0

16 files changed

Lines changed: 137 additions & 87 deletions

intl/uconv/nsIUnicodeDecoder.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,12 @@ class nsIUnicodeDecoder : public nsISupports
103103
* @param aSrcLength [IN] the length of source data buffer
104104
* @param aDestLength [OUT] the needed size of the destination buffer
105105
* @return NS_EXACT_LENGTH if an exact length was computed
106+
* NS_ERROR_OUT_OF_MEMORY if OOM
106107
* NS_OK is all we have is an approximation
107108
*/
108-
NS_IMETHOD GetMaxLength(const char * aSrc, int32_t aSrcLength,
109-
int32_t * aDestLength) = 0;
109+
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char * aSrc,
110+
int32_t aSrcLength,
111+
int32_t * aDestLength) = 0;
110112

111113
/**
112114
* Resets the charset converter so it may be recycled for a completely

intl/uconv/nsIUnicodeEncoder.h

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -45,41 +45,6 @@ class nsIUnicharEncoder : public nsISupports
4545

4646
NS_DEFINE_STATIC_IID_ACCESSOR(nsIUnicharEncoder, NS_IUNICHARENCODER_IID)
4747

48-
//
49-
// Malloc an Encoder (unicode -> charset) buffer if the
50-
// result won't fit in the static buffer
51-
//
52-
// p = the buffer pointer (char*)
53-
// e = encoder (nsIUnicodeEncoder*)
54-
// s = string (char16_t*)
55-
// l = string length (int32_t)
56-
// sb = static buffer (char[])
57-
// sbl = static buffer length (uint32_t)
58-
// al = actual buffer length (int32_t)
59-
//
60-
#define ENCODER_BUFFER_ALLOC_IF_NEEDED(p,e,s,l,sb,sbl,al) \
61-
PR_BEGIN_MACRO \
62-
if (e \
63-
&& NS_SUCCEEDED((e)->GetMaxLength((s), (l), &(al)))\
64-
&& ((al) > (int32_t)(sbl)) \
65-
&& (nullptr!=((p)=(char*)moz_xmalloc((al)+1))) \
66-
) { \
67-
} \
68-
else { \
69-
(p) = (char*)(sb); \
70-
(al) = (sbl); \
71-
} \
72-
PR_END_MACRO
73-
74-
//
75-
// Free the Encoder buffer if it was allocated
76-
//
77-
#define ENCODER_BUFFER_FREE_IF_NEEDED(p,sb) \
78-
PR_BEGIN_MACRO \
79-
if ((p) != (char*)(sb)) \
80-
free(p); \
81-
PR_END_MACRO
82-
8348
/**
8449
* Interface for a Converter from Unicode into a Charset.
8550
*
@@ -156,10 +121,12 @@ class nsIUnicodeEncoder : public nsISupports
156121
* @param aSrcLength [IN] the length of source data buffer
157122
* @param aDestLength [OUT] the needed size of the destination buffer
158123
* @return NS_OK_UENC_EXACTLENGTH if an exact length was computed
124+
* NS_ERROR_OUT_OF_MEMORY if OOM
159125
* NS_OK if all we have is an approximation
160126
*/
161-
NS_IMETHOD GetMaxLength(const char16_t * aSrc, int32_t aSrcLength,
162-
int32_t * aDestLength) = 0;
127+
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char16_t * aSrc,
128+
int32_t aSrcLength,
129+
int32_t * aDestLength) = 0;
163130

164131
/**
165132
* Resets the charset converter so it may be recycled for a completely

intl/uconv/nsReplacementToUnicode.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ class nsReplacementToUnicode : public nsBasicDecoderSupport
2424
char16_t* aDest,
2525
int32_t* aDestLength);
2626

27-
NS_IMETHOD GetMaxLength(const char* aSrc,
28-
int32_t aSrcLength,
29-
int32_t* aDestLength);
27+
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char* aSrc,
28+
int32_t aSrcLength,
29+
int32_t* aDestLength) override;
3030

3131
NS_IMETHOD Reset();
3232

intl/uconv/nsUTF8ToUnicode.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "nsUCSupport.h"
88
#include "nsUTF8ToUnicode.h"
9+
#include "mozilla/CheckedInt.h"
910
#include "mozilla/SSE.h"
1011
#include "nsCharTraits.h"
1112
#include <algorithm>
@@ -52,7 +53,14 @@ NS_IMETHODIMP nsUTF8ToUnicode::GetMaxLength(const char * aSrc,
5253
int32_t aSrcLength,
5354
int32_t * aDestLength)
5455
{
55-
*aDestLength = aSrcLength + 1;
56+
mozilla::CheckedInt32 length = aSrcLength;
57+
length += 1;
58+
59+
if (!length.isValid()) {
60+
return NS_ERROR_FAILURE;
61+
}
62+
63+
*aDestLength = length.value();
5664
return NS_OK;
5765
}
5866

intl/uconv/nsUTF8ToUnicode.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ class nsUTF8ToUnicode : public nsBasicDecoderSupport
4949
//--------------------------------------------------------------------
5050
// Subclassing of nsDecoderSupport class [declaration]
5151

52-
NS_IMETHOD GetMaxLength(const char * aSrc, int32_t aSrcLength,
53-
int32_t * aDestLength);
52+
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char * aSrc,
53+
int32_t aSrcLength,
54+
int32_t * aDestLength) override;
5455

5556
//--------------------------------------------------------------------
5657
// Subclassing of nsBasicDecoderSupport class [declaration]

intl/uconv/nsUnicodeToUTF8.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,40 @@
66
//----------------------------------------------------------------------
77
// Global functions and data [declaration]
88
#include "nsUnicodeToUTF8.h"
9+
#include "mozilla/CheckedInt.h"
910

1011
NS_IMPL_ISUPPORTS(nsUnicodeToUTF8, nsIUnicodeEncoder)
1112

1213
//----------------------------------------------------------------------
1314
// nsUnicodeToUTF8 class [implementation]
1415

15-
NS_IMETHODIMP nsUnicodeToUTF8::GetMaxLength(const char16_t * aSrc,
16-
int32_t aSrcLength,
17-
int32_t * aDestLength)
16+
NS_IMETHODIMP nsUnicodeToUTF8::GetMaxLength(const char16_t* aSrc,
17+
int32_t aSrcLength,
18+
int32_t* aDestLength)
1819
{
20+
MOZ_ASSERT(aDestLength);
21+
1922
// aSrc is interpreted as UTF16, 3 is normally enough.
20-
// But when previous buffer only contains part of the surrogate pair, we
23+
// But when previous buffer only contains part of the surrogate pair, we
2124
// need to complete it here. If the first word in following buffer is not
2225
// in valid surrogate range, we need to convert the remaining of last buffer
2326
// to 3 bytes.
24-
*aDestLength = 3*aSrcLength + 3;
27+
mozilla::CheckedInt32 length = aSrcLength;
28+
length *= 3;
29+
length += 3;
30+
31+
if (!length.isValid()) {
32+
return NS_ERROR_FAILURE;
33+
}
34+
35+
*aDestLength = length.value();
2536
return NS_OK;
2637
}
2738

28-
NS_IMETHODIMP nsUnicodeToUTF8::Convert(const char16_t * aSrc,
29-
int32_t * aSrcLength,
30-
char * aDest,
31-
int32_t * aDestLength)
39+
NS_IMETHODIMP nsUnicodeToUTF8::Convert(const char16_t * aSrc,
40+
int32_t * aSrcLength,
41+
char * aDest,
42+
int32_t * aDestLength)
3243
{
3344
const char16_t * src = aSrc;
3445
const char16_t * srcEnd = aSrc + *aSrcLength;

intl/uconv/nsUnicodeToUTF8.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#define NS_UNICODETOUTF8_CONTRACTID "@mozilla.org/intl/unicode/encoder;1?charset=UTF-8"
1818

19-
//#define NS_ERROR_UCONV_NOUNICODETOUTF8
19+
//#define NS_ERROR_UCONV_NOUNICODETOUTF8
2020
// NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_UCONV, 0x31)
2121

2222
//----------------------------------------------------------------------
@@ -41,19 +41,20 @@ class nsUnicodeToUTF8 final : public nsIUnicodeEncoder
4141
*/
4242
nsUnicodeToUTF8() {mHighSurrogate = 0;}
4343

44-
NS_IMETHOD Convert(const char16_t * aSrc,
45-
int32_t * aSrcLength,
46-
char * aDest,
44+
NS_IMETHOD Convert(const char16_t * aSrc,
45+
int32_t * aSrcLength,
46+
char * aDest,
4747
int32_t * aDestLength) override;
4848

4949
NS_IMETHOD Finish(char * aDest, int32_t * aDestLength) override;
5050

51-
NS_IMETHOD GetMaxLength(const char16_t * aSrc, int32_t aSrcLength,
52-
int32_t * aDestLength) override;
51+
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char16_t * aSrc,
52+
int32_t aSrcLength,
53+
int32_t * aDestLength) override;
5354

5455
NS_IMETHOD Reset() override {mHighSurrogate = 0; return NS_OK;}
5556

56-
NS_IMETHOD SetOutputErrorBehavior(int32_t aBehavior,
57+
NS_IMETHOD SetOutputErrorBehavior(int32_t aBehavior,
5758
nsIUnicharEncoder * aEncoder, char16_t aChar) override {return NS_OK;}
5859

5960
protected:

intl/uconv/ucvlatin/nsUTF16ToUnicode.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "nsUTF16ToUnicode.h"
77
#include "nsCharTraits.h"
8+
#include "mozilla/CheckedInt.h"
89
#include "mozilla/Endian.h"
910

1011
enum {
@@ -181,8 +182,18 @@ NS_IMETHODIMP
181182
nsUTF16ToUnicodeBase::GetMaxLength(const char * aSrc, int32_t aSrcLength,
182183
int32_t * aDestLength)
183184
{
185+
mozilla::CheckedInt32 length = aSrcLength;
186+
187+
if (STATE_HALF_CODE_POINT & mState) {
188+
length += 1;
189+
}
190+
191+
if (!length.isValid()) {
192+
return NS_ERROR_FAILURE;
193+
}
194+
184195
// the left-over data of the previous run have to be taken into account.
185-
*aDestLength = (aSrcLength + ((STATE_HALF_CODE_POINT & mState) ? 1 : 0)) / 2;
196+
*aDestLength = length.value() / 2;
186197
if (mOddHighSurrogate)
187198
(*aDestLength)++;
188199
if (mOddLowSurrogate)

intl/uconv/ucvlatin/nsUTF16ToUnicode.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ class nsUTF16ToUnicodeBase : public nsBasicDecoderSupport
2020
int32_t * aSrcLength, char16_t * aDest,
2121
int32_t * aDestLength, bool aSwapBytes);
2222

23-
public:
23+
public:
2424
//--------------------------------------------------------------------
2525
// Subclassing of nsDecoderSupport class [declaration]
2626

27-
NS_IMETHOD GetMaxLength(const char * aSrc, int32_t aSrcLength,
28-
int32_t * aDestLength);
27+
MOZ_WARN_UNUSED_RESULT NS_IMETHOD GetMaxLength(const char * aSrc,
28+
int32_t aSrcLength,
29+
int32_t * aDestLength) override;
2930
NS_IMETHOD Reset();
3031

3132
protected:
@@ -44,7 +45,7 @@ class nsUTF16BEToUnicode : public nsUTF16ToUnicodeBase
4445
public:
4546

4647
NS_IMETHOD Convert(const char * aSrc, int32_t * aSrcLength,
47-
char16_t * aDest, int32_t * aDestLength);
48+
char16_t * aDest, int32_t * aDestLength);
4849
};
4950

5051
// UTF-16 little endian
@@ -53,7 +54,7 @@ class nsUTF16LEToUnicode : public nsUTF16ToUnicodeBase
5354
public:
5455

5556
NS_IMETHOD Convert(const char * aSrc, int32_t * aSrcLength,
56-
char16_t * aDest, int32_t * aDestLength);
57+
char16_t * aDest, int32_t * aDestLength);
5758
};
5859

5960
// UTF-16 with BOM
@@ -63,14 +64,14 @@ class nsUTF16ToUnicode : public nsUTF16ToUnicodeBase
6364

6465
nsUTF16ToUnicode() { Reset();}
6566
NS_IMETHOD Convert(const char * aSrc, int32_t * aSrcLength,
66-
char16_t * aDest, int32_t * aDestLength);
67+
char16_t * aDest, int32_t * aDestLength);
6768

6869
NS_IMETHOD Reset();
6970

7071
private:
7172

7273
enum Endian {kUnknown, kBigEndian, kLittleEndian};
73-
Endian mEndian;
74+
Endian mEndian;
7475
bool mFoundBOM;
7576
};
7677

intl/uconv/ucvlatin/nsUnicodeToUTF16.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
55

66
#include "nsUnicodeToUTF16.h"
7+
#include "mozilla/CheckedInt.h"
78
#include <string.h>
89

910
NS_IMETHODIMP nsUnicodeToUTF16BE::Convert(const char16_t * aSrc, int32_t * aSrcLength,
@@ -54,10 +55,19 @@ NS_IMETHODIMP nsUnicodeToUTF16BE::Convert(const char16_t * aSrc, int32_t * aSrcL
5455
NS_IMETHODIMP nsUnicodeToUTF16BE::GetMaxLength(const char16_t * aSrc, int32_t aSrcLength,
5556
int32_t * aDestLength)
5657
{
57-
if(0 != mBOM)
58-
*aDestLength = 2*(aSrcLength+1);
59-
else
60-
*aDestLength = 2*aSrcLength;
58+
mozilla::CheckedInt32 length = 2;
59+
60+
if(0 != mBOM) {
61+
length *= (aSrcLength+1);
62+
} else {
63+
length *= aSrcLength;
64+
}
65+
66+
if (!length.isValid()) {
67+
return NS_ERROR_FAILURE;
68+
}
69+
70+
*aDestLength = length.value();
6171
return NS_OK_UENC_EXACTLENGTH;
6272
}
6373

0 commit comments

Comments
 (0)