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 249359 d8783629750506b806611ea15c368771fb847f33
parent 249358 3b73bf339093cd9e1c43b6b6c3b5750ca27297d0
child 249360 d772d098a392c569e854b81b27e24f97c4619e14
push id13617
push userryanvm@gmail.com
push dateWed, 17 Jun 2015 19:05:52 +0000
treeherderfx-team@6876a553b898 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdveditz
bugs1170794
milestone41.0a1
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