Bug 1518440 - Use CheckedInt in JSON Quote function. r=jwalden
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 17 Jan 2019 18:24:49 +0000
changeset 514298 a27f8c7557d4eefc9ed75192aff5eba3d1b80d6f
parent 514297 cb1a55c678c1bad3e9e6634f7222186ece14e4b3
child 514299 b5270d03a6d80a9e514035d3a81a7715aaa19ce6
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1518440
milestone66.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 1518440 - Use CheckedInt in JSON Quote function. r=jwalden Differential Revision: https://phabricator.services.mozilla.com/D16534
js/src/builtin/JSON.cpp
--- a/js/src/builtin/JSON.cpp
+++ b/js/src/builtin/JSON.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=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 "builtin/JSON.h"
 
+#include "mozilla/CheckedInt.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/Range.h"
 #include "mozilla/ScopeExit.h"
 
 #include "jsnum.h"
 #include "jstypes.h"
 #include "jsutil.h"
 
@@ -30,16 +31,17 @@
 
 #include "builtin/Array-inl.h"
 #include "builtin/Boolean-inl.h"
 #include "vm/JSAtom-inl.h"
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
 
+using mozilla::CheckedInt;
 using mozilla::IsFinite;
 using mozilla::Maybe;
 using mozilla::RangedPtr;
 
 using JS::AutoStableStringChars;
 
 const Class js::JSONClass = {js_JSON_str,
                              JSCLASS_HAS_CACHED_PROTO(JSProto_JSON)};
@@ -134,23 +136,30 @@ static MOZ_ALWAYS_INLINE RangedPtr<DstCh
   }
 
   /* Steps 3-4. */
   *dstPtr++ = '"';
   return dstPtr;
 }
 
 template <typename SrcCharT, typename CharVectorT>
-static bool Quote(CharVectorT& sb, JSLinearString* str) {
+static bool Quote(JSContext* cx, CharVectorT& sb, JSLinearString* str) {
   // We resize the backing buffer to the maximum size we could possibly need,
   // write the escaped string into it, and shrink it back to the size we ended
   // up needing.
+
   size_t len = str->length();
+  CheckedInt<size_t> reservedLen = CheckedInt<size_t>(len) * 6 + 2;
+  if (MOZ_UNLIKELY(!reservedLen.isValid())) {
+    ReportAllocationOverflow(cx);
+    return false;
+  }
+
   size_t sbInitialLen = sb.length();
-  if (!sb.growByUninitialized(len * 6 + 2)) {
+  if (!sb.growByUninitialized(reservedLen.value())) {
     return false;
   }
 
   typedef typename CharVectorT::ElementType DstCharT;
 
   JS::AutoCheckCannotGC nogc;
   RangedPtr<const SrcCharT> srcBegin{str->chars<SrcCharT>(nogc), len};
   RangedPtr<DstCharT> dstBegin{sb.begin(), sb.begin(), sb.end()};
@@ -170,22 +179,22 @@ static bool Quote(JSContext* cx, StringB
   // Check if either has non-latin1 before calling ensure, so that the buffer's
   // hasEnsured flag is set if the converstion to twoByte was automatic.
   if (!sb.isUnderlyingBufferLatin1() || linear->hasTwoByteChars()) {
     if (!sb.ensureTwoByteChars()) {
       return false;
     }
   }
   if (linear->hasTwoByteChars()) {
-    return Quote<char16_t>(sb.rawTwoByteBuffer(), linear);
+    return Quote<char16_t>(cx, sb.rawTwoByteBuffer(), linear);
   }
 
   return sb.isUnderlyingBufferLatin1()
-             ? Quote<Latin1Char>(sb.latin1Chars(), linear)
-             : Quote<Latin1Char>(sb.rawTwoByteBuffer(), linear);
+             ? Quote<Latin1Char>(cx, sb.latin1Chars(), linear)
+             : Quote<Latin1Char>(cx, sb.rawTwoByteBuffer(), linear);
 }
 
 namespace {
 
 using ObjectVector = GCVector<JSObject*, 8>;
 
 class StringifyContext {
  public: