Bug 1170794 - Improve the length check of the input in nsUnicode*::GetMaxLength, r=dveditz
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 17 Jun 2015 12:21:39 +0100
changeset 249285 d8783629750506b806611ea15c368771fb847f33
parent 249284 3b73bf339093cd9e1c43b6b6c3b5750ca27297d0
child 249286 d772d098a392c569e854b81b27e24f97c4619e14
push id61206
push useramarchesini@mozilla.com
push dateWed, 17 Jun 2015 11:22:03 +0000
treeherdermozilla-inbound@d87836297505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdveditz
bugs1170794
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1170794 - Improve the length check of the input in nsUnicode*::GetMaxLength, r=dveditz
intl/uconv/nsIUnicodeDecoder.h
intl/uconv/nsIUnicodeEncoder.h
intl/uconv/nsReplacementToUnicode.h
intl/uconv/nsUTF8ToUnicode.cpp
intl/uconv/nsUTF8ToUnicode.h
intl/uconv/nsUnicodeToUTF8.cpp
intl/uconv/nsUnicodeToUTF8.h
intl/uconv/ucvlatin/nsUTF16ToUnicode.cpp
intl/uconv/ucvlatin/nsUTF16ToUnicode.h
intl/uconv/ucvlatin/nsUnicodeToUTF16.cpp
intl/uconv/ucvlatin/nsUnicodeToUTF16.h
intl/uconv/util/nsUCSupport.cpp
netwerk/base/nsUnicharStreamLoader.cpp
parser/htmlparser/nsScanner.cpp
widget/gtk/nsClipboard.cpp
widget/nsPrimitiveHelpers.cpp
--- a/intl/uconv/nsIUnicodeDecoder.h
+++ b/intl/uconv/nsIUnicodeDecoder.h
@@ -98,20 +98,22 @@ public:
    * Returns a quick estimation of the size of the buffer needed to hold the
    * converted data. Remember: this estimation is >= with the actual size of 
    * the buffer needed. It will be computed for the "worst case"
    *
    * @param aSrc        [IN] the source data buffer
    * @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 
    * different and urelated buffer of data.
    */
   NS_IMETHOD Reset() = 0;
 
   /**
--- a/intl/uconv/nsIUnicodeEncoder.h
+++ b/intl/uconv/nsIUnicodeEncoder.h
@@ -40,51 +40,16 @@ public:
   /**
    * Converts a character from Unicode to a Charset.
    */
   NS_IMETHOD Convert(char16_t aChar, char * aDest, int32_t * aDestLength) = 0;
 };
 
 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.
  *
  * @created         23/Nov/1998
  * @author  Catalin Rotaru [CATA]
  */
 class nsIUnicodeEncoder : public nsISupports
 {
@@ -151,20 +116,22 @@ public:
    * Returns a quick estimation of the size of the buffer needed to hold the
    * converted data. Remember: this estimation is >= with the actual size of 
    * the buffer needed. It will be computed for the "worst case"
    *
    * @param aSrc        [IN] the source data buffer
    * @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 
    * different and urelated buffer of data.
    */
   NS_IMETHOD Reset() = 0;
 
   /**
--- a/intl/uconv/nsReplacementToUnicode.h
+++ b/intl/uconv/nsReplacementToUnicode.h
@@ -19,19 +19,19 @@ class nsReplacementToUnicode : public ns
 public:
   nsReplacementToUnicode();
 
   NS_IMETHOD Convert(const char* aSrc,
                      int32_t* aSrcLength,
                      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();
 
 private:
   bool mSeenByte;
 };
 
 #endif // nsReplacementToUnicode_h_
--- a/intl/uconv/nsUTF8ToUnicode.cpp
+++ b/intl/uconv/nsUTF8ToUnicode.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCSupport.h"
 #include "nsUTF8ToUnicode.h"
+#include "mozilla/CheckedInt.h"
 #include "mozilla/SSE.h"
 #include "nsCharTraits.h"
 #include <algorithm>
 
 #define UNICODE_BYTE_ORDER_MARK    0xFEFF
 
 static char16_t* EmitSurrogatePair(uint32_t ucs4, char16_t* aDest)
 {
@@ -47,17 +48,24 @@ nsUTF8ToUnicode::nsUTF8ToUnicode()
  *  character in the input buffer. So in the worst case the destination
  *  will need to be one code unit longer than the source.
  *  See bug 301797.
  */
 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;
 }
 
 
 //----------------------------------------------------------------------
 // Subclassing of nsBasicDecoderSupport class [implementation]
 
 NS_IMETHODIMP nsUTF8ToUnicode::Reset()
--- a/intl/uconv/nsUTF8ToUnicode.h
+++ b/intl/uconv/nsUTF8ToUnicode.h
@@ -44,18 +44,19 @@ protected:
   uint32_t mUcs4; // cached Unicode character
   uint8_t mState; // cached expected number of bytes per UTF8 character sequence
   uint8_t mBytes;
   bool mFirst;
 
   //--------------------------------------------------------------------
   // 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]
 
   NS_IMETHOD Convert(const char * aSrc, int32_t * aSrcLength, 
       char16_t * aDest, int32_t * aDestLength);
 
   //--------------------------------------------------------------------
--- a/intl/uconv/nsUnicodeToUTF8.cpp
+++ b/intl/uconv/nsUnicodeToUTF8.cpp
@@ -1,39 +1,50 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //----------------------------------------------------------------------
 // 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;
   char * dest = aDest;
   int32_t destLen = *aDestLength;
   uint32_t n;
 
   //complete remaining of last conversion
--- a/intl/uconv/nsUnicodeToUTF8.h
+++ b/intl/uconv/nsUnicodeToUTF8.h
@@ -11,17 +11,17 @@
 
 // Class ID for our UnicodeToUTF8 charset converter
 // {7C657D18-EC5E-11d2-8AAC-00600811A836}
 #define NS_UNICODETOUTF8_CID \
   { 0x7c657d18, 0xec5e, 0x11d2, {0x8a, 0xac, 0x0, 0x60, 0x8, 0x11, 0xa8, 0x36}}
 
 #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)
 
 //----------------------------------------------------------------------
 // Class nsUnicodeToUTF8 [declaration]
 
 /**
  * A character set converter from Unicode to UTF8.
  *
@@ -36,29 +36,30 @@ class nsUnicodeToUTF8 final : public nsI
 
 public:
 
   /**
    * Class constructor.
    */
   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:
   char16_t mHighSurrogate;
 
 };
 
 #endif /* nsUnicodeToUTF8_h___ */
--- a/intl/uconv/ucvlatin/nsUTF16ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsUTF16ToUnicode.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUTF16ToUnicode.h"
 #include "nsCharTraits.h"
+#include "mozilla/CheckedInt.h"
 #include "mozilla/Endian.h"
 
 enum {
   STATE_NORMAL = 0,
   STATE_HALF_CODE_POINT = 1,
   STATE_FIRST_CALL = 2,
   STATE_SECOND_BYTE = STATE_FIRST_CALL | STATE_HALF_CODE_POINT,
   STATE_ODD_SURROGATE_PAIR = 4
@@ -176,18 +177,28 @@ nsUTF16ToUnicodeBase::Reset()
   mOddLowSurrogate = 0;
   return NS_OK;
 }
 
 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)
     (*aDestLength)++;
   return NS_OK;
 }
 
 
--- a/intl/uconv/ucvlatin/nsUTF16ToUnicode.h
+++ b/intl/uconv/ucvlatin/nsUTF16ToUnicode.h
@@ -15,22 +15,23 @@ class nsUTF16ToUnicodeBase : public nsBa
 protected:
   // ctor accessible only by child classes
   nsUTF16ToUnicodeBase() { Reset();}
 
   nsresult UTF16ConvertToUnicode(const char * aSrc,
                                  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:
   uint8_t mState;
   // to store an odd byte left over between runs
   uint8_t mOddByte;
   // to store an odd high surrogate left over between runs
   char16_t mOddHighSurrogate;
@@ -39,39 +40,39 @@ protected:
 };
 
 // UTF-16 big endian
 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
 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
 class nsUTF16ToUnicode : public nsUTF16ToUnicodeBase
 {
 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;
 };
 
 #endif /* nsUTF16ToUnicode_h_ */
--- a/intl/uconv/ucvlatin/nsUnicodeToUTF16.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToUTF16.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * 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, 
       char * aDest, int32_t * aDestLength)
 {
   int32_t srcInLen = *aSrcLength;
   int32_t destInLen = *aDestLength;
   int32_t srcOutLen = 0;
@@ -49,20 +50,29 @@ needmoreoutput:
   *aSrcLength = srcOutLen;
   *aDestLength = destOutLen;
   return NS_OK_UENC_MOREOUTPUT;
 }
 
 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;
 }
 
 NS_IMETHODIMP nsUnicodeToUTF16BE::Finish(char * aDest, int32_t * aDestLength)
 {
   if(0 != mBOM)
   {
      if(*aDestLength >= 2)
--- a/intl/uconv/ucvlatin/nsUnicodeToUTF16.h
+++ b/intl/uconv/ucvlatin/nsUnicodeToUTF16.h
@@ -14,18 +14,19 @@ class nsUnicodeToUTF16BE: public nsBasic
 public:
   nsUnicodeToUTF16BE() { mBOM = 0;}
 
   //--------------------------------------------------------------------
   // Interface nsIUnicodeEncoder [declaration]
 
   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, 
       nsIUnicharEncoder * aEncoder, char16_t aChar);
 
 protected:
   char16_t mBOM;
   NS_IMETHOD CopyData(char* aDest, const char16_t* aSrc, int32_t aLen  );
--- a/intl/uconv/util/nsUCSupport.cpp
+++ b/intl/uconv/util/nsUCSupport.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCSupport.h"
 #include "nsUnicodeDecodeHelper.h"
 #include "nsUnicodeEncodeHelper.h"
+#include "mozilla/CheckedInt.h"
 #include <algorithm>
 
 #define DEFAULT_BUFFER_CAPACITY 16
 
 // XXX review the buffer growth limitation code
 
 //----------------------------------------------------------------------
 // Class nsBasicDecoderSupport [implementation]
@@ -180,17 +181,25 @@ NS_IMETHODIMP nsBufferDecoderSupport::Re
   return NS_OK;
 }
 
 NS_IMETHODIMP nsBufferDecoderSupport::GetMaxLength(const char* aSrc,
                                                    int32_t aSrcLength,
                                                    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;
 }
 
 //----------------------------------------------------------------------
 // Class nsTableDecoderSupport [implementation]
 
 nsTableDecoderSupport::nsTableDecoderSupport(uScanClassID aScanClass,
                                              uShiftInTable * aShiftInTable,
@@ -546,17 +555,24 @@ NS_IMETHODIMP nsEncoderSupport::SetOutpu
   return NS_OK;
 }
 
 NS_IMETHODIMP
 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;
 }
 
 
 //----------------------------------------------------------------------
 // Class nsTableEncoderSupport [implementation]
 
 nsTableEncoderSupport::nsTableEncoderSupport(uScanClassID aScanClass,
--- a/netwerk/base/nsUnicharStreamLoader.cpp
+++ b/netwerk/base/nsUnicharStreamLoader.cpp
@@ -206,28 +206,34 @@ nsUnicharStreamLoader::WriteSegmentFun(n
                                        uint32_t aCount,
                                        uint32_t *aWriteCount)
 {
   nsUnicharStreamLoader* self = static_cast<nsUnicharStreamLoader*>(aClosure);
 
   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;
 
   self->mBuffer.SetLength(haveRead);
   *aWriteCount = aCount;
   return NS_OK;
 }
--- a/parser/htmlparser/nsScanner.cpp
+++ b/parser/htmlparser/nsScanner.cpp
@@ -236,17 +236,22 @@ nsresult nsScanner::Append(const nsAStri
  *  @return  
  */
 nsresult nsScanner::Append(const char* aBuffer, uint32_t aLen,
                            nsIRequest *aRequest)
 {
   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();
 
     int32_t totalChars = 0;
     int32_t unicharLength = unicharBufLen;
     int32_t errorPos = -1;
 
--- a/widget/gtk/nsClipboard.cpp
+++ b/widget/gtk/nsClipboard.cpp
@@ -711,17 +711,23 @@ void ConvertHTMLtoUCS2(guchar * data, in
 #ifdef DEBUG_CLIPBOARD
             g_print("        get unicode decoder error\n");
 #endif
             outUnicodeLen = 0;
             return;
         }
         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*>
                                            (moz_xmalloc((outUnicodeLen + sizeof('\0')) *
                            sizeof(char16_t)));
             if (*unicodeData) {
                 int32_t numberTmp = dataLength;
                 decoder->Convert((const char *)data, &numberTmp,
--- a/widget/nsPrimitiveHelpers.cpp
+++ b/widget/nsPrimitiveHelpers.cpp
@@ -203,17 +203,21 @@ nsPrimitiveHelpers :: ConvertPlatformPla
 
     decoder = EncodingUtils::DecoderForEncoding(platformCharset);
 
     hasConverter = true;
   }
 
   // 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 ) {
       rv = decoder->Convert(inText, &inTextLen, *outUnicode, outUnicodeLen);
       (*outUnicode)[*outUnicodeLen] = '\0';                   // null terminate. Convert() doesn't do it for us
     }
   } // if valid length