Bug 1128413, Part 3: Enable more compiler warnings, r=mmc
authorBrian Smith <brian@briansmith.org>
Sat, 07 Feb 2015 14:38:40 -0800
changeset 255643 d17a125c8ee74f60dfae9e5637885b9cc33bc667
parent 255642 09c407963c95928f8c5e8742256a3f740edcb06b
child 255644 80a2f25792fc84d2137ed485d07e8afefefe06c8
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmmc
bugs1128413
milestone38.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 1128413, Part 3: Enable more compiler warnings, r=mmc
security/pkix/include/pkix/Input.h
security/pkix/lib/pkixder.h
security/pkix/lib/pkixnames.cpp
security/pkix/lib/pkixtime.cpp
security/pkix/lib/pkixutil.h
security/pkix/moz.build
security/pkix/test/gtest/moz.build
security/pkix/test/gtest/pkixbuild_tests.cpp
security/pkix/test/gtest/pkixcert_extension_tests.cpp
security/pkix/test/gtest/pkixcheck_CheckKeyUsage_tests.cpp
security/pkix/test/gtest/pkixcheck_CheckValidity_tests.cpp
security/pkix/test/gtest/pkixder_input_tests.cpp
security/pkix/test/gtest/pkixder_pki_types_tests.cpp
security/pkix/test/gtest/pkixder_universal_types_tests.cpp
security/pkix/test/gtest/pkixgtest.cpp
security/pkix/test/gtest/pkixgtest.h
security/pkix/test/gtest/pkixnames_tests.cpp
security/pkix/test/gtest/pkixocsp_CreateEncodedOCSPRequest_tests.cpp
security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp
security/pkix/test/lib/pkixtestnss.cpp
security/pkix/test/lib/pkixtestutil.cpp
security/pkix/test/lib/pkixtestutil.h
security/pkix/warnings.mozbuild
--- a/security/pkix/include/pkix/Input.h
+++ b/security/pkix/include/pkix/Input.h
@@ -75,16 +75,19 @@ public:
 
   // Construct a valid, empty, Init-able Input.
   Input()
     : data(nullptr)
     , len(0u)
   {
   }
 
+  // This is intentionally not explicit in order to allow value semantics.
+  Input(const Input&) = default;
+
   // Initialize the input. data must be non-null and len must be less than
   // 65536. Init may not be called more than once.
   Result Init(const uint8_t* data, size_t len)
   {
     if (this->data) {
       // already initialized
       return Result::FATAL_ERROR_INVALID_ARGS;
     }
@@ -266,31 +269,33 @@ public:
 
   void SkipToEnd()
   {
     input = end;
   }
 
   Result SkipToEnd(/*out*/ Input& skipped)
   {
-    return Skip(static_cast<size_t>(end - input), skipped);
+    return Skip(static_cast<Input::size_type>(end - input), skipped);
   }
 
   Result EnsureLength(Input::size_type len)
   {
     if (static_cast<size_t>(end - input) < len) {
       return Result::ERROR_BAD_DER;
     }
     return Success;
   }
 
   bool AtEnd() const { return input == end; }
 
   class Mark final
   {
+  public:
+    Mark(const Mark&) = default; // Intentionally not explicit.
   private:
     friend class Reader;
     Mark(const Reader& input, const uint8_t* mark) : input(input), mark(mark) { }
     const Reader& input;
     const uint8_t* const mark;
     void operator=(const Mark&) = delete;
   };
 
--- a/security/pkix/lib/pkixder.h
+++ b/security/pkix/lib/pkixder.h
@@ -50,17 +50,17 @@ enum Class : uint8_t
 // PRIVATE = 3 << 6 // unused
 };
 
 enum Constructed
 {
   CONSTRUCTED = 1 << 5
 };
 
-enum Tag
+enum Tag : uint8_t
 {
   BOOLEAN = UNIVERSAL | 0x01,
   INTEGER = UNIVERSAL | 0x02,
   BIT_STRING = UNIVERSAL | 0x03,
   OCTET_STRING = UNIVERSAL | 0x04,
   NULLTag = UNIVERSAL | 0x05,
   OIDTag = UNIVERSAL | 0x06,
   ENUMERATED = UNIVERSAL | 0x0a,
--- a/security/pkix/lib/pkixnames.cpp
+++ b/security/pkix/lib/pkixnames.cpp
@@ -1637,23 +1637,24 @@ FinishIPv6Address(/*in/out*/ uint8_t (&a
     return numComponents == 8;
   }
 
   if (numComponents >= 8) {
     return false; // no room left to expand the contraction.
   }
 
   // Shift components that occur after the contraction over.
-  int componentsToMove = numComponents - contractionIndex;
-  memmove(address + (2u * (8 - componentsToMove)),
-          address + (2u * contractionIndex),
+  size_t componentsToMove = static_cast<size_t>(numComponents -
+                                                contractionIndex);
+  memmove(address + (2u * static_cast<size_t>(8 - componentsToMove)),
+          address + (2u * static_cast<size_t>(contractionIndex)),
           componentsToMove * 2u);
   // Fill in the contracted area with zeros.
-  memset(address + (2u * contractionIndex), 0u,
-         (8u - numComponents) * 2u);
+  memset(address + (2u * static_cast<size_t>(contractionIndex)), 0u,
+         (8u - static_cast<size_t>(numComponents)) * 2u);
 
   return true;
 }
 
 } // unnamed namespace
 
 // On Windows and maybe other platforms, OS-provided IP address parsing
 // functions might fail if the protocol (IPv4 or IPv6) has been disabled, so we
@@ -1780,17 +1781,16 @@ ParseIPv6Address(Input hostname, /*out*/
       return false;
     }
 
     if (input.Peek(':')) {
       // Contraction
       if (contractionIndex != -1) {
         return false; // multiple contractions are not allowed.
       }
-      uint8_t b;
       if (input.Read(b) != Success || b != ':') {
         assert(false);
         return false;
       }
       contractionIndex = currentComponentIndex;
       if (input.AtEnd()) {
         // "::" at the end of the input.
         return FinishIPv6Address(out, currentComponentIndex,
--- a/security/pkix/lib/pkixtime.cpp
+++ b/security/pkix/lib/pkixtime.cpp
@@ -19,18 +19,25 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #include "pkix/Time.h"
 #include "pkixutil.h"
+
 #ifdef WIN32
+#ifdef _MSC_VER
+#pragma warning(push, 3)
+#endif
 #include "windows.h"
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
 #else
 #include "sys/time.h"
 #endif
 
 namespace mozilla { namespace pkix {
 
 Time
 Now()
@@ -48,17 +55,18 @@ Now()
   seconds = (DaysBeforeYear(1601) * Time::ONE_DAY_IN_SECONDS) +
             ft64 / (1000u * 1000u * 1000u / 100u);
 #else
   // "The gettimeofday() function shall obtain the current time, expressed as
   // seconds and microseconds since the Epoch."
   //   - http://pubs.opengroup.org/onlinepubs/009695399/functions/gettimeofday.html
   timeval tv;
   (void) gettimeofday(&tv, nullptr);
-  seconds = (DaysBeforeYear(1970) * Time::ONE_DAY_IN_SECONDS) + tv.tv_sec;
+  seconds = (DaysBeforeYear(1970) * Time::ONE_DAY_IN_SECONDS) +
+            static_cast<uint64_t>(tv.tv_sec);
 #endif
 
   return TimeFromElapsedSecondsAD(seconds);
 }
 
 Time
 TimeFromEpochInSeconds(uint64_t secondsSinceEpoch)
 {
--- a/security/pkix/lib/pkixutil.h
+++ b/security/pkix/lib/pkixutil.h
@@ -48,17 +48,17 @@ public:
     , endEntityOrCA(endEntityOrCA)
     , childCert(childCert)
   {
   }
 
   Result Init();
 
   const Input GetDER() const { return der; }
-  const der::Version GetVersion() const { return version; }
+  der::Version GetVersion() const { return version; }
   const SignedDataWithSignature& GetSignedData() const { return signedData; }
   const Input GetIssuer() const { return issuer; }
   // XXX: "validity" is a horrible name for the structure that holds
   // notBefore & notAfter, but that is the name used in RFC 5280 and we use the
   // RFC 5280 names for everything.
   const Input GetValidity() const { return validity; }
   const Input GetSerialNumber() const { return serialNumber; }
   const Input GetSubject() const { return subject; }
@@ -227,31 +227,32 @@ WrappedVerifySignedData(TrustDomain& tru
 //
 //     int func(XY xy) {
 //       switch (xy) {
 //         case XY::X: return 1;
 //         case XY::Y; return 2;
 //         MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
 //       }
 //     }
-#if defined(__clang__) && (__clang_major__ == 3 && __clang_minor__ < 5)
-  // Earlier versions of Clang will warn if not all cases are covered
-  // (-Wswitch-enum) AND they always, inappropriately, assume the default case
-  // is unreachable. This was fixed in
-  // http://llvm.org/klaus/clang/commit/28cd22d7c2d2458575ce9cc19dfe63c6321010ce/
-# define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM // empty
-#elif defined(__GNUC__) || defined(__clang__)
-  // GCC and recent versions of clang will warn if not all cases are covered
-  // (-Wswitch-enum). They do not assume that the default case is unreachable.
-# define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM \
-         default: assert(false); __builtin_unreachable();
+#if defined(__clang__)
+// Clang will warn if not all cases are covered (-Wswitch-enum) AND it will
+// warn if a switch statement that covers every enum label has a default case
+// (-W-covered-switch-default). Versions prior to 3.5 warned about unreachable
+// code in such default cases (-Wunreachable-code) even when
+// -W-covered-switch-default was disabled, but that changed in Clang 3.5.
+#define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM // empty
+#elif defined(__GNUC__)
+// GCC will warn if not all cases are covered (-Wswitch-enum). It does not
+// assume that the default case is unreachable.
+#define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM \
+        default: assert(false); __builtin_unreachable();
 #elif defined(_MSC_VER)
-  // MSVC will warn if not all cases are covered (C4061, level 4). It does not
-  // assume that the default case is unreachable.
-# define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM \
-         default: assert(false); __assume(0);
+// MSVC will warn if not all cases are covered (C4061, level 4). It does not
+// assume that the default case is unreachable.
+#define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM \
+        default: assert(false); __assume(0);
 #else
-# error Unsupported compiler for MOZILLA_PKIX_UNREACHABLE_DEFAULT.
+#error Unsupported compiler for MOZILLA_PKIX_UNREACHABLE_DEFAULT.
 #endif
 
 } } // namespace mozilla::pkix
 
 #endif // mozilla_pkix_pkixutil_h
--- a/security/pkix/moz.build
+++ b/security/pkix/moz.build
@@ -20,24 +20,13 @@ LOCAL_INCLUDES += [
     'include',
 ]
 
 TEST_DIRS += [
     'test/gtest',
     'test/lib',
 ]
 
-CXXFLAGS += ['-Wall']
-# -Wall with Visual C++ enables too many problematic warnings
-if CONFIG['_MSC_VER']:
-  CXXFLAGS += [
-    '-wd4514', # 'function': unreferenced inline function has been removed
-    '-wd4668', # 'symbol' is not defined as a preprocessor macro...
-    '-wd4710', # 'function': function not inlined
-    '-wd4711', # function 'function' selected for inline expansion
-    '-wd4820', # 'bytes' bytes padding added after construct 'member_name'
-  ]
-
-FAIL_ON_WARNINGS = True
+include('warnings.mozbuild')
 
 Library('mozillapkix')
 
 FINAL_LIBRARY = 'xul'
--- a/security/pkix/test/gtest/moz.build
+++ b/security/pkix/test/gtest/moz.build
@@ -25,16 +25,29 @@ SOURCES += [
 LOCAL_INCLUDES += [
     '../../include',
     '../../lib',
     '../lib',
 ]
 
 FINAL_LIBRARY = 'xul-gtest'
 
-include('/ipc/chromium/chromium-config.mozbuild')
+include('../../warnings.mozbuild')
 
-if CONFIG['_MSC_VER']:
+# These warnings are disabled in order to minimize the amount of boilerplate
+# required to implement tests, and/or because they originate in the GTest
+# framework in a way we cannot otherwise work around.
+if CONFIG['CLANG_CXX']:
   CXXFLAGS += [
-    '-wd4275', # non dll-interface class used as base for dll-interface class
+    '-Wno-exit-time-destructors',
+    '-Wno-global-constructors',
+    '-Wno-old-style-cast',
+    '-Wno-used-but-marked-unused',
   ]
-
-FAIL_ON_WARNINGS = True
+elif CONFIG['_MSC_VER']:
+  CXXFLAGS += [
+    '-wd4350', # behavior change: 'std::_Wrap_alloc<std::allocator<_Ty>>::...
+    '-wd4275', # non dll-interface class used as base for dll-interface class
+    '-wd4548', # Expression before comma has no effect
+    '-wd4625', # copy constructor could not be generated.
+    '-wd4626', # assugment operator could not be generated.
+    '-wd4640', # construction of local static object is not thread safe.
+  ]
--- a/security/pkix/test/gtest/pkixbuild_tests.cpp
+++ b/security/pkix/test/gtest/pkixbuild_tests.cpp
@@ -17,18 +17,30 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
+#if defined(_MSC_VER) && _MSC_VER < 1900
+// When building with -D_HAS_EXCEPTIONS=0, MSVC's <xtree> header triggers
+// warning C4702: unreachable code.
+// https://connect.microsoft.com/VisualStudio/feedback/details/809962
+#pragma warning(push)
+#pragma warning(disable: 4702)
+#endif
+
 #include <map>
-#include "cert.h"
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#pragma warning(pop)
+#endif
+
 #include "pkix/pkix.h"
 #include "pkixgtest.h"
 #include "pkixtestutil.h"
 
 using namespace mozilla::pkix;
 using namespace mozilla::pkix::test;
 
 static ByteString
@@ -105,17 +117,17 @@ private:
                       /*out*/ TrustLevel& trustLevel) override
   {
     trustLevel = InputEqualsByteString(candidateCert, rootCACertDER)
                ? TrustLevel::TrustAnchor
                : TrustLevel::InheritsTrust;
     return Success;
   }
 
-  Result FindIssuer(Input encodedIssuerName, IssuerChecker& checker, Time time)
+  Result FindIssuer(Input encodedIssuerName, IssuerChecker& checker, Time)
                     override
   {
     ByteString subjectDER(InputToByteString(encodedIssuerName));
     ByteString certDER(subjectDERToCertDER[subjectDER]);
     Input derCert;
     Result rv = derCert.Init(certDER.data(), certDER.length());
     if (rv != Success) {
       return rv;
@@ -142,18 +154,17 @@ private:
   }
 
   Result VerifySignedData(const SignedDataWithSignature& signedData,
                           Input subjectPublicKeyInfo) override
   {
     return TestVerifySignedData(signedData, subjectPublicKeyInfo);
   }
 
-  Result DigestBuf(Input item, /*out*/ uint8_t *digestBuf, size_t digestBufLen)
-                   override
+  Result DigestBuf(Input, /*out*/ uint8_t*, size_t) override
   {
     ADD_FAILURE();
     return Result::FATAL_ERROR_LIBRARY_FAILURE;
   }
 
   Result CheckPublicKey(Input subjectPublicKeyInfo) override
   {
     return TestCheckPublicKey(subjectPublicKeyInfo);
@@ -256,35 +267,33 @@ class ExpiredCertTrustDomain final : pub
 {
 public:
   explicit ExpiredCertTrustDomain(ByteString rootDER)
     : rootDER(rootDER)
   {
   }
 
   // The CertPolicyId argument is unused because we don't care about EV.
-  Result GetCertTrust(EndEntityOrCA endEntityOrCA, const CertPolicyId&,
-                      Input candidateCert, /*out*/ TrustLevel& trustLevel)
-                      override
+  Result GetCertTrust(EndEntityOrCA, const CertPolicyId&, Input candidateCert,
+                      /*out*/ TrustLevel& trustLevel) override
   {
     Input rootCert;
     Result rv = rootCert.Init(rootDER.data(), rootDER.length());
     if (rv != Success) {
       return rv;
     }
     if (InputsAreEqual(candidateCert, rootCert)) {
       trustLevel = TrustLevel::TrustAnchor;
     } else {
       trustLevel = TrustLevel::InheritsTrust;
     }
     return Success;
   }
 
-  Result FindIssuer(Input encodedIssuerName, IssuerChecker& checker, Time time)
-                    override
+  Result FindIssuer(Input, IssuerChecker& checker, Time) override
   {
     // keepGoing is an out parameter from IssuerChecker.Check. It would tell us
     // whether or not to continue attempting other potential issuers. We only
     // know of one potential issuer, however, so we ignore it.
     bool keepGoing;
     Input rootCert;
     Result rv = rootCert.Init(rootDER.data(), rootDER.length());
     if (rv != Success) {
@@ -338,17 +347,17 @@ TEST_F(pkixbuild, NoRevocationCheckingFo
   ByteString serialNumber(CreateEncodedSerialNumber(100));
   EXPECT_FALSE(ENCODING_FAILED(serialNumber));
   ByteString issuerDER(CNToDERName(rootCN));
   ByteString subjectDER(CNToDERName("Expired End-Entity Cert"));
   ScopedTestKeyPair reusedKey(CloneReusedKeyPair());
   ByteString certDER(CreateEncodedCertificate(
                        v3, sha256WithRSAEncryption,
                        serialNumber, issuerDER,
-                       oneDayBeforeNow - Time::ONE_DAY_IN_SECONDS,
+                       oneDayBeforeNow - ONE_DAY_IN_SECONDS_AS_TIME_T,
                        oneDayBeforeNow,
                        subjectDER, *reusedKey, nullptr, *reusedKey,
                        sha256WithRSAEncryption));
   EXPECT_FALSE(ENCODING_FAILED(certDER));
 
   Input cert;
   ASSERT_EQ(Success, cert.Init(certDER.data(), certDER.length()));
   ASSERT_EQ(Result::ERROR_EXPIRED_CERTIFICATE,
@@ -384,18 +393,17 @@ public:
     return Result::FATAL_ERROR_LIBRARY_FAILURE;
   }
 
   Result IsChainValid(const DERArray&, Time) override
   {
     return Success;
   }
 
-  Result VerifySignedData(const SignedDataWithSignature& signedData,
-                          Input subjectPublicKeyInfo) override
+  Result VerifySignedData(const SignedDataWithSignature&, Input) override
   {
     ADD_FAILURE();
     return Result::FATAL_ERROR_LIBRARY_FAILURE;
   }
 
   Result DigestBuf(Input, /*out*/uint8_t*, size_t) override
   {
     ADD_FAILURE();
@@ -458,17 +466,17 @@ public:
                       /*out*/ TrustLevel& trustLevel) override
   {
     trustLevel = endEntityOrCA == EndEntityOrCA::MustBeCA
                ? TrustLevel::TrustAnchor
                : TrustLevel::InheritsTrust;
     return Success;
   }
 
-  Result FindIssuer(Input subjectCert, IssuerChecker& checker, Time) override
+  Result FindIssuer(Input, IssuerChecker& checker, Time) override
   {
     Input issuerInput;
     EXPECT_EQ(Success, issuerInput.Init(issuer.data(), issuer.length()));
     bool keepGoing;
     EXPECT_EQ(Success,
               checker.Check(issuerInput, nullptr /*additionalNameConstraints*/,
                             keepGoing));
     EXPECT_EQ(expectedKeepGoing, keepGoing);
--- a/security/pkix/test/gtest/pkixcert_extension_tests.cpp
+++ b/security/pkix/test/gtest/pkixcert_extension_tests.cpp
@@ -58,17 +58,17 @@ CreateCertWithOneExtension(const char* s
 {
   const ByteString extensions[] = { extension, ByteString() };
   return CreateCertWithExtensions(subjectStr, extensions);
 }
 
 class TrustEverythingTrustDomain final : public TrustDomain
 {
 private:
-  Result GetCertTrust(EndEntityOrCA, const CertPolicyId&, Input candidateCert,
+  Result GetCertTrust(EndEntityOrCA, const CertPolicyId&, Input,
                       /*out*/ TrustLevel& trustLevel) override
   {
     trustLevel = TrustLevel::TrustAnchor;
     return Success;
   }
 
   Result FindIssuer(Input /*encodedIssuerName*/, IssuerChecker& /*checker*/,
                     Time /*time*/) override
--- a/security/pkix/test/gtest/pkixcheck_CheckKeyUsage_tests.cpp
+++ b/security/pkix/test/gtest/pkixcheck_CheckKeyUsage_tests.cpp
@@ -17,17 +17,17 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-#include "gtest/gtest.h"
+#include "pkixgtest.h"
 #include "pkix/pkixtypes.h"
 #include "pkixtestutil.h"
 
 using namespace mozilla::pkix;
 using namespace mozilla::pkix::test;
 
 namespace mozilla { namespace pkix {
 
--- a/security/pkix/test/gtest/pkixcheck_CheckValidity_tests.cpp
+++ b/security/pkix/test/gtest/pkixcheck_CheckValidity_tests.cpp
@@ -17,17 +17,17 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-#include "gtest/gtest.h"
+#include "pkixgtest.h"
 #include "pkix/pkixtypes.h"
 #include "pkixtestutil.h"
 
 using namespace mozilla::pkix;
 using namespace mozilla::pkix::test;
 
 namespace mozilla { namespace pkix {
 
--- a/security/pkix/test/gtest/pkixder_input_tests.cpp
+++ b/security/pkix/test/gtest/pkixder_input_tests.cpp
@@ -19,17 +19,17 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #include <functional>
 #include <vector>
-#include <gtest/gtest.h>
+#include "pkixgtest.h"
 
 #include "pkixder.h"
 
 using namespace mozilla::pkix;
 using namespace mozilla::pkix::der;
 
 namespace {
 
@@ -462,17 +462,17 @@ TEST_F(pkixder_input_tests, MarkAndGetIn
 
   Input item;
   ASSERT_EQ(Success, input.GetInput(mark, item));
   Input expected(expectedItemData);
   ASSERT_TRUE(InputsAreEqual(expected, item));
 }
 
 // Cannot run this test on debug builds because of the NotReached
-#ifndef DEBUG
+#ifdef NDEBUG
 TEST_F(pkixder_input_tests, MarkAndGetInputDifferentInput)
 {
   const uint8_t der[] = { 0x11, 0x22, 0x33, 0x44 };
   Input buf(der);
   Reader input(buf);
 
   Reader another;
   Reader::Mark mark = another.GetMark();
@@ -842,17 +842,17 @@ TEST_F(pkixder_input_tests, NestedOf)
   Reader input(buf);
 
   std::vector<uint8_t> readValues;
   ASSERT_EQ(Success,
             NestedOf(input, SEQUENCE, INTEGER, EmptyAllowed::No,
                      [&readValues](Reader& r) {
                        return NestedOfHelper(r, readValues);
                      }));
-  ASSERT_EQ((size_t) 3, readValues.size());
+  ASSERT_EQ(3u, readValues.size());
   ASSERT_EQ(0x01, readValues[0]);
   ASSERT_EQ(0x02, readValues[1]);
   ASSERT_EQ(0x03, readValues[2]);
   ASSERT_EQ(Success, End(input));
 }
 
 TEST_F(pkixder_input_tests, NestedOfWithTruncatedData)
 {
@@ -860,17 +860,17 @@ TEST_F(pkixder_input_tests, NestedOfWith
   Reader input(buf);
 
   std::vector<uint8_t> readValues;
   ASSERT_EQ(Result::ERROR_BAD_DER,
             NestedOf(input, SEQUENCE, INTEGER, EmptyAllowed::No,
                      [&readValues](Reader& r) {
                        return NestedOfHelper(r, readValues);
                      }));
-  ASSERT_EQ((size_t) 0, readValues.size());
+  ASSERT_EQ(0u, readValues.size());
 }
 
 TEST_F(pkixder_input_tests, MatchRestAtEnd)
 {
   static const uint8_t der[1] = { };
   Input buf;
   ASSERT_EQ(Success, buf.Init(der, 0));
   Reader input(buf);
--- a/security/pkix/test/gtest/pkixder_pki_types_tests.cpp
+++ b/security/pkix/test/gtest/pkixder_pki_types_tests.cpp
@@ -20,17 +20,17 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #include <functional>
 #include <vector>
 
-#include "gtest/gtest.h"
+#include "pkixgtest.h"
 #include "pkix/pkixtypes.h"
 #include "pkixder.h"
 
 using namespace mozilla::pkix;
 using namespace mozilla::pkix::der;
 
 namespace {
 
--- a/security/pkix/test/gtest/pkixder_universal_types_tests.cpp
+++ b/security/pkix/test/gtest/pkixder_universal_types_tests.cpp
@@ -19,17 +19,17 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #include <limits>
 #include <vector>
-#include <gtest/gtest.h>
+#include "pkixgtest.h"
 
 #include "pkixder.h"
 #include "pkixtestutil.h"
 #include "stdint.h"
 
 using namespace mozilla::pkix;
 using namespace mozilla::pkix::der;
 using namespace mozilla::pkix::test;
@@ -282,18 +282,19 @@ TEST_F(pkixder_universal_types_tests, En
 //   defined in Section 2.4.  The format for GeneralizedTime is as
 //   specified in Section 4.1.2.5.2 of [RFC5280].
 //
 // So while we can could accept other ASN1 (ITU-T X.680) encodings for
 // GeneralizedTime we should not accept them, and breaking reading of these
 // other encodings is actually encouraged.
 
 // e.g. TWO_CHARS(53) => '5', '3'
-#define TWO_CHARS(t) static_cast<uint8_t>('0' + ((t) / 10u)), \
-                     static_cast<uint8_t>('0' + ((t) % 10u))
+#define TWO_CHARS(t) \
+  static_cast<uint8_t>('0' + (static_cast<uint8_t>(t) / 10u)), \
+  static_cast<uint8_t>('0' + (static_cast<uint8_t>(t) % 10u))
 
 // Calls TimeChoice on the UTCTime variant of the given generalized time.
 template <uint16_t LENGTH>
 Result
 TimeChoiceForEquivalentUTCTime(const uint8_t (&generalizedTimeDER)[LENGTH],
                                /*out*/ Time& value)
 {
   static_assert(LENGTH >= 4,
@@ -550,17 +551,17 @@ static const uint8_t DAYS_IN_MONTH[] = {
   30, // September
   31, // October
   30, // November
   31, // December
 };
 
 TEST_F(pkixder_universal_types_tests, TimeMonthDaysValidRange)
 {
-  for (uint8_t month = 1; month <= 12; ++month) {
+  for (uint16_t month = 1; month <= 12; ++month) {
     for (uint8_t day = 1; day <= DAYS_IN_MONTH[month]; ++day) {
       const uint8_t DER[] = {
         0x18,                           // Generalized Time
         15,                             // Length = 15
         '2', '0', '1', '5', TWO_CHARS(month), TWO_CHARS(day), // (2015-mm-dd)
         '1', '6', '4', '5', '4', '0', 'Z' // 16:45:40
       };
       ExpectGoodTime(YMDHMS(2015, month, day, 16, 45, 40), DER);
@@ -599,17 +600,17 @@ TEST_F(pkixder_universal_types_tests, Ti
     '2', '0', '1', '5', '0', '1', '0', '0', // 2015-01-!!!00!!!
     '1', '6', '4', '5', '4', '0', 'Z' // 16:45:40
   };
   ExpectBadTime(DER);
 }
 
 TEST_F(pkixder_universal_types_tests, TimeMonthDayInvalidPastEndOfMonth)
 {
-  for (uint8_t month = 1; month <= 12; ++month) {
+  for (int16_t month = 1; month <= 12; ++month) {
     const uint8_t DER[] = {
       0x18,                           // Generalized Time
       15,                             // Length = 15
       '1', '9', '9', '1', // YYYY 1991
       TWO_CHARS(month), // MM
       TWO_CHARS(1 + (month == 2 ? 29 : DAYS_IN_MONTH[month])), // !!!DD!!!
       '1', '6', '4', '5', '4', '0', 'Z' // 16:45:40
     };
@@ -900,17 +901,17 @@ TEST_F(pkixder_universal_types_tests, In
     const uint8_t DER[] = {
       0x02, // INTEGER
       0x01, // length
       i,    // value
     };
     Input input(DER);
     Reader reader(input);
 
-    uint8_t value = i + 1; // initialize with a value that is NOT i.
+    uint8_t value = i + 1u; // initialize with a value that is NOT i.
     ASSERT_EQ(Success, Integer(reader, value));
     ASSERT_EQ(i, value);
   }
 }
 
 TEST_F(pkixder_universal_types_tests, Integer_Negative1)
 {
   // This is a valid integer value but our integer parser cannot parse
--- a/security/pkix/test/gtest/pkixgtest.cpp
+++ b/security/pkix/test/gtest/pkixgtest.cpp
@@ -25,15 +25,20 @@
 #include "pkixgtest.h"
 
 #include <ctime>
 
 #include "pkix/Time.h"
 
 namespace mozilla { namespace pkix { namespace test {
 
+const std::time_t ONE_DAY_IN_SECONDS_AS_TIME_T =
+  static_cast<std::time_t>(Time::ONE_DAY_IN_SECONDS);
+
 // This assumes that time/time_t are POSIX-compliant in that time() returns
 // the number of seconds since the Unix epoch.
 const std::time_t now(time(nullptr));
-const std::time_t oneDayBeforeNow(time(nullptr) - Time::ONE_DAY_IN_SECONDS);
-const std::time_t oneDayAfterNow(time(nullptr) + Time::ONE_DAY_IN_SECONDS);
+const std::time_t oneDayBeforeNow(time(nullptr) -
+                                  ONE_DAY_IN_SECONDS_AS_TIME_T);
+const std::time_t oneDayAfterNow(time(nullptr) +
+                                 ONE_DAY_IN_SECONDS_AS_TIME_T);
 
 } } } // namespace mozilla::pkix::test
--- a/security/pkix/test/gtest/pkixgtest.h
+++ b/security/pkix/test/gtest/pkixgtest.h
@@ -21,17 +21,46 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 #ifndef mozilla_pkix_pkixgtest_h
 #define mozilla_pkix_pkixgtest_h
 
 #include <ostream>
 
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated"
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+#pragma clang diagnostic ignored "-Wshift-sign-overflow"
+#pragma clang diagnostic ignored "-Wsign-conversion"
+#pragma clang diagnostic ignored "-Wundef"
+#elif defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wextra"
+#elif defined(_MSC_VER)
+#pragma warning(push, 3)
+// C4224: Nonstandard extension used: formal parameter 'X' was previously
+//        defined as a type.
+#pragma warning(disable: 4224)
+// C4826: Conversion from 'type1 ' to 'type_2' is sign - extended. This may
+//        cause unexpected runtime behavior.
+#pragma warning(disable: 4826)
+#endif
+
 #include "gtest/gtest.h"
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#elif defined(__GNUC__)
+#pragma GCC diagnostic pop
+#elif defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
 #include "pkix/Result.h"
 
 // PrintTo must be in the same namespace as the type we're overloading it for.
 namespace mozilla { namespace pkix {
 
 inline void
 PrintTo(const Result& result, ::std::ostream* os)
 {
@@ -42,15 +71,17 @@ PrintTo(const Result& result, ::std::ost
     *os << "mozilla::pkix::Result(" << static_cast<unsigned int>(result) << ")";
   }
 }
 
 } } // namespace mozilla::pkix
 
 namespace mozilla { namespace pkix { namespace test {
 
+extern const std::time_t ONE_DAY_IN_SECONDS_AS_TIME_T;
+
 extern const std::time_t now;
 extern const std::time_t oneDayBeforeNow;
 extern const std::time_t oneDayAfterNow;
 
 } } } // namespace mozilla::pkix::test
 
 #endif // mozilla_pkix_pkixgtest_h
--- a/security/pkix/test/gtest/pkixnames_tests.cpp
+++ b/security/pkix/test/gtest/pkixnames_tests.cpp
@@ -67,17 +67,18 @@ struct PresentedMatchesReference
     Success, \
     false \
   }
 
 #define DNS_ID_BAD_DER(a, b) \
   { \
     ByteString(reinterpret_cast<const uint8_t*>(a), sizeof(a) - 1), \
     ByteString(reinterpret_cast<const uint8_t*>(b), sizeof(b) - 1), \
-    Result::ERROR_BAD_DER \
+    Result::ERROR_BAD_DER, \
+    false \
   }
 
 static const PresentedMatchesReference DNSID_MATCH_PARAMS[] =
 {
   DNS_ID_BAD_DER("", "a"),
 
   DNS_ID_MATCH("a", "a"),
   DNS_ID_MISMATCH("b", "a"),
--- a/security/pkix/test/gtest/pkixocsp_CreateEncodedOCSPRequest_tests.cpp
+++ b/security/pkix/test/gtest/pkixocsp_CreateEncodedOCSPRequest_tests.cpp
@@ -17,17 +17,17 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-#include "gtest/gtest.h"
+#include "pkixgtest.h"
 #include "pkix/pkix.h"
 #include "pkixder.h"
 #include "pkixtestutil.h"
 
 using namespace mozilla::pkix;
 using namespace mozilla::pkix::test;
 
 class CreateEncodedOCSPRequestTrustDomain final : public TrustDomain
@@ -66,17 +66,17 @@ private:
   }
 
   Result DigestBuf(Input item, /*out*/ uint8_t *digestBuf, size_t digestBufLen)
                    override
   {
     return TestDigestBuf(item, digestBuf, digestBufLen);
   }
 
-  Result CheckPublicKey(Input subjectPublicKeyInfo) override
+  Result CheckPublicKey(Input) override
   {
     ADD_FAILURE();
     return Result::FATAL_ERROR_LIBRARY_FAILURE;
   }
 };
 
 class pkixocsp_CreateEncodedOCSPRequest : public ::testing::Test
 {
--- a/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp
+++ b/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp
@@ -48,17 +48,17 @@ public:
   }
 
   Result FindIssuer(Input, IssuerChecker&, Time) final override
   {
     ADD_FAILURE();
     return Result::FATAL_ERROR_LIBRARY_FAILURE;
   }
 
-  Result CheckRevocation(EndEntityOrCA endEntityOrCA, const CertID&, Time time,
+  Result CheckRevocation(EndEntityOrCA, const CertID&, Time,
                          /*optional*/ const Input*, /*optional*/ const Input*)
                          final override
   {
     // TODO: I guess mozilla::pkix should support revocation of designated
     // OCSP responder eventually, but we don't now, so this function should
     // never get called.
     ADD_FAILURE();
     return Result::FATAL_ERROR_LIBRARY_FAILURE;
@@ -114,17 +114,18 @@ public:
       abort();
     }
     Input rootNameDERInput;
     if (rootNameDERInput.Init(rootNameDER.data(), rootNameDER.length())
           != Success) {
       abort();
     }
 
-    serialNumberDER = CreateEncodedSerialNumber(++rootIssuedCount);
+    serialNumberDER =
+      CreateEncodedSerialNumber(static_cast<long>(++rootIssuedCount));
     if (ENCODING_FAILED(serialNumberDER)) {
       abort();
     }
     Input serialNumberDERInput;
     if (serialNumberDERInput.Init(serialNumberDER.data(),
                                   serialNumberDER.length()) != Success) {
       abort();
     }
@@ -138,28 +139,28 @@ public:
     endEntityCertID = new (std::nothrow) CertID(rootNameDERInput, rootSPKIDER,
                                                 serialNumberDERInput);
     if (!endEntityCertID) {
       abort();
     }
   }
 
   static ScopedTestKeyPair rootKeyPair;
-  static long rootIssuedCount;
+  static uint32_t rootIssuedCount;
   OCSPTestTrustDomain trustDomain;
 
   // endEntityCertID references rootKeyPair, rootNameDER, and serialNumberDER.
   ByteString rootNameDER;
   ByteString serialNumberDER;
   // endEntityCertID references rootKeyPair, rootNameDER, and serialNumberDER.
   ScopedPtr<CertID, deleteCertID> endEntityCertID;
 };
 
 /*static*/ ScopedTestKeyPair pkixocsp_VerifyEncodedResponse::rootKeyPair;
-/*static*/ long pkixocsp_VerifyEncodedResponse::rootIssuedCount = 0;
+/*static*/ uint32_t pkixocsp_VerifyEncodedResponse::rootIssuedCount = 0;
 
 ///////////////////////////////////////////////////////////////////////////////
 // responseStatus
 
 struct WithoutResponseBytes
 {
   uint8_t responseStatus;
   Result expectedError;
@@ -253,17 +254,17 @@ public:
     }
     context.signerKeyPair = signerKeyPair.Clone();
     EXPECT_TRUE(context.signerKeyPair);
     context.responseStatus = OCSPResponseContext::successful;
     context.producedAt = producedAt;
     context.signatureAlgorithm = signatureAlgorithm;
     context.certs = certs;
 
-    context.certStatus = certStatus;
+    context.certStatus = static_cast<uint8_t>(certStatus);
     context.thisUpdate = thisUpdate;
     context.nextUpdate = nextUpdate ? *nextUpdate : 0;
     context.includeNextUpdate = nextUpdate != nullptr;
 
     return CreateEncodedOCSPResponse(context);
   }
 };
 
@@ -403,17 +404,18 @@ TEST_F(pkixocsp_VerifyEncodedResponse_su
     ASSERT_EQ(Success,
               VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
                                         Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS,
                                         response, expired, nullptr,
                                         &validThrough));
     ASSERT_FALSE(expired);
     // The response was created to be valid until one day after now, so the
     // value we got for validThrough should be after that.
-    Time oneDayAfterNowAsPKIXTime(TimeFromEpochInSeconds(oneDayAfterNow));
+    Time oneDayAfterNowAsPKIXTime(
+          TimeFromEpochInSeconds(static_cast<uint64_t>(oneDayAfterNow)));
     ASSERT_TRUE(validThrough > oneDayAfterNowAsPKIXTime);
   }
   {
     Input response;
     ASSERT_EQ(Success,
               response.Init(responseString.data(), responseString.length()));
     bool expired;
     // Given validThrough from a previous verification, this response should be
@@ -513,17 +515,18 @@ protected:
                                              const char* issuer,
                                              time_t notBefore,
                                              time_t notAfter,
                                              const char* subject,
                                              const TestKeyPair& subjectKeyPair,
                                 /*optional*/ const ByteString* extensions,
                                              const TestKeyPair& signerKeyPair)
   {
-    ByteString serialNumberDER(CreateEncodedSerialNumber(serialNumber));
+    ByteString serialNumberDER(CreateEncodedSerialNumber(
+                                 static_cast<long>(serialNumber)));
     if (ENCODING_FAILED(serialNumberDER)) {
       return ByteString();
     }
     ByteString issuerDER(CNToDERName(issuer));
     if (ENCODING_FAILED(issuerDER)) {
       return ByteString();
     }
     ByteString subjectDER(CNToDERName(subject));
@@ -629,18 +632,18 @@ TEST_F(pkixocsp_VerifyEncodedResponse_De
   const ByteString extensions[] = {
     CreateEncodedEKUExtension(OCSPSigningEKUDER, Critical::No),
     ByteString()
   };
 
   ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
   ByteString signerDER(CreateEncodedCertificate(
                           ++rootIssuedCount, sha256WithRSAEncryption, rootName,
-                          now - (10 * Time::ONE_DAY_IN_SECONDS),
-                          now - (2 * Time::ONE_DAY_IN_SECONDS),
+                          now - (10 * ONE_DAY_IN_SECONDS_AS_TIME_T),
+                          now - (2 * ONE_DAY_IN_SECONDS_AS_TIME_T),
                           signerName, *signerKeyPair, extensions,
                           *rootKeyPair));
   ASSERT_FALSE(ENCODING_FAILED(signerDER));
 
   ByteString certs[] = { signerDER, ByteString() };
   ByteString responseString(
                CreateEncodedOCSPSuccessfulResponse(
                          OCSPResponseContext::good, *endEntityCertID,
@@ -665,18 +668,18 @@ TEST_F(pkixocsp_VerifyEncodedResponse_De
     CreateEncodedEKUExtension(OCSPSigningEKUDER, Critical::No),
     ByteString()
   };
 
   ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
   ByteString signerDER(CreateEncodedCertificate(
                          ++rootIssuedCount, sha256WithRSAEncryption,
                          rootName,
-                         now + (2 * Time::ONE_DAY_IN_SECONDS),
-                         now + (10 * Time::ONE_DAY_IN_SECONDS),
+                         now + (2 * ONE_DAY_IN_SECONDS_AS_TIME_T),
+                         now + (10 * ONE_DAY_IN_SECONDS_AS_TIME_T),
                          signerName, *signerKeyPair, extensions,
                          *rootKeyPair));
   ASSERT_FALSE(ENCODING_FAILED(signerDER));
 
   ByteString certs[] = { signerDER, ByteString() };
   ByteString responseString(
                CreateEncodedOCSPSuccessfulResponse(
                          OCSPResponseContext::good, *endEntityCertID,
@@ -1012,18 +1015,19 @@ TEST_F(pkixocsp_VerifyEncodedResponse_Ge
                                       response, expired));
   ASSERT_FALSE(expired);
 }
 
 TEST_F(pkixocsp_VerifyEncodedResponse_GetCertTrust, ActivelyDistrusted)
 {
   ASSERT_TRUE(trustDomain.SetCertTrust(signerCertDER,
                                        TrustLevel::ActivelyDistrusted));
-  Input response;
+  Input responseInput;
   ASSERT_EQ(Success,
-            response.Init(responseString.data(), responseString.length()));
+            responseInput.Init(responseString.data(),
+                               responseString.length()));
   bool expired;
   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
-                                      response, expired));
+                                      responseInput, expired));
   ASSERT_FALSE(expired);
 }
--- a/security/pkix/test/lib/pkixtestnss.cpp
+++ b/security/pkix/test/lib/pkixtestnss.cpp
@@ -110,17 +110,18 @@ public:
     signatureAlgorithmID.parameters.len = 0;
     SECOidTag signatureAlgorithmOidTag =
       SECOID_GetAlgorithmTag(&signatureAlgorithmID);
     if (signatureAlgorithmOidTag == SEC_OID_UNKNOWN) {
       return Result::FATAL_ERROR_INVALID_ARGS;
     }
 
     SECItem signatureItem;
-    if (SEC_SignData(&signatureItem, tbs.data(), tbs.length(),
+    if (SEC_SignData(&signatureItem, tbs.data(),
+                     static_cast<int>(tbs.length()),
                      privateKey.get(), signatureAlgorithmOidTag)
           != SECSuccess) {
       return MapPRErrorCodeToResult(PR_GetError());
     }
     signature.assign(signatureItem.data, signatureItem.len);
     SECITEM_FreeItem(&signatureItem, false);
     return Success;
   }
--- a/security/pkix/test/lib/pkixtestutil.cpp
+++ b/security/pkix/test/lib/pkixtestutil.cpp
@@ -122,20 +122,20 @@ TamperOnce(/*in/out*/ ByteString& item, 
 // Given a tag and a value, generates a DER-encoded tag-length-value item.
 ByteString
 TLV(uint8_t tag, const ByteString& value)
 {
   ByteString result;
   result.push_back(tag);
 
   if (value.length() < 128) {
-    result.push_back(value.length());
+    result.push_back(static_cast<uint8_t>(value.length()));
   } else if (value.length() < 256) {
     result.push_back(0x81u);
-    result.push_back(value.length());
+    result.push_back(static_cast<uint8_t>(value.length()));
   } else if (value.length() < 65536) {
     result.push_back(0x82u);
     result.push_back(static_cast<uint8_t>(value.length() / 256));
     result.push_back(static_cast<uint8_t>(value.length() % 256));
   } else {
     // It is MUCH more convenient for TLV to be infallible than for it to have
     // "proper" error handling.
     abort();
@@ -153,17 +153,17 @@ OCSPResponseContext::OCSPResponseContext
   , includeEmptyExtensions(false)
   , signatureAlgorithm(sha256WithRSAEncryption)
   , badSignature(false)
   , certs(nullptr)
 
   , certStatus(good)
   , revocationTime(0)
   , thisUpdate(time)
-  , nextUpdate(time + Time::ONE_DAY_IN_SECONDS)
+  , nextUpdate(time + static_cast<time_t>(Time::ONE_DAY_IN_SECONDS))
   , includeNextUpdate(true)
 {
 }
 
 static ByteString ResponseBytes(OCSPResponseContext& context);
 static ByteString BasicOCSPResponse(OCSPResponseContext& context);
 static ByteString ResponseData(OCSPResponseContext& context);
 static ByteString ResponderID(OCSPResponseContext& context);
@@ -197,17 +197,17 @@ BitString(const ByteString& rawBytes, bo
   }
   return TLV(der::BIT_STRING, prefixed);
 }
 
 ByteString
 Boolean(bool value)
 {
   ByteString encodedValue;
-  encodedValue.push_back(value ? 0xff : 0x00);
+  encodedValue.push_back(value ? 0xffu : 0x00u);
   return TLV(der::BOOLEAN, encodedValue);
 }
 
 ByteString
 Integer(long value)
 {
   if (value < 0 || value > 127) {
     // TODO: add encoding of larger values
@@ -261,32 +261,32 @@ TimeToEncodedTime(time_t time, TimeEncod
 
   if (encoding == UTCTime && (year < 1950 || year >= 2050)) {
     return ByteString();
   }
 
   ByteString value;
 
   if (encoding == GeneralizedTime) {
-    value.push_back('0' + (year / 1000));
-    value.push_back('0' + ((year % 1000) / 100));
+    value.push_back(static_cast<uint8_t>('0' + (year / 1000)));
+    value.push_back(static_cast<uint8_t>('0' + ((year % 1000) / 100)));
   }
 
-  value.push_back('0' + ((year % 100) / 10));
-  value.push_back('0' + (year % 10));
-  value.push_back('0' + ((exploded.tm_mon + 1) / 10));
-  value.push_back('0' + ((exploded.tm_mon + 1) % 10));
-  value.push_back('0' + (exploded.tm_mday / 10));
-  value.push_back('0' + (exploded.tm_mday % 10));
-  value.push_back('0' + (exploded.tm_hour / 10));
-  value.push_back('0' + (exploded.tm_hour % 10));
-  value.push_back('0' + (exploded.tm_min / 10));
-  value.push_back('0' + (exploded.tm_min % 10));
-  value.push_back('0' + (exploded.tm_sec / 10));
-  value.push_back('0' + (exploded.tm_sec % 10));
+  value.push_back(static_cast<uint8_t>('0' + ((year % 100) / 10)));
+  value.push_back(static_cast<uint8_t>('0' + (year % 10)));
+  value.push_back(static_cast<uint8_t>('0' + ((exploded.tm_mon + 1) / 10)));
+  value.push_back(static_cast<uint8_t>('0' + ((exploded.tm_mon + 1) % 10)));
+  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_mday / 10)));
+  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_mday % 10)));
+  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_hour / 10)));
+  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_hour % 10)));
+  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_min / 10)));
+  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_min % 10)));
+  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_sec / 10)));
+  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_sec % 10)));
   value.push_back('Z');
 
   return TLV(encoding == GeneralizedTime ? der::GENERALIZED_TIME : der::UTCTime,
              value);
 }
 
 static ByteString
 TimeToGeneralizedTime(time_t time)
@@ -310,28 +310,25 @@ TimeToTimeChoice(time_t time)
                            exploded.tm_year + 1900 < 2050)
                         ? UTCTime
                         : GeneralizedTime;
 
   return TimeToEncodedTime(time, encoding);
 }
 
 Time
-YMDHMS(int16_t year, int16_t month, int16_t day,
-       int16_t hour, int16_t minutes, int16_t seconds)
+YMDHMS(uint16_t year, uint16_t month, uint16_t day,
+       uint16_t hour, uint16_t minutes, uint16_t seconds)
 {
   assert(year <= 9999);
   assert(month >= 1);
   assert(month <= 12);
   assert(day >= 1);
-  assert(hour >= 0);
   assert(hour < 24);
-  assert(minutes >= 0);
   assert(minutes < 60);
-  assert(seconds >= 0);
   assert(seconds < 60);
 
   uint64_t days = DaysBeforeYear(year);
 
   {
     static const int16_t DAYS_IN_MONTH[] = {
       31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
     };
@@ -434,26 +431,51 @@ EmptyExtension(Input extnID, Critical cr
     encoded.append(Boolean(true));
   }
 
   ByteString extnValue(TLV(der::OCTET_STRING, ByteString()));
   encoded.append(extnValue);
   return TLV(der::SEQUENCE, encoded);
 }
 
+std::string
+GetEnv(const char* name)
+{
+  std::string result;
+
+#ifndef _MSC_VER
+  // XXX: Not thread safe.
+  const char* value = getenv(name);
+  if (value) {
+    result = value;
+  }
+#else
+  char* value = nullptr;
+  size_t valueLength = 0;
+  if (_dupenv_s(&value, &valueLength, name) != 0) {
+    abort();
+  }
+  if (value) {
+    result = value;
+    free(value);
+  }
+#endif
+  return result;
+}
+
 void
 MaybeLogOutput(const ByteString& result, const char* suffix)
 {
   assert(suffix);
 
   // This allows us to more easily debug the generated output, by creating a
   // file in the directory given by MOZILLA_PKIX_TEST_LOG_DIR for each
   // NOT THREAD-SAFE!!!
-  const char* logPath = getenv("MOZILLA_PKIX_TEST_LOG_DIR");
-  if (logPath) {
+  std::string logPath(GetEnv("MOZILLA_PKIX_TEST_LOG_DIR"));
+  if (!logPath.empty()) {
     static int counter = 0;
 
     std::ostringstream counterStream;
     counterStream << counter;
     if (!counterStream) {
       assert(false);
       return;
     }
@@ -824,17 +846,17 @@ BasicOCSPResponse(OCSPResponseContext& c
 }
 
 // Extension ::= SEQUENCE {
 //   id               OBJECT IDENTIFIER,
 //   critical         BOOLEAN DEFAULT FALSE
 //   value            OCTET STRING
 // }
 static ByteString
-OCSPExtension(OCSPResponseContext& context, OCSPResponseExtension& extension)
+OCSPExtension(OCSPResponseExtension& extension)
 {
   ByteString encoded;
   encoded.append(extension.id);
   if (extension.critical) {
     encoded.append(Boolean(true));
   }
   ByteString value(TLV(der::OCTET_STRING, extension.value));
   encoded.append(value);
@@ -845,17 +867,17 @@ OCSPExtension(OCSPResponseContext& conte
 //   SEQUENCE OF Extension
 // }
 static ByteString
 Extensions(OCSPResponseContext& context)
 {
   ByteString value;
   for (OCSPResponseExtension* extension = context.extensions;
        extension; extension = extension->next) {
-    ByteString extensionEncoded(OCSPExtension(context, *extension));
+    ByteString extensionEncoded(OCSPExtension(*extension));
     if (ENCODING_FAILED(extensionEncoded)) {
       return ByteString();
     }
     value.append(extensionEncoded);
   }
   ByteString sequence(TLV(der::SEQUENCE, value));
   return TLV(der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 1, sequence);
 }
@@ -910,18 +932,21 @@ ResponderID(OCSPResponseContext& context
   } else {
     contents = KeyHash(context.signerKeyPair->subjectPublicKey);
     if (ENCODING_FAILED(contents)) {
       return ByteString();
     }
     responderIDType = 2; // byKey
   }
 
-  return TLV(der::CONSTRUCTED | der::CONTEXT_SPECIFIC | responderIDType,
-             contents);
+  // XXX: MSVC 2015 wrongly warns about signed/unsigned conversion without the
+  // static_cast.
+  uint8_t tag = static_cast<uint8_t>(der::CONSTRUCTED | der::CONTEXT_SPECIFIC |
+                                     responderIDType);
+  return TLV(tag, contents);
 }
 
 // KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
 //                          -- (i.e., the SHA-1 hash of the value of the
 //                          -- BIT STRING subjectPublicKey [excluding
 //                          -- the tag, length, and number of unused
 //                          -- bits] in the responder's certificate)
 ByteString
@@ -1042,17 +1067,20 @@ ByteString
 CertStatus(OCSPResponseContext& context)
 {
   switch (context.certStatus) {
     // Both good and unknown are ultimately represented as NULL - the only
     // difference is in the tag that identifies them.
     case 0:
     case 2:
     {
-      return TLV(der::CONTEXT_SPECIFIC | context.certStatus, ByteString());
+      // XXX: MSVC 2015 wrongly warns about signed/unsigned conversion without
+      // the static cast.
+      return TLV(static_cast<uint8_t>(der::CONTEXT_SPECIFIC |
+                                      context.certStatus), ByteString());
     }
     case 1:
     {
       ByteString revocationTime(TimeToGeneralizedTime(context.revocationTime));
       if (ENCODING_FAILED(revocationTime)) {
         return ByteString();
       }
       // TODO(bug 980536): add support for revocationReason
--- a/security/pkix/test/lib/pkixtestutil.h
+++ b/security/pkix/test/lib/pkixtestutil.h
@@ -88,22 +88,18 @@ const ByteString md5WithRSAEncryption(al
 const uint8_t alg_md2WithRSAEncryption[] = {
   0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02
 };
 
 const ByteString md2WithRSAEncryption(alg_md2WithRSAEncryption,
   MOZILLA_PKIX_ARRAY_LENGTH(alg_md2WithRSAEncryption));
 
 // e.g. YMDHMS(2016, 12, 31, 1, 23, 45) => 2016-12-31:01:23:45 (GMT)
-mozilla::pkix::Time YMDHMS(int16_t year, int16_t month, int16_t day,
-                           int16_t hour, int16_t minutes, int16_t seconds);
-
-// e.g. YMDHMS(2016, 12, 31, 1, 23, 45) => 2016-12-31:01:23:45 (GMT)
-mozilla::pkix::Time YMDHMS(int16_t year, int16_t month, int16_t day,
-                           int16_t hour, int16_t minutes, int16_t seconds);
+mozilla::pkix::Time YMDHMS(uint16_t year, uint16_t month, uint16_t day,
+                           uint16_t hour, uint16_t minutes, uint16_t seconds);
 
 ByteString TLV(uint8_t tag, const ByteString& value);
 ByteString Boolean(bool value);
 ByteString Integer(long value);
 
 ByteString CN(const ByteString&, uint8_t encodingTag = 0x0c /*UTF8String*/);
 
 inline ByteString
@@ -163,32 +159,32 @@ RFC822Name(const ByteString& name)
   // (2 << 6) means "context-specific", 1 is the GeneralName tag.
   return TLV((2 << 6) | 1, name);
 }
 
 template <size_t L>
 inline ByteString
 RFC822Name(const char (&bytes)[L])
 {
-  return RFC822Name(ByteString(reinterpret_cast<const uint8_t (&)[L]>(bytes),
+  return RFC822Name(ByteString(reinterpret_cast<const uint8_t*>(&bytes),
                                L - 1));
 }
 
 inline ByteString
 DNSName(const ByteString& name)
 {
   // (2 << 6) means "context-specific", 2 is the GeneralName tag.
   return TLV((2 << 6) | 2, name);
 }
 
 template <size_t L>
 inline ByteString
 DNSName(const char (&bytes)[L])
 {
-  return DNSName(ByteString(reinterpret_cast<const uint8_t (&)[L]>(bytes),
+  return DNSName(ByteString(reinterpret_cast<const uint8_t*>(&bytes),
                             L - 1));
 }
 
 inline ByteString
 IPAddress()
 {
   // (2 << 6) means "context-specific", 7 is the GeneralName tag.
   return TLV((2 << 6) | 7, ByteString());
new file mode 100644
--- /dev/null
+++ b/security/pkix/warnings.mozbuild
@@ -0,0 +1,43 @@
+FAIL_ON_WARNINGS = True
+
+if CONFIG['CLANG_CXX']:
+  CXXFLAGS += [
+    '-Weverything',
+
+    '-Wno-c++98-compat',
+    '-Wno-c++98-compat-pedantic',
+    '-Wno-missing-prototypes',
+    '-Wno-missing-variable-declarations',
+    '-Wno-padded',
+    '-Wno-reserved-id-macro', # XXX: Will be removed in bug 1128413, Part 4.
+    '-Wno-shadow', # XXX: Clang's rules are too strict for constructors.
+    '-Wno-undef', # XXX: Will be removed in bug 1128413, Part 4.
+    '-Wno-weak-vtables', # We rely on the linker to merge the duplicate vtables.
+  ]
+elif CONFIG['_MSC_VER']:
+  CXXFLAGS += [
+    '-sdl', # Enable additional security checks based on Microsoft's SDL.
+
+    '-Wall',
+
+    '-wd4514', # 'function': unreferenced inline function has been removed
+    '-wd4668', # warning C4668: 'X' is not defined as a preprocessor macro,
+               # replacing with '0' for '#if/#elif'.
+    '-wd4710', # 'function': function not inlined
+    '-wd4711', # function 'function' selected for inline expansion
+    '-wd4800', # forcing value to bool 'true' or 'false'
+    '-wd4820', # 'bytes' bytes padding added after construct 'member_name'
+
+    # XXX: We cannot use /Za (Disable Microsoft Extensions) because windows.h
+    # won't copmile with it.
+    '-Zc:forScope', # Standard C++ rules for variable scope in for loops.
+    '-Zc:inline', # Standard C++ rules requiring definition inline functions.
+    '-Zc:rvalueCast', # Standard C++ rules for result of cast being an rvalue.
+    '-Zc:strictStrings', # Standard C++ rule that string literals are const.
+  ]
+else:
+  CXXFLAGS += [
+    '-Wall',
+    '-Wextra',
+    '-pedantic-errors',
+  ]