Merge mozilla-central to autoland a=merge on a CLOSED TREE
authorCoroiu Cristina <ccoroiu@mozilla.com>
Tue, 12 Jun 2018 12:24:54 +0300
changeset 479063 937e4ecdc133d6d7ff859174c0ec85a680ddc66c
parent 479062 fc4a67d2aea5879d93232c5639e6d806c9c923f8 (current diff)
parent 479052 87b46cd1c941782b75fcaa6b311bd9d7bd7f2120 (diff)
child 479064 671bf6da80a5ab0836feacee2100aa81614833a7
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone62.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
Merge mozilla-central to autoland a=merge on a CLOSED TREE
security/nss/lib/ckfw/nssmkey/Makefile
security/nss/lib/ckfw/nssmkey/README
security/nss/lib/ckfw/nssmkey/ckmk.h
security/nss/lib/ckfw/nssmkey/ckmkver.c
security/nss/lib/ckfw/nssmkey/config.mk
security/nss/lib/ckfw/nssmkey/manchor.c
security/nss/lib/ckfw/nssmkey/manifest.mn
security/nss/lib/ckfw/nssmkey/mconstants.c
security/nss/lib/ckfw/nssmkey/mfind.c
security/nss/lib/ckfw/nssmkey/minst.c
security/nss/lib/ckfw/nssmkey/mobject.c
security/nss/lib/ckfw/nssmkey/mrsa.c
security/nss/lib/ckfw/nssmkey/msession.c
security/nss/lib/ckfw/nssmkey/mslot.c
security/nss/lib/ckfw/nssmkey/mtoken.c
security/nss/lib/ckfw/nssmkey/nssmkey.def
security/nss/lib/ckfw/nssmkey/nssmkey.h
security/nss/lib/ckfw/nssmkey/staticobj.c
third_party/rust/debug_unreachable/.cargo-checksum.json
third_party/rust/debug_unreachable/.travis.yml
third_party/rust/debug_unreachable/Cargo.toml
third_party/rust/debug_unreachable/README.md
third_party/rust/debug_unreachable/examples/simple.rs
third_party/rust/debug_unreachable/src/lib.rs
third_party/rust/debug_unreachable/tests/check.rs
third_party/rust/ordered-float/.cargo-checksum.json
third_party/rust/ordered-float/.travis.yml
third_party/rust/ordered-float/Cargo.toml
third_party/rust/ordered-float/README.md
third_party/rust/ordered-float/src/lib.rs
third_party/rust/ordered-float/tests/test.rs
third_party/rust/unreachable-0.1.1/.cargo-checksum.json
third_party/rust/unreachable-0.1.1/.travis.yml
third_party/rust/unreachable-0.1.1/Cargo.toml
third_party/rust/unreachable-0.1.1/README.md
third_party/rust/unreachable-0.1.1/src/lib.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -554,24 +554,16 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "darling_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "debug_unreachable"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "diff"
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "docopt"
 version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1010,17 +1002,17 @@ dependencies = [
  "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "lalrpop-snap 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lalrpop-util 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "petgraph 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.58 (git+https://github.com/servo/serde?branch=deserialize_from_enums7)",
- "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "lalrpop-intern"
 version = "0.15.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1036,17 +1028,17 @@ dependencies = [
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "ena 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lalrpop-util 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "petgraph 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "lalrpop-util"
 version = "0.15.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1359,16 +1351,33 @@ dependencies = [
 name = "netwerk_helper"
 version = "0.0.1"
 dependencies = [
  "nserror 0.1.0",
  "nsstring 0.1.0",
 ]
 
 [[package]]
+name = "new-ordered-float"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "new_debug_unreachable"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "nodrop"
 version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "nom"
 version = "1.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1438,25 +1447,16 @@ source = "registry+https://github.com/ru
 name = "num_cpus"
 version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "ordered-float"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "ordermap"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "owning_ref"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1859,21 +1859,21 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "stable_deref_trait"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "string_cache"
-version = "0.7.1"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1904,34 +1904,34 @@ dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bindgen 0.33.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.23.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fallible 0.0.1",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.0.1",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "new-ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "nsstring 0.1.0",
  "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
  "smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2213,24 +2213,16 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "unicode-xid"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "unreachable"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "unreachable"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "url"
@@ -2548,17 +2540,16 @@ dependencies = [
 "checksum cstr-macros 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f9f316203d1ea36f4f18316822806f6999aa3dc5ed1adf51e35b77e3b3933d78"
 "checksum cubeb 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a3502aafa1bf95c524f65d2ba46d8741700c6a8a9543ea52c6da3d8b69a2896"
 "checksum cubeb-backend 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcac95519416d9ec814db2dc40e6293e7da25b906023d93f48b87f0587ab138"
 "checksum cubeb-core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37f7b20f757a4e4b6aa28863236551bff77682dc6db192eba15af615492b5445"
 "checksum cubeb-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "653b9e245d35dbe2a2da7c4586275cee75ff656ddeb02d4a73b4afdfa6d67502"
 "checksum darling 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3effd06d4057f275cb7858889f4952920bab78dd8ff0f6e7dfe0c8d2e67ed89"
 "checksum darling_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "167dd3e235c2f1da16a635c282630452cdf49191eb05711de1bcd1d3d5068c00"
 "checksum darling_macro 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c53edaba455f6073a10c27c72440860eb3f60444f8c8660a391032eeae744d82"
-"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
 "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
 "checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "068d4026697c1a18f0b0bb8cfcad1b0c151b90d8edb9bf4c235ad68128920d1d"
 "checksum dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b26e30aaa6bf31ec830db15fec14ed04f0f2ecfcc486ecfce88c55d3389b237f"
 "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
 "checksum ena 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe5a5078ac8c506d3e4430763b1ba9b609b1286913e7d08e581d1c2de9b7e5"
 "checksum encoding_c 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "769ecb8b33323998e482b218c0d13cd64c267609023b4b7ec3ee740714c318ee"
@@ -2618,25 +2609,26 @@ dependencies = [
 "checksum miniz_oxide_c_api 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92d98fdbd6145645828069b37ea92ca3de225e000d80702da25c20d3584b38a5"
 "checksum mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9e965267d4d58496fc4f740e9861118367f13570cadf66316ed2c3f2f14d87c7"
 "checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673"
 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
 "checksum moz_cbor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20c82a57087fd5990d7122dbff1607c3b20c3d2958e9d9ad9765aab415e2c91c"
 "checksum mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6626c2aef76eb8f984eef02e475883d3fe9112e114720446c5810fc5f045cd30"
 "checksum msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "65ba9d75bcea84e07812618fedf284a64776c2f2ea0cad6bca7f69739695a958"
 "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
+"checksum new-ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8ccbebba6fb53a6d2bdcfaf79cb339bc136dee3bfff54dc337a334bafe36476a"
+"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
 "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
 "checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
 "checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525"
 "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
 "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
 "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
 "checksum num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7de20f146db9d920c45ee8ed8f71681fd9ade71909b48c3acbd766aa504cf10"
 "checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
-"checksum ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da12c96037889ae0be29dd2bdd260e5a62a7df24e6466d5a15bb8131c1c200a8"
 "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
 "checksum parking_lot_core 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6c677d78851950b3aec390e681a411f78cc250cba277d4f578758a377f727970"
 "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
 "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
 "checksum petgraph 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7e5234c228fbfa874c86a77f685886127f82e0aef602ad1d48333fcac6ad61"
 "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
@@ -2676,17 +2668,17 @@ dependencies = [
 "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3"
 "checksum serde_derive 1.0.58 (git+https://github.com/servo/serde?branch=deserialize_from_enums7)" = "<none>"
 "checksum simd 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ed3686dd9418ebcc3a26a0c0ae56deab0681e53fe899af91f5bbcee667ebffb1"
 "checksum siphasher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ffc669b726f2bc9a3bcff66e5e23b56ba6bf70e22a34c3d7b6d0b3450b65b84"
 "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
 "checksum smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c63726029f0069f88467873e47f392575f28f9f16b72ac65465263db4b3a13c"
 "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
-"checksum string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39cb4173bcbd1319da31faa5468a7e3870683d7a237150b0b0aaafd546f6ad12"
+"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
 "checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7"
 "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
 "checksum syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9e1c669ed757c0ebd04337f6a5bb972d05e0c08fe2540dd3ee3dd9e4daf1604c"
 "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59"
 "checksum synstructure 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "010366096045d8250555904c58da03377289e7f4b2ce7a5b1027e2b532f41000"
 "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
 "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
@@ -2705,17 +2697,16 @@ dependencies = [
 "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
 "checksum uluru 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "519130f0ea964ba540a9d8af1373738c2226f1d465eda07e61db29feb5479db9"
 "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
 "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
 "checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
 "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
-"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
 "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
 "checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f"
 "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
 "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
 "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
--- a/devtools/client/inspector/grids/reducers/highlighter-settings.js
+++ b/devtools/client/inspector/grids/reducers/highlighter-settings.js
@@ -1,24 +1,32 @@
 /* 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/. */
 
 "use strict";
 
+const Services = require("Services");
+
 const {
   UPDATE_SHOW_GRID_AREAS,
   UPDATE_SHOW_GRID_LINE_NUMBERS,
   UPDATE_SHOW_INFINITE_LINES
 } = require("../actions/index");
 
-const INITIAL_HIGHLIGHTER_SETTINGS = {
-  showGridAreasOverlay: false,
-  showGridLineNumbers: false,
-  showInfiniteLines: false,
+const SHOW_GRID_AREAS = "devtools.gridinspector.showGridAreas";
+const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
+const SHOW_INFINITE_LINES = "devtools.gridinspector.showInfiniteLines";
+
+const INITIAL_HIGHLIGHTER_SETTINGS = () => {
+  return {
+    showGridAreasOverlay: Services.prefs.getBoolPref(SHOW_GRID_AREAS),
+    showGridLineNumbers: Services.prefs.getBoolPref(SHOW_GRID_LINE_NUMBERS),
+    showInfiniteLines: Services.prefs.getBoolPref(SHOW_INFINITE_LINES),
+  };
 };
 
 const reducers = {
 
   [UPDATE_SHOW_GRID_AREAS](highlighterSettings, { enabled }) {
     return Object.assign({}, highlighterSettings, {
       showGridAreasOverlay: enabled,
     });
@@ -33,15 +41,15 @@ const reducers = {
   [UPDATE_SHOW_INFINITE_LINES](highlighterSettings, { enabled }) {
     return Object.assign({}, highlighterSettings, {
       showInfiniteLines: enabled,
     });
   },
 
 };
 
-module.exports = function(highlighterSettings = INITIAL_HIGHLIGHTER_SETTINGS, action) {
+module.exports = function(highlighterSettings = INITIAL_HIGHLIGHTER_SETTINGS(), action) {
   const reducer = reducers[action.type];
   if (!reducer) {
     return highlighterSettings;
   }
   return reducer(highlighterSettings, action);
 };
--- a/devtools/client/inspector/shared/highlighters-overlay.js
+++ b/devtools/client/inspector/shared/highlighters-overlay.js
@@ -1,33 +1,23 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 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/. */
 
 "use strict";
 
-const Services = require("Services");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {
   VIEW_NODE_VALUE_TYPE,
   VIEW_NODE_SHAPE_POINT_TYPE
 } = require("devtools/client/inspector/shared/node-types");
 
-const {
-  updateShowGridAreas,
-  updateShowGridLineNumbers,
-  updateShowInfiniteLines,
-} = require("devtools/client/inspector/grids/actions/highlighter-settings");
-
 const DEFAULT_GRID_COLOR = "#4B0082";
-const SHOW_GRID_AREAS = "devtools.gridinspector.showGridAreas";
-const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
-const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines";
 
 /**
  * Highlighters overlay is a singleton managing all highlighters in the Inspector.
  */
 class HighlightersOverlay {
   /**
    * @param  {Inspector} inspector
    *         Inspector toolbox panel.
@@ -82,18 +72,16 @@ class HighlightersOverlay {
     this._handleRejection = this._handleRejection.bind(this);
     this.onShapesHighlighterShown = this.onShapesHighlighterShown.bind(this);
     this.onShapesHighlighterHidden = this.onShapesHighlighterHidden.bind(this);
 
     // Add inspector events, not specific to a given view.
     this.inspector.on("markupmutation", this.onMarkupMutation);
     this.inspector.target.on("will-navigate", this.onWillNavigate);
 
-    this.loadGridHighlighterSettings();
-
     EventEmitter.decorate(this);
   }
 
   /**
    * Returns whether `node` is somewhere inside the DOM of the rule view.
    *
    * @param {DOMNode} node
    * @return {Boolean}
@@ -128,31 +116,16 @@ class HighlightersOverlay {
   removeFromView(view) {
     const el = view.element;
     el.removeEventListener("click", this.onClick, true);
     el.removeEventListener("mousemove", this.onMouseMove);
     el.removeEventListener("mouseout", this.onMouseOut);
   }
 
   /**
-   * Load the grid highligher display settings into the store from the stored preferences.
-   */
-  loadGridHighlighterSettings() {
-    const { dispatch } = this.inspector.store;
-
-    const showGridAreas = Services.prefs.getBoolPref(SHOW_GRID_AREAS);
-    const showGridLineNumbers = Services.prefs.getBoolPref(SHOW_GRID_LINE_NUMBERS);
-    const showInfinteLines = Services.prefs.getBoolPref(SHOW_INFINITE_LINES_PREF);
-
-    dispatch(updateShowGridAreas(showGridAreas));
-    dispatch(updateShowGridLineNumbers(showGridLineNumbers));
-    dispatch(updateShowInfiniteLines(showInfinteLines));
-  }
-
-  /**
    * Toggle the shapes highlighter for the given node.
 
    * @param  {NodeFront} node
    *         The NodeFront of the element with a shape to highlight.
    * @param  {Object} options
    *         Object used for passing options to the shapes highlighter.
    * @param {TextProperty} textProperty
    *        TextProperty where to write changes.
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1276,17 +1276,19 @@ FireForgetSkippable(uint32_t aSuspected,
 
   TimeStamp now = TimeStamp::Now();
   TimeDuration duration = now - startTimeStamp;
   if (duration.ToSeconds()) {
     TimeDuration idleDuration;
     if (!aDeadline.IsNull()) {
       if (aDeadline < now) {
         // This slice overflowed the idle period.
-        idleDuration = aDeadline - startTimeStamp;
+        if (aDeadline > startTimeStamp) {
+          idleDuration = aDeadline - startTimeStamp;
+        }
       } else {
         idleDuration = duration;
       }
     }
 
     uint32_t percent =
       uint32_t(idleDuration.ToSeconds() / duration.ToSeconds() * 100);
     Telemetry::Accumulate(Telemetry::FORGET_SKIPPABLE_DURING_IDLE, percent);
--- a/gfx/layers/apz/src/GestureEventListener.cpp
+++ b/gfx/layers/apz/src/GestureEventListener.cpp
@@ -47,19 +47,20 @@ ParentLayerPoint GetCurrentFocus(const M
 ParentLayerCoord GetCurrentSpan(const MultiTouchInput& aEvent)
 {
   const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint;
   const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint;
   ParentLayerPoint delta = secondTouch - firstTouch;
   return delta.Length();
 }
 
-ParentLayerCoord GestureEventListener::GetYSpanFromStartPoint()
+ParentLayerCoord GestureEventListener::GetYSpanFromGestureStartPoint()
 {
-  const ParentLayerPoint start = mTouchStartPosition;
+  // use the position that began the one-touch-pinch gesture rather mTouchStartPosition
+  const ParentLayerPoint start = mOneTouchPinchStartPosition;
   const ParentLayerPoint& current = mTouches[0].mLocalScreenPoint;
   return current.y - start.y;
 }
 
 TapGestureInput CreateTapEvent(const MultiTouchInput& aTouch, TapGestureInput::TapGestureType aType)
 {
   return TapGestureInput(aType,
                          aTouch.mTime,
@@ -308,16 +309,19 @@ nsEventStatus GestureEventListener::Hand
         break;
       }
 
       SetState(GESTURE_ONE_TOUCH_PINCH);
 
       ParentLayerCoord currentSpan = 1.0f;
       ParentLayerPoint currentFocus = mTouchStartPosition;
 
+      // save the position that the one-touch-pinch gesture actually begins
+      mOneTouchPinchStartPosition = mLastTouchInput.mTouches[0].mLocalScreenPoint;
+
       PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_START,
                                    mLastTouchInput.mTime,
                                    mLastTouchInput.mTimeStamp,
                                    currentFocus,
                                    currentSpan,
                                    currentSpan,
                                    mLastTouchInput.modifiers);
 
@@ -383,17 +387,17 @@ nsEventStatus GestureEventListener::Hand
 
     rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
     mPreviousSpan = currentSpan;
 
     break;
   }
 
   case GESTURE_ONE_TOUCH_PINCH: {
-    ParentLayerCoord currentSpan = GetYSpanFromStartPoint();
+    ParentLayerCoord currentSpan = GetYSpanFromGestureStartPoint();
     float effectiveSpan = 1.0f + (fabsf(currentSpan.value) * ONE_TOUCH_PINCH_SPEED);
     ParentLayerPoint currentFocus = mTouchStartPosition;
 
     // Invert zoom.
     if (currentSpan.value < 0) {
       effectiveSpan = 1.0f / effectiveSpan;
     }
 
--- a/gfx/layers/apz/src/GestureEventListener.h
+++ b/gfx/layers/apz/src/GestureEventListener.h
@@ -145,20 +145,20 @@ private:
 
   void TriggerSingleTapConfirmedEvent();
 
   bool MoveDistanceExceeds(ScreenCoord aThreshold) const;
   bool MoveDistanceIsLarge() const;
   bool SecondTapIsFar() const;
 
   /**
-   * Returns current vertical span, counting from the where the user first put
-   * her finger down.
+   * Returns current vertical span, counting from the where the gesture first
+   * began (after a brief delay detecting the gesture from first touch).
    */
-  ParentLayerCoord GetYSpanFromStartPoint();
+  ParentLayerCoord GetYSpanFromGestureStartPoint();
 
   /**
    * Do actual state transition and reset substates.
    */
   void SetState(GestureState aState);
 
   RefPtr<AsyncPanZoomController> mAsyncPanZoomController;
 
@@ -204,16 +204,26 @@ private:
    * In the situation when we have a tap followed by a pinch we lose info
    * about tap since we keep only last input and to dispatch it correctly
    * we save last tap copy into this variable.
    * For more info see bug 947892.
    */
   MultiTouchInput mLastTapInput;
 
   /**
+   * Position of the last touch that exceeds the GetTouchStartTolerance when
+   * performing a one-touch-pinch gesture; using the mTouchStartPosition is
+   * slightly inaccurate because by the time the touch position has passed
+   * the threshold for the gesture, there is already a span that the zoom
+   * is calculated from, instead of starting at 1.0 when the threshold gets
+   * passed.
+   */
+  ParentLayerPoint mOneTouchPinchStartPosition;
+
+  /**
    * Position of the last touch starting. This is only valid during an attempt
    * to determine if a touch is a tap. If a touch point moves away from
    * mTouchStartPosition to the distance greater than
    * AsyncPanZoomController::GetTouchStartTolerance() while in
    * GESTURE_FIRST_SINGLE_TOUCH_DOWN, GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN
    * or GESTURE_SECOND_SINGLE_TOUCH_DOWN then we're certain the gesture is
    * not tap.
    */
--- a/ipc/glue/BackgroundUtils.cpp
+++ b/ipc/glue/BackgroundUtils.cpp
@@ -585,29 +585,36 @@ LoadInfoArgsToLoadInfo(const OptionalLoa
    return NS_OK;
 }
 
 void
 LoadInfoToParentLoadInfoForwarder(nsILoadInfo* aLoadInfo,
                                   ParentLoadInfoForwarderArgs* aForwarderArgsOut)
 {
   if (!aLoadInfo) {
-    *aForwarderArgsOut = ParentLoadInfoForwarderArgs(false, void_t());
+    *aForwarderArgsOut = ParentLoadInfoForwarderArgs(false, void_t(),
+                                                     nsILoadInfo::TAINTING_BASIC,
+                                                     false);
     return;
   }
 
   OptionalIPCServiceWorkerDescriptor ipcController = void_t();
   Maybe<ServiceWorkerDescriptor> controller(aLoadInfo->GetController());
   if (controller.isSome()) {
     ipcController = controller.ref().ToIPC();
   }
 
+  uint32_t tainting = nsILoadInfo::TAINTING_BASIC;
+  Unused << aLoadInfo->GetTainting(&tainting);
+
   *aForwarderArgsOut = ParentLoadInfoForwarderArgs(
     aLoadInfo->GetAllowInsecureRedirectToDataURI(),
-    ipcController
+    ipcController,
+    tainting,
+    aLoadInfo->GetServiceWorkerTaintingSynthesized()
   );
 }
 
 nsresult
 MergeParentLoadInfoForwarder(ParentLoadInfoForwarderArgs const& aForwarderArgs,
                              nsILoadInfo* aLoadInfo)
 {
   if (!aLoadInfo) {
@@ -622,16 +629,23 @@ MergeParentLoadInfoForwarder(ParentLoadI
 
   aLoadInfo->ClearController();
   auto& controller = aForwarderArgs.controller();
   if (controller.type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
     aLoadInfo->SetController(
       ServiceWorkerDescriptor(controller.get_IPCServiceWorkerDescriptor()));
   }
 
+  if (aForwarderArgs.serviceWorkerTaintingSynthesized()) {
+    aLoadInfo->SynthesizeServiceWorkerTainting(
+      static_cast<LoadTainting>(aForwarderArgs.tainting()));
+  } else {
+    aLoadInfo->MaybeIncreaseTainting(aForwarderArgs.tainting());
+  }
+
   return NS_OK;
 }
 
 void
 LoadInfoToChildLoadInfoForwarder(nsILoadInfo* aLoadInfo,
                                  ChildLoadInfoForwarderArgs* aForwarderArgsOut)
 {
   if (!aLoadInfo) {
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3590,16 +3590,17 @@ WorkerMain(void* arg)
         sc->markObservers.reset();
         JS_DestroyContext(cx);
         js_delete(sc);
         js_delete(input);
     });
 
     sc->isWorker = true;
     JS_SetContextPrivate(cx, sc);
+    JS_SetGrayGCRootsTracer(cx, TraceGrayRoots, nullptr);
     SetWorkerContextOptions(cx);
     JS::SetBuildIdOp(cx, ShellBuildId);
 
     JS_SetFutexCanWait(cx);
     JS::SetWarningReporter(cx, WarningReporter);
     js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
     JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy);
 
new file mode 100644
--- /dev/null
+++ b/js/src/tests/non262/regress/regress-1466387-worker-grayroot.js
@@ -0,0 +1,28 @@
+var BUGNUMBER = 1466387;
+var summary = 'grayRoot() testing on worker thread';
+
+// Before bug 1466387, the gray root tracer was not set up on worker threads,
+// but the grayRoot() function was still available. This resulted in a GC
+// collecting the gray root, then a read barrier firing on the dead object.
+//
+// This is a crashtest. If it does not crash, it will throw a ReferenceError,
+// but that's ok.
+
+print('BUGNUMBER: ' + BUGNUMBER);
+print("STATUS: " + summary);
+
+if (typeof 'evalInWorder' == 'function') {
+    evalInWorker(`
+  var wm = new WeakMap();
+  grayRoot().map = wm;
+  gczeal(4,10);
+  evaluate(\`
+  grayRoot().map = __v_1173;
+  if (!class i   { constructor() { } }  ()) {
+    (function __f_252( get       ,    )  {})();
+  }
+  \`);
+`);
+}
+
+this.reportCompare && reportCompare(true, true, summary);
--- a/mobile/android/base/java/org/mozilla/gecko/notifications/NotificationClient.java
+++ b/mobile/android/base/java/org/mozilla/gecko/notifications/NotificationClient.java
@@ -1,32 +1,31 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
  * 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/. */
 
 package org.mozilla.gecko.notifications;
 
+import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.app.Notification;
 import android.app.PendingIntent;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.net.Uri;
+import android.support.annotation.NonNull;
 import android.support.v4.app.NotificationCompat;
 import android.support.v4.app.NotificationManagerCompat;
-import android.util.Log;
 
 import java.util.HashMap;
 
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.GeckoActivityMonitor;
-import org.mozilla.gecko.GeckoApp;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoService;
 import org.mozilla.gecko.NotificationListener;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.util.BitmapUtils;
 
 /**
  * Client for posting notifications.
@@ -294,23 +293,33 @@ public final class NotificationClient im
      */
     public boolean isOngoing(final Notification notification) {
         if (notification != null && (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0) {
             return true;
         }
         return false;
     }
 
-    private void setForegroundNotificationLocked(final String name,
-                                                 final Notification notification) {
+    @SuppressLint("NewApi")
+    private void setForegroundNotificationLocked(@NonNull final String name,
+                                                 @NonNull final Notification notification) {
         mForegroundNotification = name;
 
         final Intent intent = new Intent(mContext, NotificationService.class);
         intent.putExtra(NotificationService.EXTRA_NOTIFICATION, notification);
-        mContext.startService(intent);
+        if (AppConstants.Versions.preO) {
+            mContext.startService(intent);
+        } else {
+            mContext.startForegroundService(intent);
+        }
+    }
+
+    private void removeForegroundNotificationLocked() {
+        mForegroundNotification = null;
+        mContext.stopService(new Intent(mContext, NotificationService.class));
     }
 
     private void updateForegroundNotificationLocked(final String oldName) {
         if (mForegroundNotification == null || !mForegroundNotification.equals(oldName)) {
             return;
         }
 
         // If we're removing the notification associated with the
@@ -323,11 +332,11 @@ public final class NotificationClient im
                 // uses a special ID, so we need to close its old instantiation and then
                 // re-add it with the new ID through the NotificationService.
                 onNotificationClose(name);
                 setForegroundNotificationLocked(name, notification);
                 return;
             }
         }
 
-        setForegroundNotificationLocked(null, null);
+        removeForegroundNotificationLocked();
     }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/notifications/NotificationService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/notifications/NotificationService.java
@@ -13,25 +13,18 @@ import android.os.IBinder;
 import org.mozilla.gecko.R;
 
 public final class NotificationService extends Service {
     public static final String EXTRA_NOTIFICATION = "notification";
 
     @Override // Service
     public int onStartCommand(final Intent intent, final int flags, final int startId) {
         final Notification notification = intent.getParcelableExtra(EXTRA_NOTIFICATION);
-        if (notification != null) {
-            // Start foreground notification.
-            startForeground(R.id.foregroundNotification, notification);
-            return START_NOT_STICKY;
-        }
-
-        // Stop foreground notification
-        stopForeground(true);
-        stopSelfResult(startId);
+        // Start foreground notification.
+        startForeground(R.id.foregroundNotification, notification);
         return START_NOT_STICKY;
     }
 
     @Override // Service
     public IBinder onBind(final Intent intent) {
         return null;
     }
 }
--- a/netwerk/base/nsILoadInfo.idl
+++ b/netwerk/base/nsILoadInfo.idl
@@ -988,18 +988,19 @@ interface nsILoadInfo : nsISupports
   void SetPerformanceStorage(in PerformanceStoragePtr aPerformanceStorage);
 
   /**
    * Get the PerformanceStorage.
    */
   [noscript, nostdcall, notxpcom]
   PerformanceStoragePtr GetPerformanceStorage();
 
-  /* The service worker and fetch specifications require returning the
-   * exact tainting level of the Response passed to FetchEvent.respondWith().
-   * This method allows us to override the tainting level in that case.
-   *
-   * NOTE: This should not be used outside of service worker code! Use
-   *       nsILoadInfo::MaybeIncreaseTainting() instead.
+  /**
+    * The service worker and fetch specifications require returning the
+    * exact tainting level of the Response passed to FetchEvent.respondWith().
+    * This method allows us to override the tainting level in that case.
+    *
+    * NOTE: This should not be used outside of service worker code! Use
+    *       nsILoadInfo::MaybeIncreaseTainting() instead.
    */
   [noscript, nostdcall, notxpcom]
   void SynthesizeServiceWorkerTainting(in LoadTainting aTainting);
 };
--- a/netwerk/ipc/NeckoChannelParams.ipdlh
+++ b/netwerk/ipc/NeckoChannelParams.ipdlh
@@ -127,16 +127,24 @@ struct ParentLoadInfoForwarderArgs
   // the parent and needs to be mirrored to the child so that security
   // checks can pass.
   bool allowInsecureRedirectToDataURI;
 
   // The ServiceWorker controller that may be set in the parent when
   // interception occurs.
   OptionalIPCServiceWorkerDescriptor controller;
 
+  // The service worker may synthesize a Response with a particular
+  // tainting value.
+  uint32_t tainting;
+
+  // We must also note that the tainting value was explicitly set
+  // by the service worker.
+  bool serviceWorkerTaintingSynthesized;
+
   // IMPORTANT: when you add new properites here you must also update
   // LoadInfoToParentLoadInfoForwarder and MergeParentLoadInfoForwarder
   // in BackgroundUtils.cpp/.h!
 };
 
 /**
  * This structure is used to carry selected properties of a LoadInfo
  * object to the parent process that might have changed in the child
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-8232a58332dd
+30a4b03cd9d1
--- a/security/nss/automation/taskcluster/docker-hacl/Dockerfile
+++ b/security/nss/automation/taskcluster/docker-hacl/Dockerfile
@@ -3,18 +3,18 @@ FROM ubuntu:xenial
 MAINTAINER Franziskus Kiefer <franziskuskiefer@gmail.com>
 # Based on the HACL* image from Benjamin Beurdouche and
 # the original F* formula with Daniel Fabian
 
 # Pinned versions of HACL* (F* and KreMLin are pinned as submodules)
 ENV haclrepo https://github.com/mitls/hacl-star.git
 
 # Define versions of dependencies
-ENV opamv 4.04.2
-ENV haclversion e13326efee1a9910004dccbb56f3d7be6639e0b8
+ENV opamv 4.05.0
+ENV haclversion 1da331f9ef30e13269e45ae73bbe4a4bca679ae6
 
 # Install required packages and set versions
 ADD setup.sh /tmp/setup.sh
 RUN bash /tmp/setup.sh
 
 # Create user, add scripts.
 RUN useradd -ms /bin/bash worker
 WORKDIR /home/worker
--- a/security/nss/cmd/pk1sign/pk1sign.c
+++ b/security/nss/cmd/pk1sign/pk1sign.c
@@ -173,17 +173,17 @@ SignFile(FILE *outFile, PRFileDesc *inFi
     fputs("\n", outFile);
     ExportPublicKey(outFile, cert);
 
 loser:
     if (privKey) {
         SECKEY_DestroyPrivateKey(privKey);
     }
     if (data) {
-        PORT_Free(data);
+        PR_Free(data);
     }
     PORT_FreeArena(arena, PR_FALSE);
 
     return returnValue;
 }
 
 int
 main(int argc, char **argv)
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/security/nss/gtests/ssl_gtest/manifest.mn
+++ b/security/nss/gtests/ssl_gtest/manifest.mn
@@ -31,16 +31,17 @@ CPPSRCS = \
       ssl_gather_unittest.cc \
       ssl_gtest.cc \
       ssl_hrr_unittest.cc \
       ssl_keylog_unittest.cc \
       ssl_keyupdate_unittest.cc \
       ssl_loopback_unittest.cc \
       ssl_misc_unittest.cc \
       ssl_record_unittest.cc \
+      ssl_recordsize_unittest.cc \
       ssl_resumption_unittest.cc \
       ssl_renegotiation_unittest.cc \
       ssl_skip_unittest.cc \
       ssl_staticrsa_unittest.cc \
       ssl_tls13compat_unittest.cc \
       ssl_v2_client_hello_unittest.cc \
       ssl_version_unittest.cc \
       ssl_versionpolicy_unittest.cc \
--- a/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc
@@ -63,16 +63,17 @@ static const uint16_t kManyExtensions[] 
     ssl_tls13_supported_versions_xtn,
     ssl_tls13_cookie_xtn,
     ssl_tls13_psk_key_exchange_modes_xtn,
     ssl_tls13_ticket_early_data_info_xtn,
     ssl_tls13_certificate_authorities_xtn,
     ssl_next_proto_nego_xtn,
     ssl_renegotiation_info_xtn,
     ssl_tls13_short_header_xtn,
+    ssl_record_size_limit_xtn,
     1,
     0xffff};
 // The list here includes all extensions we expect to use (SSL_MAX_EXTENSIONS),
 // plus the deprecated values (see sslt.h), and two extra dummy values.
 PR_STATIC_ASSERT((SSL_MAX_EXTENSIONS + 5) == PR_ARRAY_SIZE(kManyExtensions));
 
 void InstallManyWriters(std::shared_ptr<TlsAgent> agent,
                         SSLExtensionWriter writer, size_t *installed = nullptr,
--- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
+++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
@@ -32,16 +32,17 @@
         'ssl_gather_unittest.cc',
         'ssl_gtest.cc',
         'ssl_hrr_unittest.cc',
         'ssl_keylog_unittest.cc',
         'ssl_keyupdate_unittest.cc',
         'ssl_loopback_unittest.cc',
         'ssl_misc_unittest.cc',
         'ssl_record_unittest.cc',
+        'ssl_recordsize_unittest.cc',
         'ssl_resumption_unittest.cc',
         'ssl_renegotiation_unittest.cc',
         'ssl_skip_unittest.cc',
         'ssl_staticrsa_unittest.cc',
         'ssl_tls13compat_unittest.cc',
         'ssl_v2_client_hello_unittest.cc',
         'ssl_version_unittest.cc',
         'ssl_versionpolicy_unittest.cc',
--- a/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc
@@ -99,43 +99,57 @@ TEST_P(TlsPaddingTest, LastByteOfPadWron
                      plaintext_.data()[plaintext_.len() - 1] + 1, 1);
     Unpad(false);
   }
 }
 
 class RecordReplacer : public TlsRecordFilter {
  public:
   RecordReplacer(const std::shared_ptr<TlsAgent>& a, size_t size)
-      : TlsRecordFilter(a), enabled_(false), size_(size) {}
+      : TlsRecordFilter(a), size_(size) {
+    Disable();
+  }
 
   PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
                                     const DataBuffer& data,
                                     DataBuffer* changed) override {
-    if (!enabled_) {
-      return KEEP;
-    }
-
     EXPECT_EQ(kTlsApplicationDataType, header.content_type());
     changed->Allocate(size_);
 
     for (size_t i = 0; i < size_; ++i) {
       changed->data()[i] = i & 0xff;
     }
 
-    enabled_ = false;
+    Disable();
     return CHANGE;
   }
 
-  void Enable() { enabled_ = true; }
-
  private:
-  bool enabled_;
   size_t size_;
 };
 
+TEST_P(TlsConnectStream, BadRecordMac) {
+  EnsureTlsSetup();
+  Connect();
+  client_->SetFilter(std::make_shared<TlsRecordLastByteDamager>(client_));
+  ExpectAlert(server_, kTlsAlertBadRecordMac);
+  client_->SendData(10);
+
+  // Read from the client, get error.
+  uint8_t buf[10];
+  PRInt32 rv = PR_Read(server_->ssl_fd(), buf, sizeof(buf));
+  EXPECT_GT(0, rv);
+  EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, PORT_GetError());
+
+  // Read the server alert.
+  rv = PR_Read(client_->ssl_fd(), buf, sizeof(buf));
+  EXPECT_GT(0, rv);
+  EXPECT_EQ(SSL_ERROR_BAD_MAC_ALERT, PORT_GetError());
+}
+
 TEST_F(TlsConnectStreamTls13, LargeRecord) {
   EnsureTlsSetup();
 
   const size_t record_limit = 16384;
   auto replacer = MakeTlsFilter<RecordReplacer>(client_, record_limit);
   replacer->EnableDecryption();
   Connect();
 
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc
@@ -0,0 +1,431 @@
+/* -*- 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 "secerr.h"
+#include "ssl.h"
+#include "sslerr.h"
+#include "sslproto.h"
+
+#include "gtest_utils.h"
+#include "scoped_ptrs.h"
+#include "tls_connect.h"
+#include "tls_filter.h"
+#include "tls_parser.h"
+
+namespace nss_test {
+
+// This class tracks the maximum size of record that was sent, both cleartext
+// and plain.  It only tracks records that have an outer type of
+// application_data.  In TLS 1.3, this includes handshake messages.
+class TlsRecordMaximum : public TlsRecordFilter {
+ public:
+  TlsRecordMaximum(const std::shared_ptr<TlsAgent>& a)
+      : TlsRecordFilter(a), max_ciphertext_(0), max_plaintext_(0) {}
+
+  size_t max_ciphertext() const { return max_ciphertext_; }
+  size_t max_plaintext() const { return max_plaintext_; }
+
+ protected:
+  PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
+                                    const DataBuffer& record, size_t* offset,
+                                    DataBuffer* output) override {
+    std::cerr << "max: " << record << std::endl;
+    // Ignore unprotected packets.
+    if (header.content_type() != kTlsApplicationDataType) {
+      return KEEP;
+    }
+
+    max_ciphertext_ = (std::max)(max_ciphertext_, record.len());
+    return TlsRecordFilter::FilterRecord(header, record, offset, output);
+  }
+
+  PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
+                                    const DataBuffer& data,
+                                    DataBuffer* changed) override {
+    max_plaintext_ = (std::max)(max_plaintext_, data.len());
+    return KEEP;
+  }
+
+ private:
+  size_t max_ciphertext_;
+  size_t max_plaintext_;
+};
+
+void CheckRecordSizes(const std::shared_ptr<TlsAgent>& agent,
+                      const std::shared_ptr<TlsRecordMaximum>& record_max,
+                      size_t config) {
+  uint16_t cipher_suite;
+  ASSERT_TRUE(agent->cipher_suite(&cipher_suite));
+
+  size_t expansion;
+  size_t iv;
+  switch (cipher_suite) {
+    case TLS_AES_128_GCM_SHA256:
+    case TLS_AES_256_GCM_SHA384:
+    case TLS_CHACHA20_POLY1305_SHA256:
+      expansion = 16;
+      iv = 0;
+      break;
+
+    case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+      expansion = 16;
+      iv = 8;
+      break;
+
+    case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+      // Expansion is 20 for the MAC.  Maximum block padding is 16.  Maximum
+      // padding is added when the input plus the MAC is an exact multiple of
+      // the block size.
+      expansion = 20 + 16 - ((config + 20) % 16);
+      iv = 16;
+      break;
+
+    default:
+      ADD_FAILURE() << "No expansion set for ciphersuite "
+                    << agent->cipher_suite_name();
+      return;
+  }
+
+  switch (agent->version()) {
+    case SSL_LIBRARY_VERSION_TLS_1_3:
+      EXPECT_EQ(0U, iv) << "No IV for TLS 1.3";
+      // We only have decryption in TLS 1.3.
+      EXPECT_EQ(config - 1, record_max->max_plaintext())
+          << "bad plaintext length for " << agent->role_str();
+      break;
+
+    case SSL_LIBRARY_VERSION_TLS_1_2:
+    case SSL_LIBRARY_VERSION_TLS_1_1:
+      expansion += iv;
+      break;
+
+    case SSL_LIBRARY_VERSION_TLS_1_0:
+      break;
+
+    default:
+      ADD_FAILURE() << "Unexpected version " << agent->version();
+      return;
+  }
+
+  EXPECT_EQ(config + expansion, record_max->max_ciphertext())
+      << "bad ciphertext length for " << agent->role_str();
+}
+
+TEST_P(TlsConnectGeneric, RecordSizeMaximum) {
+  uint16_t max_record_size =
+      (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) ? 16385 : 16384;
+  size_t send_size = (version_ >= SSL_LIBRARY_VERSION_TLS_1_3)
+                         ? max_record_size
+                         : max_record_size + 1;
+
+  EnsureTlsSetup();
+  auto client_max = MakeTlsFilter<TlsRecordMaximum>(client_);
+  client_max->EnableDecryption();
+  auto server_max = MakeTlsFilter<TlsRecordMaximum>(server_);
+  server_max->EnableDecryption();
+
+  Connect();
+  client_->SendData(send_size, send_size);
+  server_->SendData(send_size, send_size);
+  server_->ReadBytes(send_size);
+  client_->ReadBytes(send_size);
+
+  CheckRecordSizes(client_, client_max, max_record_size);
+  CheckRecordSizes(server_, server_max, max_record_size);
+}
+
+TEST_P(TlsConnectGeneric, RecordSizeMinimumClient) {
+  EnsureTlsSetup();
+  auto server_max = MakeTlsFilter<TlsRecordMaximum>(server_);
+  server_max->EnableDecryption();
+
+  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
+  Connect();
+  SendReceive(127);  // Big enough for one record, allowing for 1+N splitting.
+
+  CheckRecordSizes(server_, server_max, 64);
+}
+
+TEST_P(TlsConnectGeneric, RecordSizeMinimumServer) {
+  EnsureTlsSetup();
+  auto client_max = MakeTlsFilter<TlsRecordMaximum>(client_);
+  client_max->EnableDecryption();
+
+  server_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
+  Connect();
+  SendReceive(127);
+
+  CheckRecordSizes(client_, client_max, 64);
+}
+
+TEST_P(TlsConnectGeneric, RecordSizeAsymmetric) {
+  EnsureTlsSetup();
+  auto client_max = MakeTlsFilter<TlsRecordMaximum>(client_);
+  client_max->EnableDecryption();
+  auto server_max = MakeTlsFilter<TlsRecordMaximum>(server_);
+  server_max->EnableDecryption();
+
+  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
+  server_->SetOption(SSL_RECORD_SIZE_LIMIT, 100);
+  Connect();
+  SendReceive(127);
+
+  CheckRecordSizes(client_, client_max, 100);
+  CheckRecordSizes(server_, server_max, 64);
+}
+
+// This just modifies the encrypted payload so to include a few extra zeros.
+class TlsRecordExpander : public TlsRecordFilter {
+ public:
+  TlsRecordExpander(const std::shared_ptr<TlsAgent>& a, size_t expansion)
+      : TlsRecordFilter(a), expansion_(expansion) {}
+
+ protected:
+  virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
+                                            const DataBuffer& data,
+                                            DataBuffer* changed) {
+    if (header.content_type() != kTlsApplicationDataType) {
+      return KEEP;
+    }
+    changed->Allocate(data.len() + expansion_);
+    changed->Write(0, data.data(), data.len());
+    return CHANGE;
+  }
+
+ private:
+  size_t expansion_;
+};
+
+// Tweak the plaintext of server records so that they exceed the client's limit.
+TEST_P(TlsConnectTls13, RecordSizePlaintextExceed) {
+  EnsureTlsSetup();
+  auto server_expand = MakeTlsFilter<TlsRecordExpander>(server_, 1);
+  server_expand->EnableDecryption();
+
+  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
+  Connect();
+
+  server_->SendData(100);
+
+  client_->ExpectReadWriteError();
+  ExpectAlert(client_, kTlsAlertRecordOverflow);
+  client_->ReadBytes(100);
+  EXPECT_EQ(SSL_ERROR_RX_RECORD_TOO_LONG, client_->error_code());
+
+  // Consume the alert at the server.
+  server_->Handshake();
+  server_->CheckErrorCode(SSL_ERROR_RECORD_OVERFLOW_ALERT);
+}
+
+// Tweak the ciphertext of server records so that they greatly exceed the limit.
+// This requires a much larger expansion than for plaintext to trigger the
+// guard, which runs before decryption (current allowance is 304 octets).
+TEST_P(TlsConnectTls13, RecordSizeCiphertextExceed) {
+  EnsureTlsSetup();
+
+  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
+  Connect();
+
+  auto server_expand = MakeTlsFilter<TlsRecordExpander>(server_, 320);
+  server_->SendData(100);
+
+  client_->ExpectReadWriteError();
+  ExpectAlert(client_, kTlsAlertRecordOverflow);
+  client_->ReadBytes(100);
+  EXPECT_EQ(SSL_ERROR_RX_RECORD_TOO_LONG, client_->error_code());
+
+  // Consume the alert at the server.
+  server_->Handshake();
+  server_->CheckErrorCode(SSL_ERROR_RECORD_OVERFLOW_ALERT);
+}
+
+// This indiscriminately adds padding to application data records.
+class TlsRecordPadder : public TlsRecordFilter {
+ public:
+  TlsRecordPadder(const std::shared_ptr<TlsAgent>& a, size_t padding)
+      : TlsRecordFilter(a), padding_(padding) {}
+
+ protected:
+  PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
+                                    const DataBuffer& record, size_t* offset,
+                                    DataBuffer* output) override {
+    if (header.content_type() != kTlsApplicationDataType) {
+      return KEEP;
+    }
+
+    uint8_t inner_content_type;
+    DataBuffer plaintext;
+    if (!Unprotect(header, record, &inner_content_type, &plaintext)) {
+      return KEEP;
+    }
+
+    if (inner_content_type != kTlsApplicationDataType) {
+      return KEEP;
+    }
+
+    DataBuffer ciphertext;
+    bool ok =
+        Protect(header, inner_content_type, plaintext, &ciphertext, padding_);
+    EXPECT_TRUE(ok);
+    if (!ok) {
+      return KEEP;
+    }
+    *offset = header.Write(output, *offset, ciphertext);
+    return CHANGE;
+  }
+
+ private:
+  size_t padding_;
+};
+
+TEST_P(TlsConnectTls13, RecordSizeExceedPad) {
+  EnsureTlsSetup();
+  auto server_max = std::make_shared<TlsRecordMaximum>(server_);
+  auto server_expand = std::make_shared<TlsRecordPadder>(server_, 1);
+  server_->SetFilter(std::make_shared<ChainedPacketFilter>(
+      ChainedPacketFilterInit({server_max, server_expand})));
+  server_expand->EnableDecryption();
+
+  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
+  Connect();
+
+  server_->SendData(100);
+
+  client_->ExpectReadWriteError();
+  ExpectAlert(client_, kTlsAlertRecordOverflow);
+  client_->ReadBytes(100);
+  EXPECT_EQ(SSL_ERROR_RX_RECORD_TOO_LONG, client_->error_code());
+
+  // Consume the alert at the server.
+  server_->Handshake();
+  server_->CheckErrorCode(SSL_ERROR_RECORD_OVERFLOW_ALERT);
+}
+
+TEST_P(TlsConnectGeneric, RecordSizeBadValues) {
+  EnsureTlsSetup();
+  EXPECT_EQ(SECFailure,
+            SSL_OptionSet(client_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, 63));
+  EXPECT_EQ(SECFailure,
+            SSL_OptionSet(client_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, -1));
+  EXPECT_EQ(SECFailure,
+            SSL_OptionSet(server_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, 16386));
+  Connect();
+}
+
+TEST_P(TlsConnectGeneric, RecordSizeGetValues) {
+  EnsureTlsSetup();
+  int v;
+  EXPECT_EQ(SECSuccess,
+            SSL_OptionGet(client_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, &v));
+  EXPECT_EQ(16385, v);
+  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 300);
+  EXPECT_EQ(SECSuccess,
+            SSL_OptionGet(client_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, &v));
+  EXPECT_EQ(300, v);
+  Connect();
+}
+
+// The value of the extension is capped by the maximum version of the client.
+TEST_P(TlsConnectGeneric, RecordSizeCapExtensionClient) {
+  EnsureTlsSetup();
+  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 16385);
+  auto capture =
+      MakeTlsFilter<TlsExtensionCapture>(client_, ssl_record_size_limit_xtn);
+  capture->EnableDecryption();
+  Connect();
+
+  uint64_t val = 0;
+  EXPECT_TRUE(capture->extension().Read(0, 2, &val));
+  if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
+    EXPECT_EQ(16384U, val) << "Extension should be capped";
+  } else {
+    EXPECT_EQ(16385U, val);
+  }
+}
+
+// The value of the extension is capped by the maximum version of the server.
+TEST_P(TlsConnectGeneric, RecordSizeCapExtensionServer) {
+  EnsureTlsSetup();
+  server_->SetOption(SSL_RECORD_SIZE_LIMIT, 16385);
+  auto capture =
+      MakeTlsFilter<TlsExtensionCapture>(server_, ssl_record_size_limit_xtn);
+  capture->EnableDecryption();
+  Connect();
+
+  uint64_t val = 0;
+  EXPECT_TRUE(capture->extension().Read(0, 2, &val));
+  if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
+    EXPECT_EQ(16384U, val) << "Extension should be capped";
+  } else {
+    EXPECT_EQ(16385U, val);
+  }
+}
+
+// Damage the client extension and the handshake fails, but the server
+// doesn't generate a validation error.
+TEST_P(TlsConnectGenericPre13, RecordSizeClientExtensionInvalid) {
+  EnsureTlsSetup();
+  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 1000);
+  static const uint8_t v[] = {0xf4, 0x1f};
+  MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_record_size_limit_xtn,
+                                      DataBuffer(v, sizeof(v)));
+  ConnectExpectAlert(server_, kTlsAlertDecryptError);
+}
+
+// Special handling for TLS 1.3, where the alert isn't read.
+TEST_F(TlsConnectStreamTls13, RecordSizeClientExtensionInvalid) {
+  EnsureTlsSetup();
+  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 1000);
+  static const uint8_t v[] = {0xf4, 0x1f};
+  MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_record_size_limit_xtn,
+                                      DataBuffer(v, sizeof(v)));
+  client_->ExpectSendAlert(kTlsAlertBadRecordMac);
+  server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+  ConnectExpectFail();
+}
+
+TEST_P(TlsConnectGeneric, RecordSizeServerExtensionInvalid) {
+  EnsureTlsSetup();
+  server_->SetOption(SSL_RECORD_SIZE_LIMIT, 1000);
+  static const uint8_t v[] = {0xf4, 0x1f};
+  auto replace = MakeTlsFilter<TlsExtensionReplacer>(
+      server_, ssl_record_size_limit_xtn, DataBuffer(v, sizeof(v)));
+  replace->EnableDecryption();
+  ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
+}
+
+class RecordSizeDefaultsTest : public ::testing::Test {
+ public:
+  void SetUp() {
+    EXPECT_EQ(SECSuccess,
+              SSL_OptionGetDefault(SSL_RECORD_SIZE_LIMIT, &default_));
+  }
+  void TearDown() {
+    // Make sure to restore the default value at the end.
+    EXPECT_EQ(SECSuccess,
+              SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, default_));
+  }
+
+ private:
+  PRIntn default_ = 0;
+};
+
+TEST_F(RecordSizeDefaultsTest, RecordSizeBadValues) {
+  EXPECT_EQ(SECFailure, SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, 63));
+  EXPECT_EQ(SECFailure, SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, -1));
+  EXPECT_EQ(SECFailure, SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, 16386));
+}
+
+TEST_F(RecordSizeDefaultsTest, RecordSizeGetValue) {
+  int v;
+  EXPECT_EQ(SECSuccess, SSL_OptionGetDefault(SSL_RECORD_SIZE_LIMIT, &v));
+  EXPECT_EQ(16385, v);
+  EXPECT_EQ(SECSuccess, SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, 3000));
+  EXPECT_EQ(SECSuccess, SSL_OptionGetDefault(SSL_RECORD_SIZE_LIMIT, &v));
+  EXPECT_EQ(3000, v);
+}
+
+}  // namespace nss_test
--- a/security/nss/gtests/ssl_gtest/tls_agent.cc
+++ b/security/nss/gtests/ssl_gtest/tls_agent.cc
@@ -934,19 +934,19 @@ void TlsAgent::SendRecordDirect(const Tl
   SendDirect(buf);
 }
 
 static bool ErrorIsNonFatal(PRErrorCode code) {
   return code == PR_WOULD_BLOCK_ERROR || code == SSL_ERROR_RX_SHORT_DTLS_READ;
 }
 
 void TlsAgent::SendData(size_t bytes, size_t blocksize) {
-  uint8_t block[4096];
+  uint8_t block[16385];  // One larger than the maximum record size.
 
-  ASSERT_LT(blocksize, sizeof(block));
+  ASSERT_LE(blocksize, sizeof(block));
 
   while (bytes) {
     size_t tosend = std::min(blocksize, bytes);
 
     for (size_t i = 0; i < tosend; ++i) {
       block[i] = 0xff & send_ctr_;
       ++send_ctr_;
     }
--- a/security/nss/gtests/ssl_gtest/tls_filter.cc
+++ b/security/nss/gtests/ssl_gtest/tls_filter.cc
@@ -405,26 +405,28 @@ bool TlsRecordFilter::Unprotect(const Tl
   }
 
   return true;
 }
 
 bool TlsRecordFilter::Protect(const TlsRecordHeader& header,
                               uint8_t inner_content_type,
                               const DataBuffer& plaintext,
-                              DataBuffer* ciphertext) {
+                              DataBuffer* ciphertext, size_t padding) {
   if (!cipher_spec_ || header.content_type() != kTlsApplicationDataType) {
     *ciphertext = plaintext;
     return true;
   }
   if (g_ssl_gtest_verbose) {
     std::cerr << "protect: " << header.sequence_number() << std::endl;
   }
-  DataBuffer padded = plaintext;
-  padded.Write(padded.len(), inner_content_type, 1);
+  DataBuffer padded;
+  padded.Allocate(plaintext.len() + 1 + padding);
+  size_t offset = padded.Write(0, plaintext.data(), plaintext.len());
+  padded.Write(offset, inner_content_type, 1);
   return cipher_spec_->Protect(header, padded, ciphertext);
 }
 
 bool IsHelloRetry(const DataBuffer& body) {
   static const uint8_t ssl_hello_retry_random[] = {
       0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C,
       0x02, 0x1E, 0x65, 0xB8, 0x91, 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB,
       0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C};
--- a/security/nss/gtests/ssl_gtest/tls_filter.h
+++ b/security/nss/gtests/ssl_gtest/tls_filter.h
@@ -115,17 +115,18 @@ class TlsRecordFilter : public PacketFil
 
   // Enable decryption. This only works properly for TLS 1.3 and above.
   // Enabling it for lower version tests will cause undefined
   // behavior.
   void EnableDecryption();
   bool Unprotect(const TlsRecordHeader& header, const DataBuffer& cipherText,
                  uint8_t* inner_content_type, DataBuffer* plaintext);
   bool Protect(const TlsRecordHeader& header, uint8_t inner_content_type,
-               const DataBuffer& plaintext, DataBuffer* ciphertext);
+               const DataBuffer& plaintext, DataBuffer* ciphertext,
+               size_t padding = 0);
 
  protected:
   // There are two filter functions which can be overriden. Both are
   // called with the header and the record but the outer one is called
   // with a raw pointer to let you write into the buffer and lets you
   // do anything with this section of the stream. The inner one
   // just lets you change the record contents. By default, the
   // outer one calls the inner one, so if you override the outer
@@ -501,16 +502,32 @@ class TlsClientHelloVersionChanger : pub
   virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
                                                const DataBuffer& input,
                                                DataBuffer* output);
 
  private:
   std::weak_ptr<TlsAgent> server_;
 };
 
+// Damage a record.
+class TlsRecordLastByteDamager : public TlsRecordFilter {
+ public:
+  TlsRecordLastByteDamager(const std::shared_ptr<TlsAgent>& a)
+      : TlsRecordFilter(a) {}
+
+ protected:
+  PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
+                                    const DataBuffer& data,
+                                    DataBuffer* changed) override {
+    *changed = data;
+    changed->data()[changed->len() - 1]++;
+    return CHANGE;
+  }
+};
+
 // This class selectively drops complete writes.  This relies on the fact that
 // writes in libssl are on record boundaries.
 class SelectiveDropFilter : public PacketFilter {
  public:
   SelectiveDropFilter(uint32_t pattern) : pattern_(pattern), counter_(0) {}
 
  protected:
   virtual PacketFilter::Action Filter(const DataBuffer& input,
--- a/security/nss/lib/ckfw/Makefile
+++ b/security/nss/lib/ckfw/Makefile
@@ -28,12 +28,8 @@ endif
 export:: private_export
 
 # can't do this in manifest.mn because OS_TARGET isn't defined there.
 ifeq (,$(filter-out WINNT WIN95,$(OS_TARGET)))
 ifdef NSS_BUILD_CAPI
 DIRS += capi
 endif
 endif
-
-#ifeq ($(OS_ARCH), Darwin)
-#DIRS += nssmkey
-#endif
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/Makefile
+++ /dev/null
@@ -1,72 +0,0 @@
-# 
-# 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 manifest.mn
-include $(CORE_DEPTH)/coreconf/config.mk
-include config.mk
-
-EXTRA_LIBS = \
-	$(DIST)/lib/$(LIB_PREFIX)nssckfw.$(LIB_SUFFIX) \
-	$(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX) \
-	$(DIST)/lib/$(LIB_PREFIX)nssb.$(LIB_SUFFIX) \
-	$(NULL)
-
-# can't do this in manifest.mn because OS_TARGET isn't defined there.
-ifeq (,$(filter-out WIN%,$(OS_TARGET)))
-
-ifdef NS_USE_GCC
-EXTRA_LIBS += \
-	-L$(NSPR_LIB_DIR) \
-	-lplc4 \
-	-lplds4 \
-	-lnspr4 \
-	$(NULL)
-else 
-EXTRA_SHARED_LIBS += \
-        $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
-        $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
-        $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
-        $(NULL)
-endif # NS_USE_GCC
-else
-
-EXTRA_LIBS += \
-	-L$(NSPR_LIB_DIR) \
-	-lplc4 \
-	-lplds4 \
-	-lnspr4 \
-	-framework Security \
-	-framework CoreServices \
-	$(NULL)
-endif
-
-
-include $(CORE_DEPTH)/coreconf/rules.mk
-
-# Generate certdata.c.
-generate:
-	perl certdata.perl < certdata.txt
-
-# This'll need some help from a build person.
-
-
-ifeq ($(OS_TARGET)$(OS_RELEASE), AIX4.1)
-DSO_LDOPTS              = -bM:SRE -bh:4 -bnoentry
-EXTRA_DSO_LDOPTS        = -lc
-MKSHLIB                 = xlC $(DSO_LDOPTS)
-
-$(SHARED_LIBRARY): $(OBJS)
-	@$(MAKE_OBJDIR)
-	rm -f $@
-	$(MKSHLIB) -o $@ $(OBJS) $(EXTRA_LIBS) $(EXTRA_DSO_LDOPTS)
-	chmod +x $@
-
-endif
-
-ifeq ($(OS_TARGET)$(OS_RELEASE), AIX4.2)
-LD      += -G
-endif 
-
-
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/README
+++ /dev/null
@@ -1,21 +0,0 @@
-This Cryptoki module provides acces to certs and keys stored in
-Macintosh key Ring.
-
-- It does not yet export PKCS #12 keys. To get this to work should be 
-  implemented using exporting the key object in PKCS #8 wrapped format.
-  PSM work needs to happen before this can be completed.
-- It does not import or export CA Root trust from the mac keychain.
-- It does not handle S/MIME objects (pkcs #7 in mac keychain terms?).
-- The AuthRoots don't show up on the default list.
-- Only RSA keys are supported currently.
-
-There are a number of things that have not been tested that other PKCS #11
-apps may need:
-- reading Modulus and Public Exponents from private keys and public keys.
-- storing public keys.
-- setting attributes other than CKA_ID and CKA_LABEL.
-
-Other TODOs:
-- Check for and plug memory leaks.
-- Need to map mac errors into something more intellegible than 
-  CKR_GENERAL_ERROR.
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/ckmk.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/* 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/. */
-
-#ifndef CKMK_H
-#define CKMK_H 1
-
-#include <Security/SecKeychainSearch.h>
-#include <Security/SecKeychainItem.h>
-#include <Security/SecKeychain.h>
-#include <Security/cssmtype.h>
-#include <Security/cssmapi.h>
-#include <Security/SecKey.h>
-#include <Security/SecCertificate.h>
-
-#define NTO
-
-#include "nssckmdt.h"
-#include "nssckfw.h"
-/*
- * I'm including this for access to the arena functions.
- * Looks like we should publish that API.
- */
-#ifndef BASE_H
-#include "base.h"
-#endif /* BASE_H */
-/*
- * This is where the Netscape extensions live, at least for now.
- */
-#ifndef CKT_H
-#include "ckt.h"
-#endif /* CKT_H */
-
-/*
- * statically defined raw objects. Allows us to data description objects
- * to this PKCS #11 module.
- */
-struct ckmkRawObjectStr {
-    CK_ULONG n;
-    const CK_ATTRIBUTE_TYPE *types;
-    const NSSItem *items;
-};
-typedef struct ckmkRawObjectStr ckmkRawObject;
-
-/*
- * Key/Cert Items
- */
-struct ckmkItemObjectStr {
-    SecKeychainItemRef itemRef;
-    SecItemClass itemClass;
-    PRBool hasID;
-    NSSItem modify;
-    NSSItem private;
-    NSSItem encrypt;
-    NSSItem decrypt;
-    NSSItem derive;
-    NSSItem sign;
-    NSSItem signRecover;
-    NSSItem verify;
-    NSSItem verifyRecover;
-    NSSItem wrap;
-    NSSItem unwrap;
-    NSSItem label;
-    NSSItem subject;
-    NSSItem issuer;
-    NSSItem serial;
-    NSSItem derCert;
-    NSSItem id;
-    NSSItem modulus;
-    NSSItem exponent;
-    NSSItem privateExponent;
-    NSSItem prime1;
-    NSSItem prime2;
-    NSSItem exponent1;
-    NSSItem exponent2;
-    NSSItem coefficient;
-};
-typedef struct ckmkItemObjectStr ckmkItemObject;
-
-typedef enum {
-    ckmkRaw,
-    ckmkItem,
-} ckmkObjectType;
-
-/*
- * all the various types of objects are abstracted away in cobject and
- * cfind as ckmkInternalObjects.
- */
-struct ckmkInternalObjectStr {
-    ckmkObjectType type;
-    union {
-        ckmkRawObject raw;
-        ckmkItemObject item;
-    } u;
-    CK_OBJECT_CLASS objClass;
-    NSSItem hashKey;
-    unsigned char hashKeyData[128];
-    NSSCKMDObject mdObject;
-};
-typedef struct ckmkInternalObjectStr ckmkInternalObject;
-
-/* our raw object data array */
-NSS_EXTERN_DATA ckmkInternalObject nss_ckmk_data[];
-NSS_EXTERN_DATA const PRUint32 nss_ckmk_nObjects;
-
-NSS_EXTERN_DATA const CK_VERSION nss_ckmk_CryptokiVersion;
-NSS_EXTERN_DATA const NSSUTF8 *nss_ckmk_ManufacturerID;
-NSS_EXTERN_DATA const NSSUTF8 *nss_ckmk_LibraryDescription;
-NSS_EXTERN_DATA const CK_VERSION nss_ckmk_LibraryVersion;
-NSS_EXTERN_DATA const NSSUTF8 *nss_ckmk_SlotDescription;
-NSS_EXTERN_DATA const CK_VERSION nss_ckmk_HardwareVersion;
-NSS_EXTERN_DATA const CK_VERSION nss_ckmk_FirmwareVersion;
-NSS_EXTERN_DATA const NSSUTF8 *nss_ckmk_TokenLabel;
-NSS_EXTERN_DATA const NSSUTF8 *nss_ckmk_TokenModel;
-NSS_EXTERN_DATA const NSSUTF8 *nss_ckmk_TokenSerialNumber;
-
-NSS_EXTERN_DATA const NSSCKMDInstance nss_ckmk_mdInstance;
-NSS_EXTERN_DATA const NSSCKMDSlot nss_ckmk_mdSlot;
-NSS_EXTERN_DATA const NSSCKMDToken nss_ckmk_mdToken;
-NSS_EXTERN_DATA const NSSCKMDMechanism nss_ckmk_mdMechanismRSA;
-
-NSS_EXTERN NSSCKMDSession *
-nss_ckmk_CreateSession(
-    NSSCKFWSession *fwSession,
-    CK_RV *pError);
-
-NSS_EXTERN NSSCKMDFindObjects *
-nss_ckmk_FindObjectsInit(
-    NSSCKFWSession *fwSession,
-    CK_ATTRIBUTE_PTR pTemplate,
-    CK_ULONG ulAttributeCount,
-    CK_RV *pError);
-
-/*
- * Object Utilities
- */
-NSS_EXTERN NSSCKMDObject *
-nss_ckmk_CreateMDObject(
-    NSSArena *arena,
-    ckmkInternalObject *io,
-    CK_RV *pError);
-
-NSS_EXTERN NSSCKMDObject *
-nss_ckmk_CreateObject(
-    NSSCKFWSession *fwSession,
-    CK_ATTRIBUTE_PTR pTemplate,
-    CK_ULONG ulAttributeCount,
-    CK_RV *pError);
-
-NSS_EXTERN const NSSItem *
-nss_ckmk_FetchAttribute(
-    ckmkInternalObject *io,
-    CK_ATTRIBUTE_TYPE type,
-    CK_RV *pError);
-
-NSS_EXTERN void
-nss_ckmk_DestroyInternalObject(
-    ckmkInternalObject *io);
-
-unsigned char *
-nss_ckmk_DERUnwrap(
-    unsigned char *src,
-    int size,
-    int *outSize,
-    unsigned char **next);
-
-CK_ULONG
-nss_ckmk_GetULongAttribute(
-    CK_ATTRIBUTE_TYPE type,
-    CK_ATTRIBUTE *template,
-    CK_ULONG templateSize,
-    CK_RV *pError);
-
-#define NSS_CKMK_ARRAY_SIZE(x) ((sizeof(x)) / (sizeof((x)[0])))
-
-#ifdef DEBUG
-#define CKMK_MACERR(str, err) cssmPerror(str, err)
-#else
-#define CKMK_MACERR(str, err)
-#endif
-
-#endif
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/ckmkver.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/* 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/. */
-/* Library identity and versioning */
-
-#include "nssmkey.h"
-
-#if defined(DEBUG)
-#define _DEBUG_STRING " (debug)"
-#else
-#define _DEBUG_STRING ""
-#endif
-
-/*
- * Version information
- */
-const char __nss_ckmk_version[] = "Version: NSS Access to the MAC OS X Key Ring " NSS_CKMK_LIBRARY_VERSION _DEBUG_STRING;
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/config.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-# 
-# 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/.
-
-ifdef BUILD_IDG
-DEFINES += -DNSSDEBUG
-endif
-
-ifdef NS_USE_CKFW_TRACE
-DEFINES += -DTRACE
-endif
-
-#
-#  Override TARGETS variable so that only static libraries
-#  are specifed as dependencies within rules.mk.
-#
-
-TARGETS        = $(LIBRARY)
-SHARED_LIBRARY =
-IMPORT_LIBRARY =
-PROGRAM        =
-
-
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/manchor.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/* 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/. */
-
-/*
- * nssmkey/manchor.c
- *
- * This file "anchors" the actual cryptoki entry points in this module's
- * shared library, which is required for dynamic loading.  See the
- * comments in nssck.api for more information.
- */
-
-#include "ckmk.h"
-
-#define MODULE_NAME ckmk
-#define INSTANCE_NAME (NSSCKMDInstance *)&nss_ckmk_mdInstance
-#include "nssck.api"
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/manifest.mn
+++ /dev/null
@@ -1,33 +0,0 @@
-# 
-# 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/.
-
-CORE_DEPTH = ../../../..
-
-MODULE = nss
-MAPFILE = $(OBJDIR)/nssmkey.def
-
-EXPORTS =		\
-	nssmkey.h	\
-	$(NULL)
-
-CSRCS =			\
-	manchor.c	\
-	mconstants.c	\
-	mfind.c		\
-	minst.c 	\
-	mobject.c	\
-	mrsa.c		\
-	msession.c	\
-	mslot.c		\
-	mtoken.c	\
-	ckmkver.c	\
-	staticobj.c	\
-	$(NULL)
-
-REQUIRES = nspr
-
-LIBRARY_NAME = nssmkey
-
-#EXTRA_SHARED_LIBS = -L$(DIST)/lib -lnssckfw -lnssb -lplc4 -lplds4
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/mconstants.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* 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/. */
-
-/*
- * nssmkey/constants.c
- *
- * Identification and other constants, all collected here in one place.
- */
-
-#ifndef NSSBASET_H
-#include "nssbaset.h"
-#endif /* NSSBASET_H */
-
-#ifndef NSSCKT_H
-#include "nssckt.h"
-#endif /* NSSCKT_H */
-
-#include "nssmkey.h"
-
-NSS_IMPLEMENT_DATA const CK_VERSION
-    nss_ckmk_CryptokiVersion = {
-        NSS_CKMK_CRYPTOKI_VERSION_MAJOR,
-        NSS_CKMK_CRYPTOKI_VERSION_MINOR
-    };
-
-NSS_IMPLEMENT_DATA const NSSUTF8 *
-    nss_ckmk_ManufacturerID = (NSSUTF8 *)"Mozilla Foundation";
-
-NSS_IMPLEMENT_DATA const NSSUTF8 *
-    nss_ckmk_LibraryDescription = (NSSUTF8 *)"NSS Access to Mac OS X Key Ring";
-
-NSS_IMPLEMENT_DATA const CK_VERSION
-    nss_ckmk_LibraryVersion = {
-        NSS_CKMK_LIBRARY_VERSION_MAJOR,
-        NSS_CKMK_LIBRARY_VERSION_MINOR
-    };
-
-NSS_IMPLEMENT_DATA const NSSUTF8 *
-    nss_ckmk_SlotDescription = (NSSUTF8 *)"Mac OS X Key Ring";
-
-NSS_IMPLEMENT_DATA const CK_VERSION
-    nss_ckmk_HardwareVersion = {
-        NSS_CKMK_HARDWARE_VERSION_MAJOR,
-        NSS_CKMK_HARDWARE_VERSION_MINOR
-    };
-
-NSS_IMPLEMENT_DATA const CK_VERSION
-    nss_ckmk_FirmwareVersion = {
-        NSS_CKMK_FIRMWARE_VERSION_MAJOR,
-        NSS_CKMK_FIRMWARE_VERSION_MINOR
-    };
-
-NSS_IMPLEMENT_DATA const NSSUTF8 *
-    nss_ckmk_TokenLabel = (NSSUTF8 *)"Mac OS X Key Ring";
-
-NSS_IMPLEMENT_DATA const NSSUTF8 *
-    nss_ckmk_TokenModel = (NSSUTF8 *)"1";
-
-NSS_IMPLEMENT_DATA const NSSUTF8 *
-    nss_ckmk_TokenSerialNumber = (NSSUTF8 *)"1";
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/mfind.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/* 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/. */
-
-#ifndef CKMK_H
-#include "ckmk.h"
-#endif /* CKMK_H */
-
-/*
- * nssmkey/mfind.c
- *
- * This file implements the NSSCKMDFindObjects object for the
- * "nssmkey" cryptoki module.
- */
-
-struct ckmkFOStr {
-    NSSArena *arena;
-    CK_ULONG n;
-    CK_ULONG i;
-    ckmkInternalObject **objs;
-};
-
-static void
-ckmk_mdFindObjects_Final(
-    NSSCKMDFindObjects *mdFindObjects,
-    NSSCKFWFindObjects *fwFindObjects,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    struct ckmkFOStr *fo = (struct ckmkFOStr *)mdFindObjects->etc;
-    NSSArena *arena = fo->arena;
-    PRUint32 i;
-
-    /* walk down an free the unused 'objs' */
-    for (i = fo->i; i < fo->n; i++) {
-        nss_ckmk_DestroyInternalObject(fo->objs[i]);
-    }
-
-    nss_ZFreeIf(fo->objs);
-    nss_ZFreeIf(fo);
-    nss_ZFreeIf(mdFindObjects);
-    if ((NSSArena *)NULL != arena) {
-        NSSArena_Destroy(arena);
-    }
-
-    return;
-}
-
-static NSSCKMDObject *
-ckmk_mdFindObjects_Next(
-    NSSCKMDFindObjects *mdFindObjects,
-    NSSCKFWFindObjects *fwFindObjects,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    NSSArena *arena,
-    CK_RV *pError)
-{
-    struct ckmkFOStr *fo = (struct ckmkFOStr *)mdFindObjects->etc;
-    ckmkInternalObject *io;
-
-    if (fo->i == fo->n) {
-        *pError = CKR_OK;
-        return (NSSCKMDObject *)NULL;
-    }
-
-    io = fo->objs[fo->i];
-    fo->i++;
-
-    return nss_ckmk_CreateMDObject(arena, io, pError);
-}
-
-static CK_BBOOL
-ckmk_attrmatch(
-    CK_ATTRIBUTE_PTR a,
-    ckmkInternalObject *o)
-{
-    PRBool prb;
-    const NSSItem *b;
-    CK_RV error;
-
-    b = nss_ckmk_FetchAttribute(o, a->type, &error);
-    if (b == NULL) {
-        return CK_FALSE;
-    }
-
-    if (a->ulValueLen != b->size) {
-        /* match a decoded serial number */
-        if ((a->type == CKA_SERIAL_NUMBER) && (a->ulValueLen < b->size)) {
-            int len;
-            unsigned char *data;
-
-            data = nss_ckmk_DERUnwrap(b->data, b->size, &len, NULL);
-            if ((len == a->ulValueLen) &&
-                nsslibc_memequal(a->pValue, data, len, (PRStatus *)NULL)) {
-                return CK_TRUE;
-            }
-        }
-        return CK_FALSE;
-    }
-
-    prb = nsslibc_memequal(a->pValue, b->data, b->size, (PRStatus *)NULL);
-
-    if (PR_TRUE == prb) {
-        return CK_TRUE;
-    } else {
-        return CK_FALSE;
-    }
-}
-
-static CK_BBOOL
-ckmk_match(
-    CK_ATTRIBUTE_PTR pTemplate,
-    CK_ULONG ulAttributeCount,
-    ckmkInternalObject *o)
-{
-    CK_ULONG i;
-
-    for (i = 0; i < ulAttributeCount; i++) {
-        if (CK_FALSE == ckmk_attrmatch(&pTemplate[i], o)) {
-            return CK_FALSE;
-        }
-    }
-
-    /* Every attribute passed */
-    return CK_TRUE;
-}
-
-#define CKMK_ITEM_CHUNK 20
-
-#define PUT_OBJECT(obj, err, size, count, list)                             \
-    {                                                                       \
-        if (count >= size) {                                                \
-            (list) = (list) ? nss_ZREALLOCARRAY(list, ckmkInternalObject *, \
-                                                ((size) +                   \
-                                                 CKMK_ITEM_CHUNK))          \
-                            : nss_ZNEWARRAY(NULL, ckmkInternalObject *,     \
-                                            ((size) +                       \
-                                             CKMK_ITEM_CHUNK));             \
-            if ((ckmkInternalObject **)NULL == list) {                      \
-                err = CKR_HOST_MEMORY;                                      \
-                goto loser;                                                 \
-            }                                                               \
-            (size) += CKMK_ITEM_CHUNK;                                      \
-        }                                                                   \
-        (list)[count] = (obj);                                              \
-        count++;                                                            \
-    }
-
-/* find all the certs that represent the appropriate object (cert, priv key, or
- *  pub key) in the cert store.
- */
-static PRUint32
-collect_class(
-    CK_OBJECT_CLASS objClass,
-    SecItemClass itemClass,
-    CK_ATTRIBUTE_PTR pTemplate,
-    CK_ULONG ulAttributeCount,
-    ckmkInternalObject ***listp,
-    PRUint32 *sizep,
-    PRUint32 count,
-    CK_RV *pError)
-{
-    ckmkInternalObject *next = NULL;
-    SecKeychainSearchRef searchRef = 0;
-    SecKeychainItemRef itemRef = 0;
-    OSStatus error;
-
-    /* future, build the attribute list based on the template
-     * so we can refine the search */
-    error = SecKeychainSearchCreateFromAttributes(
-        NULL, itemClass, NULL, &searchRef);
-
-    while (noErr == SecKeychainSearchCopyNext(searchRef, &itemRef)) {
-        /* if we don't have an internal object structure, get one */
-        if ((ckmkInternalObject *)NULL == next) {
-            next = nss_ZNEW(NULL, ckmkInternalObject);
-            if ((ckmkInternalObject *)NULL == next) {
-                *pError = CKR_HOST_MEMORY;
-                goto loser;
-            }
-        }
-        /* fill in the relevant object data */
-        next->type = ckmkItem;
-        next->objClass = objClass;
-        next->u.item.itemRef = itemRef;
-        next->u.item.itemClass = itemClass;
-
-        /* see if this is one of the objects we are looking for */
-        if (CK_TRUE == ckmk_match(pTemplate, ulAttributeCount, next)) {
-            /* yes, put it on the list */
-            PUT_OBJECT(next, *pError, *sizep, count, *listp);
-            next = NULL; /* this one is on the list, need to allocate a new one now */
-        } else {
-            /* no , release the current item and clear out the structure for reuse */
-            CFRelease(itemRef);
-            /* don't cache the values we just loaded */
-            nsslibc_memset(next, 0, sizeof(*next));
-        }
-    }
-loser:
-    if (searchRef) {
-        CFRelease(searchRef);
-    }
-    nss_ZFreeIf(next);
-    return count;
-}
-
-static PRUint32
-collect_objects(
-    CK_ATTRIBUTE_PTR pTemplate,
-    CK_ULONG ulAttributeCount,
-    ckmkInternalObject ***listp,
-    CK_RV *pError)
-{
-    PRUint32 i;
-    PRUint32 count = 0;
-    PRUint32 size = 0;
-    CK_OBJECT_CLASS objClass;
-
-    /*
-     * first handle the static build in objects (if any)
-     */
-    for (i = 0; i < nss_ckmk_nObjects; i++) {
-        ckmkInternalObject *o = (ckmkInternalObject *)&nss_ckmk_data[i];
-
-        if (CK_TRUE == ckmk_match(pTemplate, ulAttributeCount, o)) {
-            PUT_OBJECT(o, *pError, size, count, *listp);
-        }
-    }
-
-    /*
-     * now handle the various object types
-     */
-    objClass = nss_ckmk_GetULongAttribute(CKA_CLASS,
-                                          pTemplate, ulAttributeCount, pError);
-    if (CKR_OK != *pError) {
-        objClass = CK_INVALID_HANDLE;
-    }
-    *pError = CKR_OK;
-    switch (objClass) {
-        case CKO_CERTIFICATE:
-            count = collect_class(objClass, kSecCertificateItemClass,
-                                  pTemplate, ulAttributeCount, listp,
-                                  &size, count, pError);
-            break;
-        case CKO_PUBLIC_KEY:
-            count = collect_class(objClass, CSSM_DL_DB_RECORD_PUBLIC_KEY,
-                                  pTemplate, ulAttributeCount, listp,
-                                  &size, count, pError);
-            break;
-        case CKO_PRIVATE_KEY:
-            count = collect_class(objClass, CSSM_DL_DB_RECORD_PRIVATE_KEY,
-                                  pTemplate, ulAttributeCount, listp,
-                                  &size, count, pError);
-            break;
-        /* all of them */
-        case CK_INVALID_HANDLE:
-            count = collect_class(CKO_CERTIFICATE, kSecCertificateItemClass,
-                                  pTemplate, ulAttributeCount, listp,
-                                  &size, count, pError);
-            count = collect_class(CKO_PUBLIC_KEY, CSSM_DL_DB_RECORD_PUBLIC_KEY,
-                                  pTemplate, ulAttributeCount, listp,
-                                  &size, count, pError);
-            count = collect_class(CKO_PUBLIC_KEY, CSSM_DL_DB_RECORD_PRIVATE_KEY,
-                                  pTemplate, ulAttributeCount, listp,
-                                  &size, count, pError);
-            break;
-        default:
-            break;
-    }
-    if (CKR_OK != *pError) {
-        goto loser;
-    }
-
-    return count;
-loser:
-    nss_ZFreeIf(*listp);
-    return 0;
-}
-
-NSS_IMPLEMENT NSSCKMDFindObjects *
-nss_ckmk_FindObjectsInit(
-    NSSCKFWSession *fwSession,
-    CK_ATTRIBUTE_PTR pTemplate,
-    CK_ULONG ulAttributeCount,
-    CK_RV *pError)
-{
-    /* This could be made more efficient.  I'm rather rushed. */
-    NSSArena *arena;
-    NSSCKMDFindObjects *rv = (NSSCKMDFindObjects *)NULL;
-    struct ckmkFOStr *fo = (struct ckmkFOStr *)NULL;
-    ckmkInternalObject **temp = (ckmkInternalObject **)NULL;
-
-    arena = NSSArena_Create();
-    if ((NSSArena *)NULL == arena) {
-        goto loser;
-    }
-
-    rv = nss_ZNEW(arena, NSSCKMDFindObjects);
-    if ((NSSCKMDFindObjects *)NULL == rv) {
-        *pError = CKR_HOST_MEMORY;
-        goto loser;
-    }
-
-    fo = nss_ZNEW(arena, struct ckmkFOStr);
-    if ((struct ckmkFOStr *)NULL == fo) {
-        *pError = CKR_HOST_MEMORY;
-        goto loser;
-    }
-
-    fo->arena = arena;
-    /* fo->n and fo->i are already zero */
-
-    rv->etc = (void *)fo;
-    rv->Final = ckmk_mdFindObjects_Final;
-    rv->Next = ckmk_mdFindObjects_Next;
-    rv->null = (void *)NULL;
-
-    fo->n = collect_objects(pTemplate, ulAttributeCount, &temp, pError);
-    if (*pError != CKR_OK) {
-        goto loser;
-    }
-
-    fo->objs = nss_ZNEWARRAY(arena, ckmkInternalObject *, fo->n);
-    if ((ckmkInternalObject **)NULL == fo->objs) {
-        *pError = CKR_HOST_MEMORY;
-        goto loser;
-    }
-
-    (void)nsslibc_memcpy(fo->objs, temp, sizeof(ckmkInternalObject *) * fo->n);
-    nss_ZFreeIf(temp);
-    temp = (ckmkInternalObject **)NULL;
-
-    return rv;
-
-loser:
-    nss_ZFreeIf(temp);
-    nss_ZFreeIf(fo);
-    nss_ZFreeIf(rv);
-    if ((NSSArena *)NULL != arena) {
-        NSSArena_Destroy(arena);
-    }
-    return (NSSCKMDFindObjects *)NULL;
-}
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/minst.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/* 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 "ckmk.h"
-
-/*
- * nssmkey/minstance.c
- *
- * This file implements the NSSCKMDInstance object for the
- * "nssmkey" cryptoki module.
- */
-
-/*
- * NSSCKMDInstance methods
- */
-
-static CK_ULONG
-ckmk_mdInstance_GetNSlots(
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    return (CK_ULONG)1;
-}
-
-static CK_VERSION
-ckmk_mdInstance_GetCryptokiVersion(
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    return nss_ckmk_CryptokiVersion;
-}
-
-static NSSUTF8 *
-ckmk_mdInstance_GetManufacturerID(
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    return (NSSUTF8 *)nss_ckmk_ManufacturerID;
-}
-
-static NSSUTF8 *
-ckmk_mdInstance_GetLibraryDescription(
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    return (NSSUTF8 *)nss_ckmk_LibraryDescription;
-}
-
-static CK_VERSION
-ckmk_mdInstance_GetLibraryVersion(
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    return nss_ckmk_LibraryVersion;
-}
-
-static CK_RV
-ckmk_mdInstance_GetSlots(
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    NSSCKMDSlot *slots[])
-{
-    slots[0] = (NSSCKMDSlot *)&nss_ckmk_mdSlot;
-    return CKR_OK;
-}
-
-static CK_BBOOL
-ckmk_mdInstance_ModuleHandlesSessionObjects(
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    /* we don't want to allow any session object creation, at least
-     * until we can investigate whether or not we can use those objects
-     */
-    return CK_TRUE;
-}
-
-NSS_IMPLEMENT_DATA const NSSCKMDInstance
-    nss_ckmk_mdInstance = {
-        (void *)NULL, /* etc */
-        NULL,         /* Initialize */
-        NULL,         /* Finalize */
-        ckmk_mdInstance_GetNSlots,
-        ckmk_mdInstance_GetCryptokiVersion,
-        ckmk_mdInstance_GetManufacturerID,
-        ckmk_mdInstance_GetLibraryDescription,
-        ckmk_mdInstance_GetLibraryVersion,
-        ckmk_mdInstance_ModuleHandlesSessionObjects,
-        /*NULL, /* HandleSessionObjects */
-        ckmk_mdInstance_GetSlots,
-        NULL,        /* WaitForSlotEvent */
-        (void *)NULL /* null terminator */
-    };
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/mobject.c
+++ /dev/null
@@ -1,1861 +0,0 @@
-/* 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 "ckmk.h"
-#include "nssbase.h"
-
-#include "secdert.h" /* for DER_INTEGER */
-#include "string.h"
-
-/* asn1 encoder (to build pkcs#8 blobs) */
-#include <seccomon.h>
-#include <secitem.h>
-#include <blapit.h>
-#include <secoid.h>
-#include <secasn1.h>
-
-/* for importing the keys */
-#include <CoreFoundation/CoreFoundation.h>
-#include <security/SecImportExport.h>
-
-/*
- * nssmkey/mobject.c
- *
- * This file implements the NSSCKMDObject object for the
- * "nssmkey" cryptoki module.
- */
-
-const CK_ATTRIBUTE_TYPE certAttrs[] = {
-    CKA_CLASS,
-    CKA_TOKEN,
-    CKA_PRIVATE,
-    CKA_MODIFIABLE,
-    CKA_LABEL,
-    CKA_CERTIFICATE_TYPE,
-    CKA_SUBJECT,
-    CKA_ISSUER,
-    CKA_SERIAL_NUMBER,
-    CKA_VALUE
-};
-const PRUint32 certAttrsCount = NSS_CKMK_ARRAY_SIZE(certAttrs);
-
-/* private keys, for now only support RSA */
-const CK_ATTRIBUTE_TYPE privKeyAttrs[] = {
-    CKA_CLASS,
-    CKA_TOKEN,
-    CKA_PRIVATE,
-    CKA_MODIFIABLE,
-    CKA_LABEL,
-    CKA_KEY_TYPE,
-    CKA_DERIVE,
-    CKA_LOCAL,
-    CKA_SUBJECT,
-    CKA_SENSITIVE,
-    CKA_DECRYPT,
-    CKA_SIGN,
-    CKA_SIGN_RECOVER,
-    CKA_UNWRAP,
-    CKA_EXTRACTABLE,
-    CKA_ALWAYS_SENSITIVE,
-    CKA_NEVER_EXTRACTABLE,
-    CKA_MODULUS,
-    CKA_PUBLIC_EXPONENT,
-};
-const PRUint32 privKeyAttrsCount = NSS_CKMK_ARRAY_SIZE(privKeyAttrs);
-
-/* public keys, for now only support RSA */
-const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = {
-    CKA_CLASS,
-    CKA_TOKEN,
-    CKA_PRIVATE,
-    CKA_MODIFIABLE,
-    CKA_LABEL,
-    CKA_KEY_TYPE,
-    CKA_DERIVE,
-    CKA_LOCAL,
-    CKA_SUBJECT,
-    CKA_ENCRYPT,
-    CKA_VERIFY,
-    CKA_VERIFY_RECOVER,
-    CKA_WRAP,
-    CKA_MODULUS,
-    CKA_PUBLIC_EXPONENT,
-};
-const PRUint32 pubKeyAttrsCount = NSS_CKMK_ARRAY_SIZE(pubKeyAttrs);
-static const CK_BBOOL ck_true = CK_TRUE;
-static const CK_BBOOL ck_false = CK_FALSE;
-static const CK_CERTIFICATE_TYPE ckc_x509 = CKC_X_509;
-static const CK_KEY_TYPE ckk_rsa = CKK_RSA;
-static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
-static const CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
-static const CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY;
-static const NSSItem ckmk_trueItem = {
-    (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL)
-};
-static const NSSItem ckmk_falseItem = {
-    (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL)
-};
-static const NSSItem ckmk_x509Item = {
-    (void *)&ckc_x509, (PRUint32)sizeof(CK_CERTIFICATE_TYPE)
-};
-static const NSSItem ckmk_rsaItem = {
-    (void *)&ckk_rsa, (PRUint32)sizeof(CK_KEY_TYPE)
-};
-static const NSSItem ckmk_certClassItem = {
-    (void *)&cko_certificate, (PRUint32)sizeof(CK_OBJECT_CLASS)
-};
-static const NSSItem ckmk_privKeyClassItem = {
-    (void *)&cko_private_key, (PRUint32)sizeof(CK_OBJECT_CLASS)
-};
-static const NSSItem ckmk_pubKeyClassItem = {
-    (void *)&cko_public_key, (PRUint32)sizeof(CK_OBJECT_CLASS)
-};
-static const NSSItem ckmk_emptyItem = {
-    (void *)&ck_true, 0
-};
-
-/*
- * these are utilities. The chould be moved to a new utilities file.
- */
-#ifdef DEBUG
-static void
-itemdump(char *str, void *data, int size, CK_RV error)
-{
-    unsigned char *ptr = (unsigned char *)data;
-    int i;
-    fprintf(stderr, str);
-    for (i = 0; i < size; i++) {
-        fprintf(stderr, "%02x ", (unsigned int)ptr[i]);
-    }
-    fprintf(stderr, " (error = %d)\n", (int)error);
-}
-#endif
-
-/*
- * unwrap a single DER value
- * now that we have util linked in, we should probably use
- * the ANS1_Decoder for this work...
- */
-unsigned char *
-nss_ckmk_DERUnwrap(
-    unsigned char *src,
-    int size,
-    int *outSize,
-    unsigned char **next)
-{
-    unsigned char *start = src;
-    unsigned int len = 0;
-
-    /* initialize error condition return values */
-    *outSize = 0;
-    if (next) {
-        *next = src;
-    }
-
-    if (size < 2) {
-        return start;
-    }
-    src++; /* skip the tag -- should check it against an expected value! */
-    len = (unsigned)*src++;
-    if (len & 0x80) {
-        int count = len & 0x7f;
-        len = 0;
-
-        if (count + 2 > size) {
-            return start;
-        }
-        while (count-- > 0) {
-            len = (len << 8) | (unsigned)*src++;
-        }
-    }
-    if (len + (src - start) > (unsigned int)size) {
-        return start;
-    }
-    if (next) {
-        *next = src + len;
-    }
-    *outSize = len;
-
-    return src;
-}
-
-/*
- * get an attribute from a template. Value is returned in NSS item.
- * data for the item is owned by the template.
- */
-CK_RV
-nss_ckmk_GetAttribute(
-    CK_ATTRIBUTE_TYPE type,
-    CK_ATTRIBUTE *template,
-    CK_ULONG templateSize,
-    NSSItem *item)
-{
-    CK_ULONG i;
-
-    for (i = 0; i < templateSize; i++) {
-        if (template[i].type == type) {
-            item->data = template[i].pValue;
-            item->size = template[i].ulValueLen;
-            return CKR_OK;
-        }
-    }
-    return CKR_TEMPLATE_INCOMPLETE;
-}
-
-/*
- * get an attribute which is type CK_ULONG.
- */
-CK_ULONG
-nss_ckmk_GetULongAttribute(
-    CK_ATTRIBUTE_TYPE type,
-    CK_ATTRIBUTE *template,
-    CK_ULONG templateSize,
-    CK_RV *pError)
-{
-    NSSItem item;
-
-    *pError = nss_ckmk_GetAttribute(type, template, templateSize, &item);
-    if (CKR_OK != *pError) {
-        return (CK_ULONG)0;
-    }
-    if (item.size != sizeof(CK_ULONG)) {
-        *pError = CKR_ATTRIBUTE_VALUE_INVALID;
-        return (CK_ULONG)0;
-    }
-    return *(CK_ULONG *)item.data;
-}
-
-/*
- * get an attribute which is type CK_BBOOL.
- */
-CK_BBOOL
-nss_ckmk_GetBoolAttribute(
-    CK_ATTRIBUTE_TYPE type,
-    CK_ATTRIBUTE *template,
-    CK_ULONG templateSize,
-    CK_BBOOL defaultBool)
-{
-    NSSItem item;
-    CK_RV error;
-
-    error = nss_ckmk_GetAttribute(type, template, templateSize, &item);
-    if (CKR_OK != error) {
-        return defaultBool;
-    }
-    if (item.size != sizeof(CK_BBOOL)) {
-        return defaultBool;
-    }
-    return *(CK_BBOOL *)item.data;
-}
-
-/*
- * get an attribute as a NULL terminated string. Caller is responsible to
- * free the string.
- */
-char *
-nss_ckmk_GetStringAttribute(
-    CK_ATTRIBUTE_TYPE type,
-    CK_ATTRIBUTE *template,
-    CK_ULONG templateSize,
-    CK_RV *pError)
-{
-    NSSItem item;
-    char *str;
-
-    /* get the attribute */
-    *pError = nss_ckmk_GetAttribute(type, template, templateSize, &item);
-    if (CKR_OK != *pError) {
-        return (char *)NULL;
-    }
-    /* make sure it is null terminated */
-    str = nss_ZNEWARRAY(NULL, char, item.size + 1);
-    if ((char *)NULL == str) {
-        *pError = CKR_HOST_MEMORY;
-        return (char *)NULL;
-    }
-
-    nsslibc_memcpy(str, item.data, item.size);
-    str[item.size] = 0;
-
-    return str;
-}
-
-/*
- * Apple doesn't seem to have a public interface to the DER encoder,
- * wip out a quick one for integers only (anything more complicated,
- * we should use one of the 3 in lib/util). -- especially since we
- * now link with it.
- */
-static CK_RV
-ckmk_encodeInt(NSSItem *dest, void *src, int srcLen)
-{
-    int dataLen = srcLen;
-    int lenLen = 1;
-    int encLen;
-    int isSigned = 0;
-    int offset = 0;
-    unsigned char *data = NULL;
-    int i;
-
-    if (*(unsigned char *)src & 0x80) {
-        dataLen++;
-        isSigned = 1;
-    }
-
-    /* calculate the length of the length specifier */
-    /* (NOTE: destroys dataLen value) */
-    if (dataLen > 0x7f) {
-        do {
-            lenLen++;
-            dataLen >>= 8;
-        } while (dataLen);
-    }
-
-    /* calculate our total length */
-    dataLen = isSigned + srcLen;
-    encLen = 1 + lenLen + dataLen;
-    data = nss_ZNEWARRAY(NULL, unsigned char, encLen);
-    if ((unsigned char *)NULL == data) {
-        return CKR_HOST_MEMORY;
-    }
-    data[0] = DER_INTEGER;
-    if (1 == lenLen) {
-        data[1] = dataLen;
-    } else {
-        data[1] = 0x80 + lenLen;
-        for (i = 0; i < lenLen; i++) {
-            data[i + 1] = ((dataLen >> ((lenLen -
-                                         i - 1) *
-                                        8)) &
-                           0xff);
-        }
-    }
-    offset = lenLen + 1;
-
-    if (isSigned) {
-        data[offset++] = 0;
-    }
-    nsslibc_memcpy(&data[offset], src, srcLen);
-    dest->data = data;
-    dest->size = encLen;
-    return CKR_OK;
-}
-
-/*
- * Get a Keyring attribute. If content is set to true, then we get the
- * content, not the attribute.
- */
-static CK_RV
-ckmk_GetCommonAttribute(
-    ckmkInternalObject *io,
-    SecItemAttr itemAttr,
-    PRBool content,
-    NSSItem *item,
-    char *dbString)
-{
-    SecKeychainAttributeList *attrList = NULL;
-    SecKeychainAttributeInfo attrInfo;
-    PRUint32 len = 0;
-    PRUint32 dataLen = 0;
-    PRUint32 attrFormat = 0;
-    void *dataVal = 0;
-    void *out = NULL;
-    CK_RV error = CKR_OK;
-    OSStatus macErr;
-
-    attrInfo.count = 1;
-    attrInfo.tag = &itemAttr;
-    attrInfo.format = &attrFormat;
-
-    macErr = SecKeychainItemCopyAttributesAndData(io->u.item.itemRef,
-                                                  &attrInfo, NULL, &attrList, &len, &out);
-    if (noErr != macErr) {
-        CKMK_MACERR(dbString, macErr);
-        return CKR_ATTRIBUTE_TYPE_INVALID;
-    }
-    dataLen = content ? len : attrList->attr->length;
-    dataVal = content ? out : attrList->attr->data;
-
-    /* Apple's documentation says this value is DER Encoded, but it clearly isn't
-     * der encode it before we ship it back off to NSS
-     */
-    if (kSecSerialNumberItemAttr == itemAttr) {
-        error = ckmk_encodeInt(item, dataVal, dataLen);
-        goto loser; /* logically 'done' if error == CKR_OK */
-    }
-    item->data = nss_ZNEWARRAY(NULL, char, dataLen);
-    if (NULL == item->data) {
-        error = CKR_HOST_MEMORY;
-        goto loser;
-    }
-    nsslibc_memcpy(item->data, dataVal, dataLen);
-    item->size = dataLen;
-
-loser:
-    SecKeychainItemFreeAttributesAndData(attrList, out);
-    return error;
-}
-
-/*
- * change an attribute (does not operate on the content).
- */
-static CK_RV
-ckmk_updateAttribute(
-    SecKeychainItemRef itemRef,
-    SecItemAttr itemAttr,
-    void *data,
-    PRUint32 len,
-    char *dbString)
-{
-    SecKeychainAttributeList attrList;
-    SecKeychainAttribute attrAttr;
-    OSStatus macErr;
-    CK_RV error = CKR_OK;
-
-    attrList.count = 1;
-    attrList.attr = &attrAttr;
-    attrAttr.tag = itemAttr;
-    attrAttr.data = data;
-    attrAttr.length = len;
-    macErr = SecKeychainItemModifyAttributesAndData(itemRef, &attrList, 0, NULL);
-    if (noErr != macErr) {
-        CKMK_MACERR(dbString, macErr);
-        error = CKR_ATTRIBUTE_TYPE_INVALID;
-    }
-    return error;
-}
-
-/*
- * get an attribute (does not operate on the content)
- */
-static CK_RV
-ckmk_GetDataAttribute(
-    ckmkInternalObject *io,
-    SecItemAttr itemAttr,
-    NSSItem *item,
-    char *dbString)
-{
-    return ckmk_GetCommonAttribute(io, itemAttr, PR_FALSE, item, dbString);
-}
-
-/*
- * get an attribute we know is a BOOL.
- */
-static CK_RV
-ckmk_GetBoolAttribute(
-    ckmkInternalObject *io,
-    SecItemAttr itemAttr,
-    NSSItem *item,
-    char *dbString)
-{
-    SecKeychainAttribute attr;
-    SecKeychainAttributeList attrList;
-    CK_BBOOL *boolp = NULL;
-    PRUint32 len = 0;
-    ;
-    void *out = NULL;
-    CK_RV error = CKR_OK;
-    OSStatus macErr;
-
-    attr.tag = itemAttr;
-    attr.length = 0;
-    attr.data = NULL;
-    attrList.count = 1;
-    attrList.attr = &attr;
-
-    boolp = nss_ZNEW(NULL, CK_BBOOL);
-    if ((CK_BBOOL *)NULL == boolp) {
-        error = CKR_HOST_MEMORY;
-        goto loser;
-    }
-
-    macErr = SecKeychainItemCopyContent(io->u.item.itemRef, NULL,
-                                        &attrList, &len, &out);
-    if (noErr != macErr) {
-        CKMK_MACERR(dbString, macErr);
-        error = CKR_ATTRIBUTE_TYPE_INVALID;
-        goto loser;
-    }
-    if (sizeof(PRUint32) != attr.length) {
-        error = CKR_ATTRIBUTE_TYPE_INVALID;
-        goto loser;
-    }
-    *boolp = *(PRUint32 *)attr.data ? 1 : 0;
-    item->data = boolp;
-    boolp = NULL;
-    item->size = sizeof(CK_BBOOL);
-
-loser:
-    nss_ZFreeIf(boolp);
-    SecKeychainItemFreeContent(&attrList, out);
-    return error;
-}
-
-/*
- * macros for fetching attributes into a cache and returning the
- * appropriate value. These operate inside switch statements
- */
-#define CKMK_HANDLE_ITEM(func, io, type, loc, item, error, str) \
-    if (0 == (item)->loc.size) {                                \
-        error = func(io, type, &(item)->loc, str);              \
-    }                                                           \
-    return (CKR_OK == (error)) ? &(item)->loc : NULL;
-
-#define CKMK_HANDLE_OPT_ITEM(func, io, type, loc, item, error, str) \
-    if (0 == (item)->loc.size) {                                    \
-        (void)func(io, type, &(item)->loc, str);                    \
-    }                                                               \
-    return &(item)->loc;
-
-#define CKMK_HANDLE_BOOL_ITEM(io, type, loc, item, error, str) \
-    CKMK_HANDLE_ITEM(ckmk_GetBoolAttribute, io, type, loc, item, error, str)
-#define CKMK_HANDLE_DATA_ITEM(io, type, loc, item, error, str) \
-    CKMK_HANDLE_ITEM(ckmk_GetDataAttribute, io, type, loc, item, error, str)
-#define CKMK_HANDLE_OPT_DATA_ITEM(io, type, loc, item, error, str) \
-    CKMK_HANDLE_OPT_ITEM(ckmk_GetDataAttribute, io, type, loc, item, error, str)
-
-/*
- * fetch the unique identifier for each object type.
- */
-static void
-ckmk_FetchHashKey(
-    ckmkInternalObject *io)
-{
-    NSSItem *key = &io->hashKey;
-
-    if (io->objClass == CKO_CERTIFICATE) {
-        ckmk_GetCommonAttribute(io, kSecCertEncodingItemAttr,
-                                PR_TRUE, key, "Fetching HashKey (cert)");
-    } else {
-        ckmk_GetCommonAttribute(io, kSecKeyLabel,
-                                PR_FALSE, key, "Fetching HashKey (key)");
-    }
-}
-
-/*
- * Apple mucks with the actual subject and issuer, so go fetch
- * the real ones ourselves.
- */
-static void
-ckmk_fetchCert(
-    ckmkInternalObject *io)
-{
-    CK_RV error;
-    unsigned char *cert, *next;
-    int certSize, thisEntrySize;
-
-    error = ckmk_GetCommonAttribute(io, kSecCertEncodingItemAttr, PR_TRUE,
-                                    &io->u.item.derCert, "Fetching Value (cert)");
-    if (CKR_OK != error) {
-        return;
-    }
-    /* unwrap the cert bundle */
-    cert = nss_ckmk_DERUnwrap((unsigned char *)io->u.item.derCert.data,
-                              io->u.item.derCert.size,
-                              &certSize, NULL);
-    /* unwrap the cert itself */
-    /* cert == certdata */
-    cert = nss_ckmk_DERUnwrap(cert, certSize, &certSize, NULL);
-
-    /* skip the optional version */
-    if ((cert[0] & 0xa0) == 0xa0) {
-        nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next);
-        certSize -= next - cert;
-        cert = next;
-    }
-    /* skip the serial number */
-    nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next);
-    certSize -= next - cert;
-    cert = next;
-
-    /* skip the OID */
-    nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next);
-    certSize -= next - cert;
-    cert = next;
-
-    /* save the (wrapped) issuer */
-    io->u.item.issuer.data = cert;
-    nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next);
-    io->u.item.issuer.size = next - cert;
-    certSize -= io->u.item.issuer.size;
-    cert = next;
-
-    /* skip the OID */
-    nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next);
-    certSize -= next - cert;
-    cert = next;
-
-    /* save the (wrapped) subject */
-    io->u.item.subject.data = cert;
-    nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next);
-    io->u.item.subject.size = next - cert;
-    certSize -= io->u.item.subject.size;
-    cert = next;
-}
-
-static void
-ckmk_fetchModulus(
-    ckmkInternalObject *io)
-{
-    NSSItem item;
-    PRInt32 modLen;
-    CK_RV error;
-
-    /* we can't reliably get the modulus for private keys through CSSM (sigh).
-     * For NSS this is OK because we really only use this to get the modulus
-     * length (unless we are trying to get a public key from a private keys,
-     * something CSSM ALSO does not do!).
-     */
-    error = ckmk_GetDataAttribute(io, kSecKeyKeySizeInBits, &item,
-                                  "Key Fetch Modulus");
-    if (CKR_OK != error) {
-        return;
-    }
-
-    modLen = *(PRInt32 *)item.data;
-    modLen = modLen / 8; /* convert from bits to bytes */
-
-    nss_ZFreeIf(item.data);
-    io->u.item.modulus.data = nss_ZNEWARRAY(NULL, char, modLen);
-    if (NULL == io->u.item.modulus.data) {
-        return;
-    }
-    *(char *)io->u.item.modulus.data = 0x80; /* fake NSS out or it will
-                                              * drop the first byte */
-    io->u.item.modulus.size = modLen;
-    return;
-}
-
-const NSSItem *
-ckmk_FetchCertAttribute(
-    ckmkInternalObject *io,
-    CK_ATTRIBUTE_TYPE type,
-    CK_RV *pError)
-{
-    ckmkItemObject *item = &io->u.item;
-    *pError = CKR_OK;
-    switch (type) {
-        case CKA_CLASS:
-            return &ckmk_certClassItem;
-        case CKA_TOKEN:
-        case CKA_MODIFIABLE:
-            return &ckmk_trueItem;
-        case CKA_PRIVATE:
-            return &ckmk_falseItem;
-        case CKA_CERTIFICATE_TYPE:
-            return &ckmk_x509Item;
-        case CKA_LABEL:
-            CKMK_HANDLE_OPT_DATA_ITEM(io, kSecLabelItemAttr, label, item, *pError,
-                                      "Cert:Label attr")
-        case CKA_SUBJECT:
-            /* OK, well apple does provide an subject and issuer attribute, but they
-             * decided to cannonicalize that value. Probably a good move for them,
-             * but makes it useless for most users of PKCS #11.. Get the real subject
-             * from the certificate */
-            if (0 == item->derCert.size) {
-                ckmk_fetchCert(io);
-            }
-            return &item->subject;
-        case CKA_ISSUER:
-            if (0 == item->derCert.size) {
-                ckmk_fetchCert(io);
-            }
-            return &item->issuer;
-        case CKA_SERIAL_NUMBER:
-            CKMK_HANDLE_DATA_ITEM(io, kSecSerialNumberItemAttr, serial, item, *pError,
-                                  "Cert:Serial Number attr")
-        case CKA_VALUE:
-            if (0 == item->derCert.size) {
-                ckmk_fetchCert(io);
-            }
-            return &item->derCert;
-        case CKA_ID:
-            CKMK_HANDLE_OPT_DATA_ITEM(io, kSecPublicKeyHashItemAttr, id, item, *pError,
-                                      "Cert:ID attr")
-        default:
-            *pError = CKR_ATTRIBUTE_TYPE_INVALID;
-            break;
-    }
-    return NULL;
-}
-
-const NSSItem *
-ckmk_FetchPubKeyAttribute(
-    ckmkInternalObject *io,
-    CK_ATTRIBUTE_TYPE type,
-    CK_RV *pError)
-{
-    ckmkItemObject *item = &io->u.item;
-    *pError = CKR_OK;
-
-    switch (type) {
-        case CKA_CLASS:
-            return &ckmk_pubKeyClassItem;
-        case CKA_TOKEN:
-        case CKA_LOCAL:
-            return &ckmk_trueItem;
-        case CKA_KEY_TYPE:
-            return &ckmk_rsaItem;
-        case CKA_LABEL:
-            CKMK_HANDLE_OPT_DATA_ITEM(io, kSecKeyPrintName, label, item, *pError,
-                                      "PubKey:Label attr")
-        case CKA_ENCRYPT:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeyEncrypt, encrypt, item, *pError,
-                                  "PubKey:Encrypt attr")
-        case CKA_VERIFY:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeyVerify, verify, item, *pError,
-                                  "PubKey:Verify attr")
-        case CKA_VERIFY_RECOVER:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeyVerifyRecover, verifyRecover,
-                                  item, *pError, "PubKey:VerifyRecover attr")
-        case CKA_PRIVATE:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeyPrivate, private, item, *pError,
-                                  "PubKey:Private attr")
-        case CKA_MODIFIABLE:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeyModifiable, modify, item, *pError,
-                                  "PubKey:Modify attr")
-        case CKA_DERIVE:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeyDerive, derive, item, *pError,
-                                  "PubKey:Derive attr")
-        case CKA_WRAP:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeyWrap, wrap, item, *pError,
-                                  "PubKey:Wrap attr")
-        case CKA_SUBJECT:
-            CKMK_HANDLE_OPT_DATA_ITEM(io, kSecSubjectItemAttr, subject, item, *pError,
-                                      "PubKey:Subect attr")
-        case CKA_MODULUS:
-            return &ckmk_emptyItem;
-        case CKA_PUBLIC_EXPONENT:
-            return &ckmk_emptyItem;
-        case CKA_ID:
-            CKMK_HANDLE_OPT_DATA_ITEM(io, kSecKeyLabel, id, item, *pError,
-                                      "PubKey:ID attr")
-        default:
-            *pError = CKR_ATTRIBUTE_TYPE_INVALID;
-            break;
-    }
-    return NULL;
-}
-
-const NSSItem *
-ckmk_FetchPrivKeyAttribute(
-    ckmkInternalObject *io,
-    CK_ATTRIBUTE_TYPE type,
-    CK_RV *pError)
-{
-    ckmkItemObject *item = &io->u.item;
-    *pError = CKR_OK;
-
-    switch (type) {
-        case CKA_CLASS:
-            return &ckmk_privKeyClassItem;
-        case CKA_TOKEN:
-        case CKA_LOCAL:
-            return &ckmk_trueItem;
-        case CKA_SENSITIVE:
-        case CKA_EXTRACTABLE: /* will probably move in the future */
-        case CKA_ALWAYS_SENSITIVE:
-        case CKA_NEVER_EXTRACTABLE:
-            return &ckmk_falseItem;
-        case CKA_KEY_TYPE:
-            return &ckmk_rsaItem;
-        case CKA_LABEL:
-            CKMK_HANDLE_OPT_DATA_ITEM(io, kSecKeyPrintName, label, item, *pError,
-                                      "PrivateKey:Label attr")
-        case CKA_DECRYPT:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeyDecrypt, decrypt, item, *pError,
-                                  "PrivateKey:Decrypt attr")
-        case CKA_SIGN:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeySign, sign, item, *pError,
-                                  "PrivateKey:Sign attr")
-        case CKA_SIGN_RECOVER:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeySignRecover, signRecover, item, *pError,
-                                  "PrivateKey:Sign Recover attr")
-        case CKA_PRIVATE:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeyPrivate, private, item, *pError,
-                                  "PrivateKey:Private attr")
-        case CKA_MODIFIABLE:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeyModifiable, modify, item, *pError,
-                                  "PrivateKey:Modify attr")
-        case CKA_DERIVE:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeyDerive, derive, item, *pError,
-                                  "PrivateKey:Derive attr")
-        case CKA_UNWRAP:
-            CKMK_HANDLE_BOOL_ITEM(io, kSecKeyUnwrap, unwrap, item, *pError,
-                                  "PrivateKey:Unwrap attr")
-        case CKA_SUBJECT:
-            CKMK_HANDLE_OPT_DATA_ITEM(io, kSecSubjectItemAttr, subject, item, *pError,
-                                      "PrivateKey:Subject attr")
-        case CKA_MODULUS:
-            if (0 == item->modulus.size) {
-                ckmk_fetchModulus(io);
-            }
-            return &item->modulus;
-        case CKA_PUBLIC_EXPONENT:
-            return &ckmk_emptyItem;
-#ifdef notdef
-        /* the following are sensitive attributes. We could implement them for
-         * sensitive keys using the key export function, but it's better to
-         * just support wrap through this token. That will more reliably allow us
-         * to export any private key that is truly exportable.
-         */
-        case CKA_PRIVATE_EXPONENT:
-            CKMK_HANDLE_DATA_ITEM(io, kSecPrivateExponentItemAttr, privateExponent,
-                                  item, *pError)
-        case CKA_PRIME_1:
-            CKMK_HANDLE_DATA_ITEM(io, kSecPrime1ItemAttr, prime1, item, *pError)
-        case CKA_PRIME_2:
-            CKMK_HANDLE_DATA_ITEM(io, kSecPrime2ItemAttr, prime2, item, *pError)
-        case CKA_EXPONENT_1:
-            CKMK_HANDLE_DATA_ITEM(io, kSecExponent1ItemAttr, exponent1, item, *pError)
-        case CKA_EXPONENT_2:
-            CKMK_HANDLE_DATA_ITEM(io, kSecExponent2ItemAttr, exponent2, item, *pError)
-        case CKA_COEFFICIENT:
-            CKMK_HANDLE_DATA_ITEM(io, kSecCoefficientItemAttr, coefficient,
-                                  item, *pError)
-#endif
-        case CKA_ID:
-            CKMK_HANDLE_OPT_DATA_ITEM(io, kSecKeyLabel, id, item, *pError,
-                                      "PrivateKey:ID attr")
-        default:
-            *pError = CKR_ATTRIBUTE_TYPE_INVALID;
-            return NULL;
-    }
-}
-
-const NSSItem *
-nss_ckmk_FetchAttribute(
-    ckmkInternalObject *io,
-    CK_ATTRIBUTE_TYPE type,
-    CK_RV *pError)
-{
-    CK_ULONG i;
-    const NSSItem *value = NULL;
-
-    if (io->type == ckmkRaw) {
-        for (i = 0; i < io->u.raw.n; i++) {
-            if (type == io->u.raw.types[i]) {
-                return &io->u.raw.items[i];
-            }
-        }
-        *pError = CKR_ATTRIBUTE_TYPE_INVALID;
-        return NULL;
-    }
-    /* deal with the common attributes */
-    switch (io->objClass) {
-        case CKO_CERTIFICATE:
-            value = ckmk_FetchCertAttribute(io, type, pError);
-            break;
-        case CKO_PRIVATE_KEY:
-            value = ckmk_FetchPrivKeyAttribute(io, type, pError);
-            break;
-        case CKO_PUBLIC_KEY:
-            value = ckmk_FetchPubKeyAttribute(io, type, pError);
-            break;
-        default:
-            *pError = CKR_OBJECT_HANDLE_INVALID;
-            return NULL;
-    }
-
-#ifdef DEBUG
-    if (CKA_ID == type) {
-        itemdump("id: ", value->data, value->size, *pError);
-    }
-#endif
-    return value;
-}
-
-static void
-ckmk_removeObjectFromHash(
-    ckmkInternalObject *io);
-
-/*
- *
- * These are the MSObject functions we need to implement
- *
- * Finalize - unneeded (actually we should clean up the hashtables)
- * Destroy
- * IsTokenObject - CK_TRUE
- * GetAttributeCount
- * GetAttributeTypes
- * GetAttributeSize
- * GetAttribute
- * SetAttribute
- * GetObjectSize
- */
-
-static CK_RV
-ckmk_mdObject_Destroy(
-    NSSCKMDObject *mdObject,
-    NSSCKFWObject *fwObject,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc;
-    OSStatus macErr;
-
-    if (ckmkRaw == io->type) {
-        /* there is not 'object write protected' error, use the next best thing */
-        return CKR_TOKEN_WRITE_PROTECTED;
-    }
-
-    /* This API is done well. The following 4 lines are the complete apple
-     * specific part of this implementation */
-    macErr = SecKeychainItemDelete(io->u.item.itemRef);
-    if (noErr != macErr) {
-        CKMK_MACERR("Delete object", macErr);
-    }
-
-    /* remove it from the hash */
-    ckmk_removeObjectFromHash(io);
-
-    /* free the puppy.. */
-    nss_ckmk_DestroyInternalObject(io);
-
-    return CKR_OK;
-}
-
-static CK_BBOOL
-ckmk_mdObject_IsTokenObject(
-    NSSCKMDObject *mdObject,
-    NSSCKFWObject *fwObject,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    return CK_TRUE;
-}
-
-static CK_ULONG
-ckmk_mdObject_GetAttributeCount(
-    NSSCKMDObject *mdObject,
-    NSSCKFWObject *fwObject,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc;
-
-    if (ckmkRaw == io->type) {
-        return io->u.raw.n;
-    }
-    switch (io->objClass) {
-        case CKO_CERTIFICATE:
-            return certAttrsCount;
-        case CKO_PUBLIC_KEY:
-            return pubKeyAttrsCount;
-        case CKO_PRIVATE_KEY:
-            return privKeyAttrsCount;
-        default:
-            break;
-    }
-    return 0;
-}
-
-static CK_RV
-ckmk_mdObject_GetAttributeTypes(
-    NSSCKMDObject *mdObject,
-    NSSCKFWObject *fwObject,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_ATTRIBUTE_TYPE_PTR typeArray,
-    CK_ULONG ulCount)
-{
-    ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc;
-    CK_ULONG i;
-    CK_RV error = CKR_OK;
-    const CK_ATTRIBUTE_TYPE *attrs = NULL;
-    CK_ULONG size = ckmk_mdObject_GetAttributeCount(
-        mdObject, fwObject, mdSession, fwSession,
-        mdToken, fwToken, mdInstance, fwInstance, &error);
-
-    if (size != ulCount) {
-        return CKR_BUFFER_TOO_SMALL;
-    }
-    if (io->type == ckmkRaw) {
-        attrs = io->u.raw.types;
-    } else
-        switch (io->objClass) {
-            case CKO_CERTIFICATE:
-                attrs =
-                    certAttrs;
-                break;
-            case CKO_PUBLIC_KEY:
-                attrs =
-                    pubKeyAttrs;
-                break;
-            case CKO_PRIVATE_KEY:
-                attrs =
-                    privKeyAttrs;
-                break;
-            default:
-                return CKR_OK;
-        }
-
-    for (i = 0; i < size; i++) {
-        typeArray[i] = attrs[i];
-    }
-
-    return CKR_OK;
-}
-
-static CK_ULONG
-ckmk_mdObject_GetAttributeSize(
-    NSSCKMDObject *mdObject,
-    NSSCKFWObject *fwObject,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_ATTRIBUTE_TYPE attribute,
-    CK_RV *pError)
-{
-    ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc;
-
-    const NSSItem *b;
-
-    b = nss_ckmk_FetchAttribute(io, attribute, pError);
-
-    if ((const NSSItem *)NULL == b) {
-        return 0;
-    }
-    return b->size;
-}
-
-static CK_RV
-ckmk_mdObject_SetAttribute(
-    NSSCKMDObject *mdObject,
-    NSSCKFWObject *fwObject,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_ATTRIBUTE_TYPE attribute,
-    NSSItem *value)
-{
-    ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc;
-    SecKeychainItemRef itemRef;
-
-    if (io->type == ckmkRaw) {
-        return CKR_TOKEN_WRITE_PROTECTED;
-    }
-    itemRef = io->u.item.itemRef;
-
-    switch (io->objClass) {
-        case CKO_PRIVATE_KEY:
-        case CKO_PUBLIC_KEY:
-            switch (attribute) {
-                case CKA_ID:
-                    ckmk_updateAttribute(itemRef, kSecKeyLabel,
-                                         value->data, value->size, "Set Attr Key ID");
-#ifdef DEBUG
-                    itemdump("key id: ", value->data, value->size, CKR_OK);
-#endif
-                    break;
-                case CKA_LABEL:
-                    ckmk_updateAttribute(itemRef, kSecKeyPrintName, value->data,
-                                         value->size, "Set Attr Key Label");
-                    break;
-                default:
-                    break;
-            }
-            break;
-
-        case CKO_CERTIFICATE:
-            switch (attribute) {
-                case CKA_ID:
-                    ckmk_updateAttribute(itemRef, kSecPublicKeyHashItemAttr,
-                                         value->data, value->size, "Set Attr Cert ID");
-                    break;
-                case CKA_LABEL:
-                    ckmk_updateAttribute(itemRef, kSecLabelItemAttr, value->data,
-                                         value->size, "Set Attr Cert Label");
-                    break;
-                default:
-                    break;
-            }
-            break;
-
-        default:
-            break;
-    }
-    return CKR_OK;
-}
-
-static NSSCKFWItem
-ckmk_mdObject_GetAttribute(
-    NSSCKMDObject *mdObject,
-    NSSCKFWObject *fwObject,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_ATTRIBUTE_TYPE attribute,
-    CK_RV *pError)
-{
-    NSSCKFWItem mdItem;
-    ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc;
-
-    mdItem.needsFreeing = PR_FALSE;
-    mdItem.item = (NSSItem *)nss_ckmk_FetchAttribute(io, attribute, pError);
-
-    return mdItem;
-}
-
-static CK_ULONG
-ckmk_mdObject_GetObjectSize(
-    NSSCKMDObject *mdObject,
-    NSSCKFWObject *fwObject,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    CK_ULONG rv = 1;
-
-    /* size is irrelevant to this token */
-    return rv;
-}
-
-static const NSSCKMDObject
-    ckmk_prototype_mdObject = {
-        (void *)NULL, /* etc */
-        NULL,         /* Finalize */
-        ckmk_mdObject_Destroy,
-        ckmk_mdObject_IsTokenObject,
-        ckmk_mdObject_GetAttributeCount,
-        ckmk_mdObject_GetAttributeTypes,
-        ckmk_mdObject_GetAttributeSize,
-        ckmk_mdObject_GetAttribute,
-        NULL, /* FreeAttribute */
-        ckmk_mdObject_SetAttribute,
-        ckmk_mdObject_GetObjectSize,
-        (void *)NULL /* null terminator */
-    };
-
-static nssHash *ckmkInternalObjectHash = NULL;
-
-NSS_IMPLEMENT NSSCKMDObject *
-nss_ckmk_CreateMDObject(
-    NSSArena *arena,
-    ckmkInternalObject *io,
-    CK_RV *pError)
-{
-    if ((nssHash *)NULL == ckmkInternalObjectHash) {
-        ckmkInternalObjectHash = nssHash_CreateItem(NULL, 10);
-    }
-    if (ckmkItem == io->type) {
-        /* the hash key, not a cryptographic key */
-        NSSItem *key = &io->hashKey;
-        ckmkInternalObject *old_o = NULL;
-
-        if (key->size == 0) {
-            ckmk_FetchHashKey(io);
-        }
-        old_o = (ckmkInternalObject *)
-            nssHash_Lookup(ckmkInternalObjectHash, key);
-        if (!old_o) {
-            nssHash_Add(ckmkInternalObjectHash, key, io);
-        } else if (old_o != io) {
-            nss_ckmk_DestroyInternalObject(io);
-            io = old_o;
-        }
-    }
-
-    if ((void *)NULL == io->mdObject.etc) {
-        (void)nsslibc_memcpy(&io->mdObject, &ckmk_prototype_mdObject,
-                             sizeof(ckmk_prototype_mdObject));
-        io->mdObject.etc = (void *)io;
-    }
-    return &io->mdObject;
-}
-
-static void
-ckmk_removeObjectFromHash(
-    ckmkInternalObject *io)
-{
-    NSSItem *key = &io->hashKey;
-
-    if ((nssHash *)NULL == ckmkInternalObjectHash) {
-        return;
-    }
-    if (key->size == 0) {
-        ckmk_FetchHashKey(io);
-    }
-    nssHash_Remove(ckmkInternalObjectHash, key);
-    return;
-}
-
-void
-nss_ckmk_DestroyInternalObject(
-    ckmkInternalObject *io)
-{
-    switch (io->type) {
-        case ckmkRaw:
-            return;
-        case ckmkItem:
-            nss_ZFreeIf(io->u.item.modify.data);
-            nss_ZFreeIf(io->u.item.private.data);
-            nss_ZFreeIf(io->u.item.encrypt.data);
-            nss_ZFreeIf(io->u.item.decrypt.data);
-            nss_ZFreeIf(io->u.item.derive.data);
-            nss_ZFreeIf(io->u.item.sign.data);
-            nss_ZFreeIf(io->u.item.signRecover.data);
-            nss_ZFreeIf(io->u.item.verify.data);
-            nss_ZFreeIf(io->u.item.verifyRecover.data);
-            nss_ZFreeIf(io->u.item.wrap.data);
-            nss_ZFreeIf(io->u.item.unwrap.data);
-            nss_ZFreeIf(io->u.item.label.data);
-            /*nss_ZFreeIf(io->u.item.subject.data); */
-            /*nss_ZFreeIf(io->u.item.issuer.data); */
-            nss_ZFreeIf(io->u.item.serial.data);
-            nss_ZFreeIf(io->u.item.modulus.data);
-            nss_ZFreeIf(io->u.item.exponent.data);
-            nss_ZFreeIf(io->u.item.privateExponent.data);
-            nss_ZFreeIf(io->u.item.prime1.data);
-            nss_ZFreeIf(io->u.item.prime2.data);
-            nss_ZFreeIf(io->u.item.exponent1.data);
-            nss_ZFreeIf(io->u.item.exponent2.data);
-            nss_ZFreeIf(io->u.item.coefficient.data);
-            break;
-    }
-    nss_ZFreeIf(io);
-    return;
-}
-
-static ckmkInternalObject *
-nss_ckmk_NewInternalObject(
-    CK_OBJECT_CLASS objClass,
-    SecKeychainItemRef itemRef,
-    SecItemClass itemClass,
-    CK_RV *pError)
-{
-    ckmkInternalObject *io = nss_ZNEW(NULL, ckmkInternalObject);
-
-    if ((ckmkInternalObject *)NULL == io) {
-        *pError = CKR_HOST_MEMORY;
-        return io;
-    }
-    io->type = ckmkItem;
-    io->objClass = objClass;
-    io->u.item.itemRef = itemRef;
-    io->u.item.itemClass = itemClass;
-    return io;
-}
-
-/*
- * Apple doesn't alway have a default keyChain set by the OS, use the
- * SearchList to try to find one.
- */
-static CK_RV
-ckmk_GetSafeDefaultKeychain(
-    SecKeychainRef *keychainRef)
-{
-    OSStatus macErr;
-    CFArrayRef searchList = 0;
-    CK_RV error = CKR_OK;
-
-    macErr = SecKeychainCopyDefault(keychainRef);
-    if (noErr != macErr) {
-        int searchCount = 0;
-        if (errSecNoDefaultKeychain != macErr) {
-            CKMK_MACERR("Getting default key chain", macErr);
-            error = CKR_GENERAL_ERROR;
-            goto loser;
-        }
-        /* ok, we don't have a default key chain, find one */
-        macErr = SecKeychainCopySearchList(&searchList);
-        if (noErr != macErr) {
-            CKMK_MACERR("failed to find a keyring searchList", macErr);
-            error = CKR_DEVICE_REMOVED;
-            goto loser;
-        }
-        searchCount = CFArrayGetCount(searchList);
-        if (searchCount < 1) {
-            error = CKR_DEVICE_REMOVED;
-            goto loser;
-        }
-        *keychainRef =
-            (SecKeychainRef)CFRetain(CFArrayGetValueAtIndex(searchList, 0));
-        if (0 == *keychainRef) {
-            error = CKR_DEVICE_REMOVED;
-            goto loser;
-        }
-        /* should we set it as default? */
-    }
-loser:
-    if (0 != searchList) {
-        CFRelease(searchList);
-    }
-    return error;
-}
-static ckmkInternalObject *
-nss_ckmk_CreateCertificate(
-    NSSCKFWSession *fwSession,
-    CK_ATTRIBUTE_PTR pTemplate,
-    CK_ULONG ulAttributeCount,
-    CK_RV *pError)
-{
-    NSSItem value;
-    ckmkInternalObject *io = NULL;
-    OSStatus macErr;
-    SecCertificateRef certRef;
-    SecKeychainItemRef itemRef;
-    SecKeychainRef keychainRef;
-    CSSM_DATA certData;
-
-    *pError = nss_ckmk_GetAttribute(CKA_VALUE, pTemplate,
-                                    ulAttributeCount, &value);
-    if (CKR_OK != *pError) {
-        goto loser;
-    }
-
-    certData.Data = value.data;
-    certData.Length = value.size;
-    macErr = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3,
-                                          CSSM_CERT_ENCODING_BER, &certRef);
-    if (noErr != macErr) {
-        CKMK_MACERR("Create cert from data Failed", macErr);
-        *pError = CKR_GENERAL_ERROR; /* need to map macErr */
-        goto loser;
-    }
-
-    *pError = ckmk_GetSafeDefaultKeychain(&keychainRef);
-    if (CKR_OK != *pError) {
-        goto loser;
-    }
-
-    macErr = SecCertificateAddToKeychain(certRef, keychainRef);
-    itemRef = (SecKeychainItemRef)certRef;
-    if (errSecDuplicateItem != macErr) {
-        NSSItem keyID = { NULL, 0 };
-        char *nickname = NULL;
-        CK_RV dummy;
-
-        if (noErr != macErr) {
-            CKMK_MACERR("Add cert to keychain Failed", macErr);
-            *pError = CKR_GENERAL_ERROR; /* need to map macErr */
-            goto loser;
-        }
-        /* these two are optional */
-        nickname = nss_ckmk_GetStringAttribute(CKA_LABEL, pTemplate,
-                                               ulAttributeCount, &dummy);
-        /* we've added a new one, update the attributes in the key ring */
-        if (nickname) {
-            ckmk_updateAttribute(itemRef, kSecLabelItemAttr, nickname,
-                                 strlen(nickname) + 1, "Modify Cert Label");
-            nss_ZFreeIf(nickname);
-        }
-        dummy = nss_ckmk_GetAttribute(CKA_ID, pTemplate,
-                                      ulAttributeCount, &keyID);
-        if (CKR_OK == dummy) {
-            dummy = ckmk_updateAttribute(itemRef, kSecPublicKeyHashItemAttr,
-                                         keyID.data, keyID.size, "Modify Cert ID");
-        }
-    }
-
-    io = nss_ckmk_NewInternalObject(CKO_CERTIFICATE, itemRef,
-                                    kSecCertificateItemClass, pError);
-    if ((ckmkInternalObject *)NULL != io) {
-        itemRef = 0;
-    }
-
-loser:
-    if (0 != itemRef) {
-        CFRelease(itemRef);
-    }
-    if (0 != keychainRef) {
-        CFRelease(keychainRef);
-    }
-
-    return io;
-}
-
-/*
- * PKCS #8 attributes
- */
-struct ckmk_AttributeStr {
-    SECItem attrType;
-    SECItem *attrValue;
-};
-typedef struct ckmk_AttributeStr ckmk_Attribute;
-
-/*
- ** A PKCS#8 private key info object
- */
-struct PrivateKeyInfoStr {
-    PLArenaPool *arena;
-    SECItem version;
-    SECAlgorithmID algorithm;
-    SECItem privateKey;
-    ckmk_Attribute **attributes;
-};
-typedef struct PrivateKeyInfoStr PrivateKeyInfo;
-
-const SEC_ASN1Template ckmk_RSAPrivateKeyTemplate[] = {
-    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RSAPrivateKey) },
-    { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, version) },
-    { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, modulus) },
-    { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, publicExponent) },
-    { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, privateExponent) },
-    { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime1) },
-    { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime2) },
-    { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent1) },
-    { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent2) },
-    { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, coefficient) },
-    { 0 }
-};
-
-const SEC_ASN1Template ckmk_AttributeTemplate[] = {
-    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ckmk_Attribute) },
-    { SEC_ASN1_OBJECT_ID, offsetof(ckmk_Attribute, attrType) },
-    { SEC_ASN1_SET_OF, offsetof(ckmk_Attribute, attrValue),
-      SEC_AnyTemplate },
-    { 0 }
-};
-
-const SEC_ASN1Template ckmk_SetOfAttributeTemplate[] = {
-    { SEC_ASN1_SET_OF, 0, ckmk_AttributeTemplate },
-};
-
-SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
-
-/* ASN1 Templates for new decoder/encoder */
-const SEC_ASN1Template ckmk_PrivateKeyInfoTemplate[] = {
-    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PrivateKeyInfo) },
-    { SEC_ASN1_INTEGER, offsetof(PrivateKeyInfo, version) },
-    { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(PrivateKeyInfo, algorithm),
-      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
-    { SEC_ASN1_OCTET_STRING, offsetof(PrivateKeyInfo, privateKey) },
-    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
-      offsetof(PrivateKeyInfo, attributes), ckmk_SetOfAttributeTemplate },
-    { 0 }
-};
-
-#define CKMK_PRIVATE_KEY_INFO_VERSION 0
-static CK_RV
-ckmk_CreateRSAKeyBlob(
-    RSAPrivateKey *lk,
-    NSSItem *keyBlob)
-{
-    PrivateKeyInfo *pki = NULL;
-    PLArenaPool *arena = NULL;
-    SECOidTag algorithm = SEC_OID_UNKNOWN;
-    void *dummy;
-    SECStatus rv;
-    SECItem *encodedKey = NULL;
-    CK_RV error = CKR_OK;
-
-    arena = PORT_NewArena(2048); /* XXX different size? */
-    if (!arena) {
-        error = CKR_HOST_MEMORY;
-        goto loser;
-    }
-
-    pki = (PrivateKeyInfo *)PORT_ArenaZAlloc(arena, sizeof(PrivateKeyInfo));
-    if (!pki) {
-        error = CKR_HOST_MEMORY;
-        goto loser;
-    }
-    pki->arena = arena;
-
-    dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
-                               ckmk_RSAPrivateKeyTemplate);
-    algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
-
-    if (!dummy) {
-        error = CKR_DEVICE_ERROR; /* should map NSS SECError */
-        goto loser;
-    }
-
-    rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm,
-                               (SECItem *)NULL);
-    if (rv != SECSuccess) {
-        error = CKR_DEVICE_ERROR; /* should map NSS SECError */
-        goto loser;
-    }
-
-    dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
-                                  CKMK_PRIVATE_KEY_INFO_VERSION);
-    if (!dummy) {
-        error = CKR_DEVICE_ERROR; /* should map NSS SECError */
-        goto loser;
-    }
-
-    encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki,
-                                    ckmk_PrivateKeyInfoTemplate);
-    if (!encodedKey) {
-        error = CKR_DEVICE_ERROR;
-        goto loser;
-    }
-
-    keyBlob->data = nss_ZNEWARRAY(NULL, char, encodedKey->len);
-    if (NULL == keyBlob->data) {
-        error = CKR_HOST_MEMORY;
-        goto loser;
-    }
-    nsslibc_memcpy(keyBlob->data, encodedKey->data, encodedKey->len);
-    keyBlob->size = encodedKey->len;
-
-loser:
-    if (arena) {
-        PORT_FreeArena(arena, PR_TRUE);
-    }
-    if (encodedKey) {
-        SECITEM_FreeItem(encodedKey, PR_TRUE);
-    }
-
-    return error;
-}
-/*
- * There MUST be a better way to do this. For now, find the key based on the
- * default name Apple gives it once we import.
- */
-#define IMPORTED_NAME "Imported Private Key"
-static CK_RV
-ckmk_FindImportedKey(
-    SecKeychainRef keychainRef,
-    SecItemClass itemClass,
-    SecKeychainItemRef *outItemRef)
-{
-    OSStatus macErr;
-    SecKeychainSearchRef searchRef = 0;
-    SecKeychainItemRef newItemRef;
-
-    macErr = SecKeychainSearchCreateFromAttributes(keychainRef, itemClass,
-                                                   NULL, &searchRef);
-    if (noErr != macErr) {
-        CKMK_MACERR("Can't search for Key", macErr);
-        return CKR_GENERAL_ERROR;
-    }
-    while (noErr == SecKeychainSearchCopyNext(searchRef, &newItemRef)) {
-        SecKeychainAttributeList *attrList = NULL;
-        SecKeychainAttributeInfo attrInfo;
-        SecItemAttr itemAttr = kSecKeyPrintName;
-        PRUint32 attrFormat = 0;
-        OSStatus macErr;
-
-        attrInfo.count = 1;
-        attrInfo.tag = &itemAttr;
-        attrInfo.format = &attrFormat;
-
-        macErr = SecKeychainItemCopyAttributesAndData(newItemRef,
-                                                      &attrInfo, NULL, &attrList, NULL, NULL);
-        if (noErr == macErr) {
-            if (nsslibc_memcmp(attrList->attr->data, IMPORTED_NAME,
-                               attrList->attr->length, NULL) == 0) {
-                *outItemRef = newItemRef;
-                CFRelease(searchRef);
-                SecKeychainItemFreeAttributesAndData(attrList, NULL);
-                return CKR_OK;
-            }
-            SecKeychainItemFreeAttributesAndData(attrList, NULL);
-        }
-        CFRelease(newItemRef);
-    }
-    CFRelease(searchRef);
-    return CKR_GENERAL_ERROR; /* we can come up with something better! */
-}
-
-static ckmkInternalObject *
-nss_ckmk_CreatePrivateKey(
-    NSSCKFWSession *fwSession,
-    CK_ATTRIBUTE_PTR pTemplate,
-    CK_ULONG ulAttributeCount,
-    CK_RV *pError)
-{
-    NSSItem attribute;
-    RSAPrivateKey lk;
-    NSSItem keyID;
-    char *nickname = NULL;
-    ckmkInternalObject *io = NULL;
-    CK_KEY_TYPE keyType;
-    OSStatus macErr;
-    SecKeychainItemRef itemRef = 0;
-    NSSItem keyBlob = { NULL, 0 };
-    CFDataRef dataRef = 0;
-    SecExternalFormat inputFormat = kSecFormatBSAFE;
-    /*SecExternalFormat inputFormat = kSecFormatOpenSSL;  */
-    SecExternalItemType itemType = kSecItemTypePrivateKey;
-    SecKeyImportExportParameters keyParams;
-    SecKeychainRef targetKeychain = 0;
-    unsigned char zero = 0;
-    CK_RV error;
-
-    keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
-    keyParams.flags = 0;
-    keyParams.passphrase = 0;
-    keyParams.alertTitle = 0;
-    keyParams.alertPrompt = 0;
-    keyParams.accessRef = 0;                          /* default */
-    keyParams.keyUsage = 0;                           /* will get filled in */
-    keyParams.keyAttributes = CSSM_KEYATTR_PERMANENT; /* will get filled in */
-    keyType = nss_ckmk_GetULongAttribute(CKA_KEY_TYPE, pTemplate, ulAttributeCount, pError);
-    if (CKR_OK != *pError) {
-        return (ckmkInternalObject *)NULL;
-    }
-    if (CKK_RSA != keyType) {
-        *pError = CKR_ATTRIBUTE_VALUE_INVALID;
-        return (ckmkInternalObject *)NULL;
-    }
-    if (nss_ckmk_GetBoolAttribute(CKA_DECRYPT,
-                                  pTemplate, ulAttributeCount, CK_TRUE)) {
-        keyParams.keyUsage |= CSSM_KEYUSE_DECRYPT;
-    }
-    if (nss_ckmk_GetBoolAttribute(CKA_UNWRAP,
-                                  pTemplate, ulAttributeCount, CK_TRUE)) {
-        keyParams.keyUsage |= CSSM_KEYUSE_UNWRAP;
-    }
-    if (nss_ckmk_GetBoolAttribute(CKA_SIGN,
-                                  pTemplate, ulAttributeCount, CK_TRUE)) {
-        keyParams.keyUsage |= CSSM_KEYUSE_SIGN;
-    }
-    if (nss_ckmk_GetBoolAttribute(CKA_DERIVE,
-                                  pTemplate, ulAttributeCount, CK_FALSE)) {
-        keyParams.keyUsage |= CSSM_KEYUSE_DERIVE;
-    }
-    if (nss_ckmk_GetBoolAttribute(CKA_SENSITIVE,
-                                  pTemplate, ulAttributeCount, CK_TRUE)) {
-        keyParams.keyAttributes |= CSSM_KEYATTR_SENSITIVE;
-    }
-    if (nss_ckmk_GetBoolAttribute(CKA_EXTRACTABLE,
-                                  pTemplate, ulAttributeCount, CK_TRUE)) {
-        keyParams.keyAttributes |= CSSM_KEYATTR_EXTRACTABLE;
-    }
-
-    lk.version.type = siUnsignedInteger;
-    lk.version.data = &zero;
-    lk.version.len = 1;
-
-    *pError = nss_ckmk_GetAttribute(CKA_MODULUS, pTemplate,
-                                    ulAttributeCount, &attribute);
-    if (CKR_OK != *pError) {
-        return (ckmkInternalObject *)NULL;
-    }
-    lk.modulus.type = siUnsignedInteger;
-    lk.modulus.data = attribute.data;
-    lk.modulus.len = attribute.size;
-
-    *pError = nss_ckmk_GetAttribute(CKA_PUBLIC_EXPONENT, pTemplate,
-                                    ulAttributeCount, &attribute);
-    if (CKR_OK != *pError) {
-        return (ckmkInternalObject *)NULL;
-    }
-    lk.publicExponent.type = siUnsignedInteger;
-    lk.publicExponent.data = attribute.data;
-    lk.publicExponent.len = attribute.size;
-
-    *pError = nss_ckmk_GetAttribute(CKA_PRIVATE_EXPONENT, pTemplate,
-                                    ulAttributeCount, &attribute);
-    if (CKR_OK != *pError) {
-        return (ckmkInternalObject *)NULL;
-    }
-    lk.privateExponent.type = siUnsignedInteger;
-    lk.privateExponent.data = attribute.data;
-    lk.privateExponent.len = attribute.size;
-
-    *pError = nss_ckmk_GetAttribute(CKA_PRIME_1, pTemplate,
-                                    ulAttributeCount, &attribute);
-    if (CKR_OK != *pError) {
-        return (ckmkInternalObject *)NULL;
-    }
-    lk.prime1.type = siUnsignedInteger;
-    lk.prime1.data = attribute.data;
-    lk.prime1.len = attribute.size;
-
-    *pError = nss_ckmk_GetAttribute(CKA_PRIME_2, pTemplate,
-                                    ulAttributeCount, &attribute);
-    if (CKR_OK != *pError) {
-        return (ckmkInternalObject *)NULL;
-    }
-    lk.prime2.type = siUnsignedInteger;
-    lk.prime2.data = attribute.data;
-    lk.prime2.len = attribute.size;
-
-    *pError = nss_ckmk_GetAttribute(CKA_EXPONENT_1, pTemplate,
-                                    ulAttributeCount, &attribute);
-    if (CKR_OK != *pError) {
-        return (ckmkInternalObject *)NULL;
-    }
-    lk.exponent1.type = siUnsignedInteger;
-    lk.exponent1.data = attribute.data;
-    lk.exponent1.len = attribute.size;
-
-    *pError = nss_ckmk_GetAttribute(CKA_EXPONENT_2, pTemplate,
-                                    ulAttributeCount, &attribute);
-    if (CKR_OK != *pError) {
-        return (ckmkInternalObject *)NULL;
-    }
-    lk.exponent2.type = siUnsignedInteger;
-    lk.exponent2.data = attribute.data;
-    lk.exponent2.len = attribute.size;
-
-    *pError = nss_ckmk_GetAttribute(CKA_COEFFICIENT, pTemplate,
-                                    ulAttributeCount, &attribute);
-    if (CKR_OK != *pError) {
-        return (ckmkInternalObject *)NULL;
-    }
-    lk.coefficient.type = siUnsignedInteger;
-    lk.coefficient.data = attribute.data;
-    lk.coefficient.len = attribute.size;
-
-    /* ASN1 Encode the pkcs8 structure... look at softoken to see how this
-     * is done... */
-    error = ckmk_CreateRSAKeyBlob(&lk, &keyBlob);
-    if (CKR_OK != error) {
-        goto loser;
-    }
-
-    dataRef = CFDataCreate(NULL, (UInt8 *)keyBlob.data, keyBlob.size);
-    if (0 == dataRef) {
-        *pError = CKR_HOST_MEMORY;
-        goto loser;
-    }
-
-    *pError == ckmk_GetSafeDefaultKeychain(&targetKeychain);
-    if (CKR_OK != *pError) {
-        goto loser;
-    }
-
-    /* the itemArray that is returned is useless. the item does not
-     * is 'not on the key chain' so none of the modify calls work on it.
-     * It also has a key that isn't the same key as the one in the actual
-     * key chain. In short it isn't the item we want, and it gives us zero
-     * information about the item we want, so don't even bother with it...
-     */
-    macErr = SecKeychainItemImport(dataRef, NULL, &inputFormat, &itemType, 0,
-                                   &keyParams, targetKeychain, NULL);
-    if (noErr != macErr) {
-        CKMK_MACERR("Import Private Key", macErr);
-        *pError = CKR_GENERAL_ERROR;
-        goto loser;
-    }
-
-    *pError = ckmk_FindImportedKey(targetKeychain,
-                                   CSSM_DL_DB_RECORD_PRIVATE_KEY,
-                                   &itemRef);
-    if (CKR_OK != *pError) {
-#ifdef DEBUG
-        fprintf(stderr, "couldn't find key in keychain \n");
-#endif
-        goto loser;
-    }
-
-    /* set the CKA_ID and  the CKA_LABEL */
-    error = nss_ckmk_GetAttribute(CKA_ID, pTemplate,
-                                  ulAttributeCount, &keyID);
-    if (CKR_OK == error) {
-        error = ckmk_updateAttribute(itemRef, kSecKeyLabel,
-                                     keyID.data, keyID.size, "Modify Key ID");
-#ifdef DEBUG
-        itemdump("key id: ", keyID.data, keyID.size, error);
-#endif
-    }
-    nickname = nss_ckmk_GetStringAttribute(CKA_LABEL, pTemplate,
-                                           ulAttributeCount, &error);
-    if (nickname) {
-        ckmk_updateAttribute(itemRef, kSecKeyPrintName, nickname,
-                             strlen(nickname) + 1, "Modify Key Label");
-    } else {
-#define DEFAULT_NICKNAME "NSS Imported Key"
-        ckmk_updateAttribute(itemRef, kSecKeyPrintName, DEFAULT_NICKNAME,
-                             sizeof(DEFAULT_NICKNAME), "Modify Key Label");
-    }
-
-    io = nss_ckmk_NewInternalObject(CKO_PRIVATE_KEY, itemRef,
-                                    CSSM_DL_DB_RECORD_PRIVATE_KEY, pError);
-    if ((ckmkInternalObject *)NULL == io) {
-        CFRelease(itemRef);
-    }
-
-    return io;
-
-loser:
-    /* free the key blob */
-    if (keyBlob.data) {
-        nss_ZFreeIf(keyBlob.data);
-    }
-    if (0 != targetKeychain) {
-        CFRelease(targetKeychain);
-    }
-    if (0 != dataRef) {
-        CFRelease(dataRef);
-    }
-    return io;
-}
-
-NSS_EXTERN NSSCKMDObject *
-nss_ckmk_CreateObject(
-    NSSCKFWSession *fwSession,
-    CK_ATTRIBUTE_PTR pTemplate,
-    CK_ULONG ulAttributeCount,
-    CK_RV *pError)
-{
-    CK_OBJECT_CLASS objClass;
-    ckmkInternalObject *io = NULL;
-    CK_BBOOL isToken;
-
-    /*
-     * only create token objects
-     */
-    isToken = nss_ckmk_GetBoolAttribute(CKA_TOKEN, pTemplate,
-                                        ulAttributeCount, CK_FALSE);
-    if (!isToken) {
-        *pError = CKR_ATTRIBUTE_VALUE_INVALID;
-        return (NSSCKMDObject *)NULL;
-    }
-
-    /*
-     * only create keys and certs.
-     */
-    objClass = nss_ckmk_GetULongAttribute(CKA_CLASS, pTemplate,
-                                          ulAttributeCount, pError);
-    if (CKR_OK != *pError) {
-        return (NSSCKMDObject *)NULL;
-    }
-#ifdef notdef
-    if (objClass == CKO_PUBLIC_KEY) {
-        return CKR_OK; /* fake public key creation, happens as a side effect of
-                        * private key creation */
-    }
-#endif
-    if (objClass == CKO_CERTIFICATE) {
-        io = nss_ckmk_CreateCertificate(fwSession, pTemplate,
-                                        ulAttributeCount, pError);
-    } else if (objClass == CKO_PRIVATE_KEY) {
-        io = nss_ckmk_CreatePrivateKey(fwSession, pTemplate,
-                                       ulAttributeCount, pError);
-    } else {
-        *pError = CKR_ATTRIBUTE_VALUE_INVALID;
-    }
-
-    if ((ckmkInternalObject *)NULL == io) {
-        return (NSSCKMDObject *)NULL;
-    }
-    return nss_ckmk_CreateMDObject(NULL, io, pError);
-}
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/mrsa.c
+++ /dev/null
@@ -1,479 +0,0 @@
-/* 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 "ckmk.h"
-
-/* Sigh, For all the talk about 'ease of use', apple has hidden the interfaces
- * needed to be able to truly use CSSM. These came from their modification
- * to NSS's S/MIME code. The following two functions currently are not
- * part of the SecKey.h interface.
- */
-OSStatus
-SecKeyGetCredentials(
-    SecKeyRef keyRef,
-    CSSM_ACL_AUTHORIZATION_TAG authTag,
-    int type,
-    const CSSM_ACCESS_CREDENTIALS **creds);
-
-/* this function could be implemented using 'SecKeychainItemCopyKeychain' and
- * 'SecKeychainGetCSPHandle' */
-OSStatus
-SecKeyGetCSPHandle(
-    SecKeyRef keyRef,
-    CSSM_CSP_HANDLE *cspHandle);
-
-typedef struct ckmkInternalCryptoOperationRSAPrivStr
-    ckmkInternalCryptoOperationRSAPriv;
-struct ckmkInternalCryptoOperationRSAPrivStr {
-    NSSCKMDCryptoOperation mdOperation;
-    NSSCKMDMechanism *mdMechanism;
-    ckmkInternalObject *iKey;
-    NSSItem *buffer;
-    CSSM_CC_HANDLE cssmContext;
-};
-
-typedef enum {
-    CKMK_DECRYPT,
-    CKMK_SIGN
-} ckmkRSAOpType;
-
-/*
- * ckmk_mdCryptoOperationRSAPriv_Create
- */
-static NSSCKMDCryptoOperation *
-ckmk_mdCryptoOperationRSAPriv_Create(
-    const NSSCKMDCryptoOperation *proto,
-    NSSCKMDMechanism *mdMechanism,
-    NSSCKMDObject *mdKey,
-    ckmkRSAOpType type,
-    CK_RV *pError)
-{
-    ckmkInternalObject *iKey = (ckmkInternalObject *)mdKey->etc;
-    const NSSItem *classItem = nss_ckmk_FetchAttribute(iKey, CKA_CLASS, pError);
-    const NSSItem *keyType = nss_ckmk_FetchAttribute(iKey, CKA_KEY_TYPE, pError);
-    ckmkInternalCryptoOperationRSAPriv *iOperation;
-    SecKeyRef privateKey;
-    OSStatus macErr;
-    CSSM_RETURN cssmErr;
-    const CSSM_KEY *cssmKey;
-    CSSM_CSP_HANDLE cspHandle;
-    const CSSM_ACCESS_CREDENTIALS *creds = NULL;
-    CSSM_CC_HANDLE cssmContext;
-    CSSM_ACL_AUTHORIZATION_TAG authType;
-
-    /* make sure we have the right objects */
-    if (((const NSSItem *)NULL == classItem) ||
-        (sizeof(CK_OBJECT_CLASS) != classItem->size) ||
-        (CKO_PRIVATE_KEY != *(CK_OBJECT_CLASS *)classItem->data) ||
-        ((const NSSItem *)NULL == keyType) ||
-        (sizeof(CK_KEY_TYPE) != keyType->size) ||
-        (CKK_RSA != *(CK_KEY_TYPE *)keyType->data)) {
-        *pError = CKR_KEY_TYPE_INCONSISTENT;
-        return (NSSCKMDCryptoOperation *)NULL;
-    }
-
-    privateKey = (SecKeyRef)iKey->u.item.itemRef;
-    macErr = SecKeyGetCSSMKey(privateKey, &cssmKey);
-    if (noErr != macErr) {
-        CKMK_MACERR("Getting CSSM Key", macErr);
-        *pError = CKR_KEY_HANDLE_INVALID;
-        return (NSSCKMDCryptoOperation *)NULL;
-    }
-    macErr = SecKeyGetCSPHandle(privateKey, &cspHandle);
-    if (noErr != macErr) {
-        CKMK_MACERR("Getting CSP for Key", macErr);
-        *pError = CKR_KEY_HANDLE_INVALID;
-        return (NSSCKMDCryptoOperation *)NULL;
-    }
-    switch (type) {
-        case CKMK_DECRYPT:
-            authType = CSSM_ACL_AUTHORIZATION_DECRYPT;
-            break;
-        case CKMK_SIGN:
-            authType = CSSM_ACL_AUTHORIZATION_SIGN;
-            break;
-        default:
-            *pError = CKR_GENERAL_ERROR;
-#ifdef DEBUG
-            fprintf(stderr, "RSAPriv_Create: bad type = %d\n", type);
-#endif
-            return (NSSCKMDCryptoOperation *)NULL;
-    }
-
-    macErr = SecKeyGetCredentials(privateKey, authType, 0, &creds);
-    if (noErr != macErr) {
-        CKMK_MACERR("Getting Credentials for Key", macErr);
-        *pError = CKR_KEY_HANDLE_INVALID;
-        return (NSSCKMDCryptoOperation *)NULL;
-    }
-
-    switch (type) {
-        case CKMK_DECRYPT:
-            cssmErr = CSSM_CSP_CreateAsymmetricContext(cspHandle, CSSM_ALGID_RSA,
-                                                       creds, cssmKey, CSSM_PADDING_PKCS1, &cssmContext);
-            break;
-        case CKMK_SIGN:
-            cssmErr = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA,
-                                                      creds, cssmKey, &cssmContext);
-            break;
-        default:
-            *pError = CKR_GENERAL_ERROR;
-#ifdef DEBUG
-            fprintf(stderr, "RSAPriv_Create: bad type = %d\n", type);
-#endif
-            return (NSSCKMDCryptoOperation *)NULL;
-    }
-    if (noErr != cssmErr) {
-        CKMK_MACERR("Getting Context for Key", cssmErr);
-        *pError = CKR_GENERAL_ERROR;
-        return (NSSCKMDCryptoOperation *)NULL;
-    }
-
-    iOperation = nss_ZNEW(NULL, ckmkInternalCryptoOperationRSAPriv);
-    if ((ckmkInternalCryptoOperationRSAPriv *)NULL == iOperation) {
-        *pError = CKR_HOST_MEMORY;
-        return (NSSCKMDCryptoOperation *)NULL;
-    }
-    iOperation->mdMechanism = mdMechanism;
-    iOperation->iKey = iKey;
-    iOperation->cssmContext = cssmContext;
-
-    nsslibc_memcpy(&iOperation->mdOperation,
-                   proto, sizeof(NSSCKMDCryptoOperation));
-    iOperation->mdOperation.etc = iOperation;
-
-    return &iOperation->mdOperation;
-}
-
-static void
-ckmk_mdCryptoOperationRSAPriv_Destroy(
-    NSSCKMDCryptoOperation *mdOperation,
-    NSSCKFWCryptoOperation *fwOperation,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    ckmkInternalCryptoOperationRSAPriv *iOperation =
-        (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
-
-    if (iOperation->buffer) {
-        nssItem_Destroy(iOperation->buffer);
-    }
-    if (iOperation->cssmContext) {
-        CSSM_DeleteContext(iOperation->cssmContext);
-    }
-    nss_ZFreeIf(iOperation);
-    return;
-}
-
-static CK_ULONG
-ckmk_mdCryptoOperationRSA_GetFinalLength(
-    NSSCKMDCryptoOperation *mdOperation,
-    NSSCKFWCryptoOperation *fwOperation,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    ckmkInternalCryptoOperationRSAPriv *iOperation =
-        (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
-    const NSSItem *modulus =
-        nss_ckmk_FetchAttribute(iOperation->iKey, CKA_MODULUS, pError);
-
-    return modulus->size;
-}
-
-/*
- * ckmk_mdCryptoOperationRSADecrypt_GetOperationLength
- * we won't know the length until we actually decrypt the
- * input block. Since we go to all the work to decrypt the
- * the block, we'll save if for when the block is asked for
- */
-static CK_ULONG
-ckmk_mdCryptoOperationRSADecrypt_GetOperationLength(
-    NSSCKMDCryptoOperation *mdOperation,
-    NSSCKFWCryptoOperation *fwOperation,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    const NSSItem *input,
-    CK_RV *pError)
-{
-    ckmkInternalCryptoOperationRSAPriv *iOperation =
-        (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
-    CSSM_DATA cssmInput;
-    CSSM_DATA cssmOutput = { 0, NULL };
-    PRUint32 bytesDecrypted;
-    CSSM_DATA remainder = { 0, NULL };
-    NSSItem output;
-    CSSM_RETURN cssmErr;
-
-    if (iOperation->buffer) {
-        return iOperation->buffer->size;
-    }
-
-    cssmInput.Data = input->data;
-    cssmInput.Length = input->size;
-
-    cssmErr = CSSM_DecryptData(iOperation->cssmContext,
-                               &cssmInput, 1, &cssmOutput, 1,
-                               &bytesDecrypted, &remainder);
-    if (CSSM_OK != cssmErr) {
-        CKMK_MACERR("Decrypt Failed", cssmErr);
-        *pError = CKR_DATA_INVALID;
-        return 0;
-    }
-    /* we didn't suppy any buffers, so it should all be in remainder */
-    output.data = nss_ZNEWARRAY(NULL, char, bytesDecrypted + remainder.Length);
-    if (NULL == output.data) {
-        free(cssmOutput.Data);
-        free(remainder.Data);
-        *pError = CKR_HOST_MEMORY;
-        return 0;
-    }
-    output.size = bytesDecrypted + remainder.Length;
-
-    if (0 != bytesDecrypted) {
-        nsslibc_memcpy(output.data, cssmOutput.Data, bytesDecrypted);
-        free(cssmOutput.Data);
-    }
-    if (0 != remainder.Length) {
-        nsslibc_memcpy(((char *)output.data) + bytesDecrypted,
-                       remainder.Data, remainder.Length);
-        free(remainder.Data);
-    }
-
-    iOperation->buffer = nssItem_Duplicate(&output, NULL, NULL);
-    nss_ZFreeIf(output.data);
-    if ((NSSItem *)NULL == iOperation->buffer) {
-        *pError = CKR_HOST_MEMORY;
-        return 0;
-    }
-
-    return iOperation->buffer->size;
-}
-
-/*
- * ckmk_mdCryptoOperationRSADecrypt_UpdateFinal
- *
- * NOTE: ckmk_mdCryptoOperationRSADecrypt_GetOperationLength is presumed to
- * have been called previously.
- */
-static CK_RV
-ckmk_mdCryptoOperationRSADecrypt_UpdateFinal(
-    NSSCKMDCryptoOperation *mdOperation,
-    NSSCKFWCryptoOperation *fwOperation,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    const NSSItem *input,
-    NSSItem *output)
-{
-    ckmkInternalCryptoOperationRSAPriv *iOperation =
-        (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
-    NSSItem *buffer = iOperation->buffer;
-
-    if ((NSSItem *)NULL == buffer) {
-        return CKR_GENERAL_ERROR;
-    }
-    nsslibc_memcpy(output->data, buffer->data, buffer->size);
-    output->size = buffer->size;
-    return CKR_OK;
-}
-
-/*
- * ckmk_mdCryptoOperationRSASign_UpdateFinal
- *
- */
-static CK_RV
-ckmk_mdCryptoOperationRSASign_UpdateFinal(
-    NSSCKMDCryptoOperation *mdOperation,
-    NSSCKFWCryptoOperation *fwOperation,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    const NSSItem *input,
-    NSSItem *output)
-{
-    ckmkInternalCryptoOperationRSAPriv *iOperation =
-        (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
-    CSSM_DATA cssmInput;
-    CSSM_DATA cssmOutput = { 0, NULL };
-    CSSM_RETURN cssmErr;
-
-    cssmInput.Data = input->data;
-    cssmInput.Length = input->size;
-
-    cssmErr = CSSM_SignData(iOperation->cssmContext, &cssmInput, 1,
-                            CSSM_ALGID_NONE, &cssmOutput);
-    if (CSSM_OK != cssmErr) {
-        CKMK_MACERR("Signed Failed", cssmErr);
-        return CKR_FUNCTION_FAILED;
-    }
-    if (cssmOutput.Length > output->size) {
-        free(cssmOutput.Data);
-        return CKR_BUFFER_TOO_SMALL;
-    }
-    nsslibc_memcpy(output->data, cssmOutput.Data, cssmOutput.Length);
-    free(cssmOutput.Data);
-    output->size = cssmOutput.Length;
-
-    return CKR_OK;
-}
-
-NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
-    ckmk_mdCryptoOperationRSADecrypt_proto = {
-        NULL, /* etc */
-        ckmk_mdCryptoOperationRSAPriv_Destroy,
-        NULL, /* GetFinalLengh - not needed for one shot Decrypt/Encrypt */
-        ckmk_mdCryptoOperationRSADecrypt_GetOperationLength,
-        NULL, /* Final - not needed for one shot operation */
-        NULL, /* Update - not needed for one shot operation */
-        NULL, /* DigetUpdate - not needed for one shot operation */
-        ckmk_mdCryptoOperationRSADecrypt_UpdateFinal,
-        NULL,        /* UpdateCombo - not needed for one shot operation */
-        NULL,        /* DigetKey - not needed for one shot operation */
-        (void *)NULL /* null terminator */
-    };
-
-NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
-    ckmk_mdCryptoOperationRSASign_proto = {
-        NULL, /* etc */
-        ckmk_mdCryptoOperationRSAPriv_Destroy,
-        ckmk_mdCryptoOperationRSA_GetFinalLength,
-        NULL, /* GetOperationLengh - not needed for one shot Sign/Verify */
-        NULL, /* Final - not needed for one shot operation */
-        NULL, /* Update - not needed for one shot operation */
-        NULL, /* DigetUpdate - not needed for one shot operation */
-        ckmk_mdCryptoOperationRSASign_UpdateFinal,
-        NULL,        /* UpdateCombo - not needed for one shot operation */
-        NULL,        /* DigetKey - not needed for one shot operation */
-        (void *)NULL /* null terminator */
-    };
-
-/********** NSSCKMDMechansim functions ***********************/
-/*
- * ckmk_mdMechanismRSA_Destroy
- */
-static void
-ckmk_mdMechanismRSA_Destroy(
-    NSSCKMDMechanism *mdMechanism,
-    NSSCKFWMechanism *fwMechanism,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    nss_ZFreeIf(fwMechanism);
-}
-
-/*
- * ckmk_mdMechanismRSA_GetMinKeySize
- */
-static CK_ULONG
-ckmk_mdMechanismRSA_GetMinKeySize(
-    NSSCKMDMechanism *mdMechanism,
-    NSSCKFWMechanism *fwMechanism,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    return 384;
-}
-
-/*
- * ckmk_mdMechanismRSA_GetMaxKeySize
- */
-static CK_ULONG
-ckmk_mdMechanismRSA_GetMaxKeySize(
-    NSSCKMDMechanism *mdMechanism,
-    NSSCKFWMechanism *fwMechanism,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    return 16384;
-}
-
-/*
- * ckmk_mdMechanismRSA_DecryptInit
- */
-static NSSCKMDCryptoOperation *
-ckmk_mdMechanismRSA_DecryptInit(
-    NSSCKMDMechanism *mdMechanism,
-    NSSCKFWMechanism *fwMechanism,
-    CK_MECHANISM *pMechanism,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    NSSCKMDObject *mdKey,
-    NSSCKFWObject *fwKey,
-    CK_RV *pError)
-{
-    return ckmk_mdCryptoOperationRSAPriv_Create(
-        &ckmk_mdCryptoOperationRSADecrypt_proto,
-        mdMechanism, mdKey, CKMK_DECRYPT, pError);
-}
-
-/*
- * ckmk_mdMechanismRSA_SignInit
- */
-static NSSCKMDCryptoOperation *
-ckmk_mdMechanismRSA_SignInit(
-    NSSCKMDMechanism *mdMechanism,
-    NSSCKFWMechanism *fwMechanism,
-    CK_MECHANISM *pMechanism,
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    NSSCKMDObject *mdKey,
-    NSSCKFWObject *fwKey,
-    CK_RV *pError)
-{
-    return ckmk_mdCryptoOperationRSAPriv_Create(
-        &ckmk_mdCryptoOperationRSASign_proto,
-        mdMechanism, mdKey, CKMK_SIGN, pError);
-}
-
-NSS_IMPLEMENT_DATA const NSSCKMDMechanism
-    nss_ckmk_mdMechanismRSA = {
-        (void *)NULL, /* etc */
-        ckmk_mdMechanismRSA_Destroy,
-        ckmk_mdMechanismRSA_GetMinKeySize,
-        ckmk_mdMechanismRSA_GetMaxKeySize,
-        NULL, /* GetInHardware - default false */
-        NULL, /* EncryptInit - default errs */
-        ckmk_mdMechanismRSA_DecryptInit,
-        NULL, /* DigestInit - default errs*/
-        ckmk_mdMechanismRSA_SignInit,
-        NULL,                         /* VerifyInit - default errs */
-        ckmk_mdMechanismRSA_SignInit, /* SignRecoverInit */
-        NULL,                         /* VerifyRecoverInit - default errs */
-        NULL,                         /* GenerateKey - default errs */
-        NULL,                         /* GenerateKeyPair - default errs */
-        NULL,                         /* GetWrapKeyLength - default errs */
-        NULL,                         /* WrapKey - default errs */
-        NULL,                         /* UnwrapKey - default errs */
-        NULL,                         /* DeriveKey - default errs */
-        (void *)NULL                  /* null terminator */
-    };
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/msession.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/* 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 "ckmk.h"
-
-/*
- * nssmkey/msession.c
- *
- * This file implements the NSSCKMDSession object for the
- * "nssmkey" cryptoki module.
- */
-
-static NSSCKMDFindObjects *
-ckmk_mdSession_FindObjectsInit(
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_ATTRIBUTE_PTR pTemplate,
-    CK_ULONG ulAttributeCount,
-    CK_RV *pError)
-{
-    return nss_ckmk_FindObjectsInit(fwSession, pTemplate, ulAttributeCount, pError);
-}
-
-static NSSCKMDObject *
-ckmk_mdSession_CreateObject(
-    NSSCKMDSession *mdSession,
-    NSSCKFWSession *fwSession,
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    NSSArena *arena,
-    CK_ATTRIBUTE_PTR pTemplate,
-    CK_ULONG ulAttributeCount,
-    CK_RV *pError)
-{
-    return nss_ckmk_CreateObject(fwSession, pTemplate, ulAttributeCount, pError);
-}
-
-NSS_IMPLEMENT NSSCKMDSession *
-nss_ckmk_CreateSession(
-    NSSCKFWSession *fwSession,
-    CK_RV *pError)
-{
-    NSSArena *arena;
-    NSSCKMDSession *rv;
-
-    arena = NSSCKFWSession_GetArena(fwSession, pError);
-    if ((NSSArena *)NULL == arena) {
-        return (NSSCKMDSession *)NULL;
-    }
-
-    rv = nss_ZNEW(arena, NSSCKMDSession);
-    if ((NSSCKMDSession *)NULL == rv) {
-        *pError = CKR_HOST_MEMORY;
-        return (NSSCKMDSession *)NULL;
-    }
-
-    /*
-     * rv was zeroed when allocated, so we only
-     * need to set the non-zero members.
-     */
-
-    rv->etc = (void *)fwSession;
-    /* rv->Close */
-    /* rv->GetDeviceError */
-    /* rv->Login */
-    /* rv->Logout */
-    /* rv->InitPIN */
-    /* rv->SetPIN */
-    /* rv->GetOperationStateLen */
-    /* rv->GetOperationState */
-    /* rv->SetOperationState */
-    rv->CreateObject = ckmk_mdSession_CreateObject;
-    /* rv->CopyObject */
-    rv->FindObjectsInit = ckmk_mdSession_FindObjectsInit;
-    /* rv->SeedRandom */
-    /* rv->GetRandom */
-    /* rv->null */
-
-    return rv;
-}
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/mslot.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/* 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 "ckmk.h"
-
-/*
- * nssmkey/mslot.c
- *
- * This file implements the NSSCKMDSlot object for the
- * "nssmkey" cryptoki module.
- */
-
-static NSSUTF8 *
-ckmk_mdSlot_GetSlotDescription(
-    NSSCKMDSlot *mdSlot,
-    NSSCKFWSlot *fwSlot,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    return (NSSUTF8 *)nss_ckmk_SlotDescription;
-}
-
-static NSSUTF8 *
-ckmk_mdSlot_GetManufacturerID(
-    NSSCKMDSlot *mdSlot,
-    NSSCKFWSlot *fwSlot,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    return (NSSUTF8 *)nss_ckmk_ManufacturerID;
-}
-
-static CK_VERSION
-ckmk_mdSlot_GetHardwareVersion(
-    NSSCKMDSlot *mdSlot,
-    NSSCKFWSlot *fwSlot,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    return nss_ckmk_HardwareVersion;
-}
-
-static CK_VERSION
-ckmk_mdSlot_GetFirmwareVersion(
-    NSSCKMDSlot *mdSlot,
-    NSSCKFWSlot *fwSlot,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    return nss_ckmk_FirmwareVersion;
-}
-
-static NSSCKMDToken *
-ckmk_mdSlot_GetToken(
-    NSSCKMDSlot *mdSlot,
-    NSSCKFWSlot *fwSlot,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    return (NSSCKMDToken *)&nss_ckmk_mdToken;
-}
-
-NSS_IMPLEMENT_DATA const NSSCKMDSlot
-    nss_ckmk_mdSlot = {
-        (void *)NULL, /* etc */
-        NULL,         /* Initialize */
-        NULL,         /* Destroy */
-        ckmk_mdSlot_GetSlotDescription,
-        ckmk_mdSlot_GetManufacturerID,
-        NULL, /* GetTokenPresent -- defaults to true */
-        NULL, /* GetRemovableDevice -- defaults to false */
-        NULL, /* GetHardwareSlot -- defaults to false */
-        ckmk_mdSlot_GetHardwareVersion,
-        ckmk_mdSlot_GetFirmwareVersion,
-        ckmk_mdSlot_GetToken,
-        (void *)NULL /* null terminator */
-    };
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/mtoken.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* 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 "ckmk.h"
-
-/*
- * nssmkey/mtoken.c
- *
- * This file implements the NSSCKMDToken object for the
- * "nssmkey" cryptoki module.
- */
-
-static NSSUTF8 *
-ckmk_mdToken_GetLabel(
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    return (NSSUTF8 *)nss_ckmk_TokenLabel;
-}
-
-static NSSUTF8 *
-ckmk_mdToken_GetManufacturerID(
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    return (NSSUTF8 *)nss_ckmk_ManufacturerID;
-}
-
-static NSSUTF8 *
-ckmk_mdToken_GetModel(
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    return (NSSUTF8 *)nss_ckmk_TokenModel;
-}
-
-static NSSUTF8 *
-ckmk_mdToken_GetSerialNumber(
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_RV *pError)
-{
-    return (NSSUTF8 *)nss_ckmk_TokenSerialNumber;
-}
-
-static CK_BBOOL
-ckmk_mdToken_GetIsWriteProtected(
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    return CK_FALSE;
-}
-
-/* fake out Mozilla so we don't try to initialize the token */
-static CK_BBOOL
-ckmk_mdToken_GetUserPinInitialized(
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    return CK_TRUE;
-}
-
-static CK_VERSION
-ckmk_mdToken_GetHardwareVersion(
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    return nss_ckmk_HardwareVersion;
-}
-
-static CK_VERSION
-ckmk_mdToken_GetFirmwareVersion(
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    return nss_ckmk_FirmwareVersion;
-}
-
-static NSSCKMDSession *
-ckmk_mdToken_OpenSession(
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    NSSCKFWSession *fwSession,
-    CK_BBOOL rw,
-    CK_RV *pError)
-{
-    return nss_ckmk_CreateSession(fwSession, pError);
-}
-
-static CK_ULONG
-ckmk_mdToken_GetMechanismCount(
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance)
-{
-    return (CK_ULONG)1;
-}
-
-static CK_RV
-ckmk_mdToken_GetMechanismTypes(
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_MECHANISM_TYPE types[])
-{
-    types[0] = CKM_RSA_PKCS;
-    return CKR_OK;
-}
-
-static NSSCKMDMechanism *
-ckmk_mdToken_GetMechanism(
-    NSSCKMDToken *mdToken,
-    NSSCKFWToken *fwToken,
-    NSSCKMDInstance *mdInstance,
-    NSSCKFWInstance *fwInstance,
-    CK_MECHANISM_TYPE which,
-    CK_RV *pError)
-{
-    if (which != CKM_RSA_PKCS) {
-        *pError = CKR_MECHANISM_INVALID;
-        return (NSSCKMDMechanism *)NULL;
-    }
-    return (NSSCKMDMechanism *)&nss_ckmk_mdMechanismRSA;
-}
-
-NSS_IMPLEMENT_DATA const NSSCKMDToken
-    nss_ckmk_mdToken = {
-        (void *)NULL, /* etc */
-        NULL,         /* Setup */
-        NULL,         /* Invalidate */
-        NULL,         /* InitToken -- default errs */
-        ckmk_mdToken_GetLabel,
-        ckmk_mdToken_GetManufacturerID,
-        ckmk_mdToken_GetModel,
-        ckmk_mdToken_GetSerialNumber,
-        NULL, /* GetHasRNG -- default is false */
-        ckmk_mdToken_GetIsWriteProtected,
-        NULL, /* GetLoginRequired -- default is false */
-        ckmk_mdToken_GetUserPinInitialized,
-        NULL, /* GetRestoreKeyNotNeeded -- irrelevant */
-        NULL, /* GetHasClockOnToken -- default is false */
-        NULL, /* GetHasProtectedAuthenticationPath -- default is false */
-        NULL, /* GetSupportsDualCryptoOperations -- default is false */
-        NULL, /* GetMaxSessionCount -- default is CK_UNAVAILABLE_INFORMATION */
-        NULL, /* GetMaxRwSessionCount -- default is CK_UNAVAILABLE_INFORMATION */
-        NULL, /* GetMaxPinLen -- irrelevant */
-        NULL, /* GetMinPinLen -- irrelevant */
-        NULL, /* GetTotalPublicMemory -- default is CK_UNAVAILABLE_INFORMATION */
-        NULL, /* GetFreePublicMemory -- default is CK_UNAVAILABLE_INFORMATION */
-        NULL, /* GetTotalPrivateMemory -- default is CK_UNAVAILABLE_INFORMATION */
-        NULL, /* GetFreePrivateMemory -- default is CK_UNAVAILABLE_INFORMATION */
-        ckmk_mdToken_GetHardwareVersion,
-        ckmk_mdToken_GetFirmwareVersion,
-        NULL, /* GetUTCTime -- no clock */
-        ckmk_mdToken_OpenSession,
-        ckmk_mdToken_GetMechanismCount,
-        ckmk_mdToken_GetMechanismTypes,
-        ckmk_mdToken_GetMechanism,
-        (void *)NULL /* null terminator */
-    };
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/nssmkey.def
+++ /dev/null
@@ -1,26 +0,0 @@
-;+#
-;+# 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/.
-;+#
-;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
-;+#   1. For all unix platforms, the string ";-"  means "remove this line"
-;+#   2. For all unix platforms, the string " DATA " will be removed from any 
-;+#     line on which it occurs.
-;+#   3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
-;+#      On AIX, lines containing ";+" will be removed.
-;+#   4. For all unix platforms, the string ";;" will thave the ";;" removed.
-;+#   5. For all unix platforms, after the above processing has taken place,
-;+#    all characters after the first ";" on the line will be removed.
-;+#    And for AIX, the first ";" will also be removed.
-;+#  This file is passed directly to windows. Since ';' is a comment, all UNIX
-;+#   directives are hidden behind ";", ";+", and ";-"
-;+
-;+NSSMKEY_3.0 {       # First release of nssmkey
-;+    global:
-LIBRARY nssmkey ;-
-EXPORTS ;-
-C_GetFunctionList;
-;+    local:
-;+*;
-;+};
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/nssmkey.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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/. */
-
-#ifndef NSSMKEY_H
-#define NSSMKEY_H
-
-/*
- * NSS CKMK Version numbers.
- *
- * These are the version numbers for the nssmkey module packaged with
- * this release on NSS. To determine the version numbers of the builtin
- * module you are using, use the appropriate PKCS #11 calls.
- *
- * These version numbers detail changes to the PKCS #11 interface. They map
- * to the PKCS #11 spec versions.
- */
-#define NSS_CKMK_CRYPTOKI_VERSION_MAJOR 2
-#define NSS_CKMK_CRYPTOKI_VERSION_MINOR 20
-
-/* These version numbers detail the changes
- * to the list of trusted certificates.
- *
- * NSS_CKMK_LIBRARY_VERSION_MINOR is a CK_BYTE.  It's not clear
- * whether we may use its full range (0-255) or only 0-99 because
- * of the comment in the CK_VERSION type definition.
- */
-#define NSS_CKMK_LIBRARY_VERSION_MAJOR 1
-#define NSS_CKMK_LIBRARY_VERSION_MINOR 1
-#define NSS_CKMK_LIBRARY_VERSION "1.1"
-
-/* These version numbers detail the semantic changes to the ckfw engine. */
-#define NSS_CKMK_HARDWARE_VERSION_MAJOR 1
-#define NSS_CKMK_HARDWARE_VERSION_MINOR 0
-
-/* These version numbers detail the semantic changes to ckbi itself
- * (new PKCS #11 objects), etc. */
-#define NSS_CKMK_FIRMWARE_VERSION_MAJOR 1
-#define NSS_CKMK_FIRMWARE_VERSION_MINOR 0
-
-#endif /* NSSMKEY_H */
deleted file mode 100644
--- a/security/nss/lib/ckfw/nssmkey/staticobj.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 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/. */
-
-#ifndef CKMK_H
-#include "ckmk.h"
-#endif /* CKMK_H */
-
-static const CK_TRUST ckt_netscape_valid = CKT_NETSCAPE_VALID;
-static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
-static const CK_TRUST ckt_netscape_trusted_delegator = CKT_NETSCAPE_TRUSTED_DELEGATOR;
-static const CK_OBJECT_CLASS cko_netscape_trust = CKO_NETSCAPE_TRUST;
-static const CK_BBOOL ck_true = CK_TRUE;
-static const CK_OBJECT_CLASS cko_data = CKO_DATA;
-static const CK_CERTIFICATE_TYPE ckc_x_509 = CKC_X_509;
-static const CK_BBOOL ck_false = CK_FALSE;
-static const CK_OBJECT_CLASS cko_netscape_builtin_root_list = CKO_NETSCAPE_BUILTIN_ROOT_LIST;
-
-/* example of a static object */
-static const CK_ATTRIBUTE_TYPE nss_ckmk_types_1[] = {
-    CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_MODIFIABLE, CKA_LABEL
-};
-
-static const NSSItem nss_ckmk_items_1[] = {
-    { (void *)&cko_data, (PRUint32)sizeof(CK_OBJECT_CLASS) },
-    { (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL) },
-    { (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) },
-    { (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) },
-    { (void *)"Mozilla Mac Key Ring Access", (PRUint32)28 }
-};
-
-ckmkInternalObject nss_ckmk_data[] = {
-    { ckmkRaw, { { 5, nss_ckmk_types_1, nss_ckmk_items_1 } }, CKO_DATA, { NULL } },
-};
-
-const PRUint32 nss_ckmk_nObjects = 1;
--- a/security/nss/lib/freebl/dsa.c
+++ b/security/nss/lib/freebl/dsa.c
@@ -11,24 +11,21 @@
 #include "prerror.h"
 #include "secerr.h"
 
 #include "prtypes.h"
 #include "prinit.h"
 #include "blapi.h"
 #include "nssilock.h"
 #include "secitem.h"
-#include "blapi.h"
+#include "blapit.h"
 #include "mpi.h"
 #include "secmpi.h"
 #include "pqg.h"
 
-/* XXX to be replaced by define in blapit.h */
-#define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048
-
 /*
  * FIPS 186-2 requires result from random output to be reduced mod q when
  * generating random numbers for DSA.
  *
  * Input: w, 2*qLen bytes
  *        q, qLen bytes
  * Output: xj, qLen bytes
  */
@@ -163,17 +160,17 @@ dsa_NewKeyExtended(const PQGParams *para
     PLArenaPool *arena;
     DSAPrivateKey *key;
     /* Check args. */
     if (!params || !privKey || !seed || !seed->data) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
     /* Initialize an arena for the DSA key. */
-    arena = PORT_NewArena(NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE);
+    arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
     if (!arena) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         return SECFailure;
     }
     key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
     if (!key) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         PORT_FreeArena(arena, PR_TRUE);
@@ -208,18 +205,19 @@ dsa_NewKeyExtended(const PQGParams *para
     MPINT_TO_SECITEM(&y, &key->publicValue, arena);
     *privKey = key;
     key = NULL;
 cleanup:
     mp_clear(&p);
     mp_clear(&g);
     mp_clear(&x);
     mp_clear(&y);
-    if (key)
+    if (key) {
         PORT_FreeArena(key->params.arena, PR_TRUE);
+    }
     if (err) {
         translate_mpi_error(err);
         return SECFailure;
     }
     return SECSuccess;
 }
 
 SECStatus
@@ -316,16 +314,17 @@ DSA_NewKeyFromSeed(const PQGParams *para
 static SECStatus
 dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
                const unsigned char *kb)
 {
     mp_int p, q, g; /* PQG parameters */
     mp_int x, k;    /* private key & pseudo-random integer */
     mp_int r, s;    /* tuple (r, s) is signature) */
     mp_int t;       /* holding tmp values */
+    mp_int ar;      /* holding blinding values */
     mp_err err = MP_OKAY;
     SECStatus rv = SECSuccess;
     unsigned int dsa_subprime_len, dsa_signature_len, offset;
     SECItem localDigest;
     unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN];
     SECItem t2 = { siBuffer, NULL, 0 };
 
     /* FIPS-compliance dictates that digest is a SHA hash. */
@@ -359,24 +358,26 @@ dsa_SignDigest(DSAPrivateKey *key, SECIt
     MP_DIGITS(&p) = 0;
     MP_DIGITS(&q) = 0;
     MP_DIGITS(&g) = 0;
     MP_DIGITS(&x) = 0;
     MP_DIGITS(&k) = 0;
     MP_DIGITS(&r) = 0;
     MP_DIGITS(&s) = 0;
     MP_DIGITS(&t) = 0;
+    MP_DIGITS(&ar) = 0;
     CHECK_MPI_OK(mp_init(&p));
     CHECK_MPI_OK(mp_init(&q));
     CHECK_MPI_OK(mp_init(&g));
     CHECK_MPI_OK(mp_init(&x));
     CHECK_MPI_OK(mp_init(&k));
     CHECK_MPI_OK(mp_init(&r));
     CHECK_MPI_OK(mp_init(&s));
     CHECK_MPI_OK(mp_init(&t));
+    CHECK_MPI_OK(mp_init(&ar));
     /*
     ** Convert stored PQG and private key into MPI integers.
     */
     SECITEM_TO_MPINT(key->params.prime, &p);
     SECITEM_TO_MPINT(key->params.subPrime, &q);
     SECITEM_TO_MPINT(key->params.base, &g);
     SECITEM_TO_MPINT(key->privateValue, &x);
     OCTETS_TO_MPINT(kb, &k, dsa_subprime_len);
@@ -392,24 +393,38 @@ dsa_SignDigest(DSAPrivateKey *key, SECIt
     **
     ** s = (k**-1 * (HASH(M) + x*r)) mod q
     */
     if (DSA_NewRandom(NULL, &key->params.subPrime, &t2) != SECSuccess) {
         PORT_SetError(SEC_ERROR_NEED_RANDOM);
         rv = SECFailure;
         goto cleanup;
     }
-    SECITEM_TO_MPINT(t2, &t);                /* t <-$ Zq */
+    SECITEM_TO_MPINT(t2, &t); /* t <-$ Zq */
+    SECITEM_FreeItem(&t2, PR_FALSE);
+    if (DSA_NewRandom(NULL, &key->params.subPrime, &t2) != SECSuccess) {
+        PORT_SetError(SEC_ERROR_NEED_RANDOM);
+        rv = SECFailure;
+        goto cleanup;
+    }
+    SECITEM_TO_MPINT(t2, &ar); /* ar <-$ Zq */
+    SECITEM_FreeItem(&t2, PR_FALSE);
+
+    /* Using mp_invmod on k directly would leak bits from k. */
+    CHECK_MPI_OK(mp_mul(&k, &ar, &k));       /* k = k * ar */
     CHECK_MPI_OK(mp_mulmod(&k, &t, &q, &k)); /* k = k * t mod q */
     CHECK_MPI_OK(mp_invmod(&k, &q, &k));     /* k = k**-1 mod q */
     CHECK_MPI_OK(mp_mulmod(&k, &t, &q, &k)); /* k = k * t mod q */
     SECITEM_TO_MPINT(localDigest, &s);       /* s = HASH(M)     */
-    CHECK_MPI_OK(mp_mulmod(&x, &r, &q, &x)); /* x = x * r mod q */
-    CHECK_MPI_OK(mp_addmod(&s, &x, &q, &s)); /* s = s + x mod q */
-    CHECK_MPI_OK(mp_mulmod(&s, &k, &q, &s)); /* s = s * k mod q */
+    /* To avoid leaking secret bits here the addition is blinded. */
+    CHECK_MPI_OK(mp_mul(&x, &ar, &x));        /* x = x * ar */
+    CHECK_MPI_OK(mp_mulmod(&x, &r, &q, &x));  /* x = x * r mod q */
+    CHECK_MPI_OK(mp_mulmod(&s, &ar, &q, &t)); /* t = s * ar mod q */
+    CHECK_MPI_OK(mp_add(&t, &x, &s));         /* s = t + x */
+    CHECK_MPI_OK(mp_mulmod(&s, &k, &q, &s));  /* s = s * k mod q */
     /*
     ** verify r != 0 and s != 0
     ** mentioned as optional in FIPS 186-1.
     */
     if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) {
         PORT_SetError(SEC_ERROR_NEED_RANDOM);
         rv = SECFailure;
         goto cleanup;
@@ -433,17 +448,17 @@ cleanup:
     mp_clear(&p);
     mp_clear(&q);
     mp_clear(&g);
     mp_clear(&x);
     mp_clear(&k);
     mp_clear(&r);
     mp_clear(&s);
     mp_clear(&t);
-    SECITEM_FreeItem(&t2, PR_FALSE);
+    mp_clear(&ar);
     if (err) {
         translate_mpi_error(err);
         rv = SECFailure;
     }
     return rv;
 }
 
 /* signature is caller-supplied buffer of at least 40 bytes.
--- a/security/nss/lib/freebl/ec.c
+++ b/security/nss/lib/freebl/ec.c
@@ -648,16 +648,17 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *k
                          const SECItem *digest, const unsigned char *kb, const int kblen)
 {
     SECStatus rv = SECFailure;
     mp_int x1;
     mp_int d, k; /* private key, random integer */
     mp_int r, s; /* tuple (r, s) is the signature */
     mp_int t;    /* holding tmp values */
     mp_int n;
+    mp_int ar; /* blinding value */
     mp_err err = MP_OKAY;
     ECParams *ecParams = NULL;
     SECItem kGpoint = { siBuffer, NULL, 0 };
     int flen = 0;   /* length in bytes of the field size */
     unsigned olen;  /* length in bytes of the base point order */
     unsigned obits; /* length in bits  of the base point order */
     unsigned char *t2 = NULL;
 
@@ -669,16 +670,17 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *k
     /* must happen before the first potential call to cleanup */
     MP_DIGITS(&x1) = 0;
     MP_DIGITS(&d) = 0;
     MP_DIGITS(&k) = 0;
     MP_DIGITS(&r) = 0;
     MP_DIGITS(&s) = 0;
     MP_DIGITS(&n) = 0;
     MP_DIGITS(&t) = 0;
+    MP_DIGITS(&ar) = 0;
 
     /* Check args */
     if (!key || !signature || !digest || !kb || (kblen < 0)) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         goto cleanup;
     }
 
     ecParams = &(key->ecParams);
@@ -695,16 +697,17 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *k
 
     CHECK_MPI_OK(mp_init(&x1));
     CHECK_MPI_OK(mp_init(&d));
     CHECK_MPI_OK(mp_init(&k));
     CHECK_MPI_OK(mp_init(&r));
     CHECK_MPI_OK(mp_init(&s));
     CHECK_MPI_OK(mp_init(&n));
     CHECK_MPI_OK(mp_init(&t));
+    CHECK_MPI_OK(mp_init(&ar));
 
     SECITEM_TO_MPINT(ecParams->order, &n);
     SECITEM_TO_MPINT(key->privateValue, &d);
 
     CHECK_MPI_OK(mp_read_unsigned_octets(&k, kb, kblen));
     /* Make sure k is in the interval [1, n-1] */
     if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
 #if EC_DEBUG
@@ -810,22 +813,35 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *k
         goto cleanup;
     }
     if (RNG_GenerateGlobalRandomBytes(t2, 2 * ecParams->order.len) != SECSuccess) {
         PORT_SetError(SEC_ERROR_NEED_RANDOM);
         rv = SECFailure;
         goto cleanup;
     }
     CHECK_MPI_OK(mp_read_unsigned_octets(&t, t2, 2 * ecParams->order.len)); /* t <-$ Zn */
-    CHECK_MPI_OK(mp_mulmod(&k, &t, &n, &k));                                /* k = k * t mod n */
-    CHECK_MPI_OK(mp_invmod(&k, &n, &k));                                    /* k = k**-1 mod n */
-    CHECK_MPI_OK(mp_mulmod(&k, &t, &n, &k));                                /* k = k * t mod n */
-    CHECK_MPI_OK(mp_mulmod(&d, &r, &n, &d));                                /* d = d * r mod n */
-    CHECK_MPI_OK(mp_addmod(&s, &d, &n, &s));                                /* s = s + d mod n */
-    CHECK_MPI_OK(mp_mulmod(&s, &k, &n, &s));                                /* s = s * k mod n */
+    PORT_Memset(t2, 0, 2 * ecParams->order.len);
+    if (RNG_GenerateGlobalRandomBytes(t2, 2 * ecParams->order.len) != SECSuccess) {
+        PORT_SetError(SEC_ERROR_NEED_RANDOM);
+        rv = SECFailure;
+        goto cleanup;
+    }
+    CHECK_MPI_OK(mp_read_unsigned_octets(&ar, t2, 2 * ecParams->order.len)); /* ar <-$ Zn */
+
+    /* Using mp_invmod on k directly would leak bits from k. */
+    CHECK_MPI_OK(mp_mul(&k, &ar, &k));       /* k = k * ar */
+    CHECK_MPI_OK(mp_mulmod(&k, &t, &n, &k)); /* k = k * t mod n */
+    CHECK_MPI_OK(mp_invmod(&k, &n, &k));     /* k = k**-1 mod n */
+    CHECK_MPI_OK(mp_mulmod(&k, &t, &n, &k)); /* k = k * t mod n */
+    /* To avoid leaking secret bits here the addition is blinded. */
+    CHECK_MPI_OK(mp_mul(&d, &ar, &t));        /* t = d * ar */
+    CHECK_MPI_OK(mp_mulmod(&t, &r, &n, &d));  /* d = t * r mod n */
+    CHECK_MPI_OK(mp_mulmod(&s, &ar, &n, &t)); /* t = s * ar mod n */
+    CHECK_MPI_OK(mp_add(&t, &d, &s));         /* s = t + d */
+    CHECK_MPI_OK(mp_mulmod(&s, &k, &n, &s));  /* s = s * k mod n */
 
 #if EC_DEBUG
     mp_todecimal(&s, mpstr);
     printf("s : %s (dec)\n", mpstr);
     mp_tohex(&s, mpstr);
     printf("s : %s\n", mpstr);
 #endif
 
@@ -853,16 +869,17 @@ finish:
 cleanup:
     mp_clear(&x1);
     mp_clear(&d);
     mp_clear(&k);
     mp_clear(&r);
     mp_clear(&s);
     mp_clear(&n);
     mp_clear(&t);
+    mp_clear(&ar);
 
     if (t2) {
         PORT_Free(t2);
     }
 
     if (kGpoint.data) {
         PORT_ZFree(kGpoint.data, kGpoint.len);
     }
--- a/security/nss/lib/pkcs12/p12e.c
+++ b/security/nss/lib/pkcs12/p12e.c
@@ -879,17 +879,19 @@ sec_PKCS12AddAttributeToBag(SEC_PKCS12Ex
     sec_PKCS12Attribute *attribute;
     void *mark = NULL, *dummy = NULL;
     SECOidData *oiddata = NULL;
     SECItem unicodeName = { siBuffer, NULL, 0 };
     void *src = NULL;
     unsigned int nItems = 0;
     SECStatus rv;
 
-    if (!safeBag || !p12ctxt) {
+    PORT_Assert(p12ctxt->arena == safeBag->arena);
+    if (!safeBag || !p12ctxt || p12ctxt->arena != safeBag->arena) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
     mark = PORT_ArenaMark(safeBag->arena);
 
     /* allocate the attribute */
     attribute = (sec_PKCS12Attribute *)PORT_ArenaZAlloc(safeBag->arena,
                                                         sizeof(sec_PKCS12Attribute));
@@ -1584,16 +1586,17 @@ sec_pkcs12_encoder_start_context(SEC_PKC
             /*
              * This code only works with PKCS #12 Mac using PKCS #5 v1
              * PBA keygens. PKCS #5 v2 support will require a change to
              * the PKCS #12 spec.
              */
             params = PK11_CreatePBEParams(salt, &pwd,
                                           NSS_PBE_DEFAULT_ITERATION_COUNT);
             SECITEM_ZfreeItem(salt, PR_TRUE);
+            salt = NULL;
             SECITEM_ZfreeItem(&pwd, PR_FALSE);
 
             /* get the PBA Mechanism to generate the key */
             switch (p12exp->integrityInfo.pwdInfo.algorithm) {
                 case SEC_OID_SHA1:
                     integrityMechType = CKM_PBA_SHA1_WITH_SHA1_HMAC;
                     break;
                 case SEC_OID_MD5:
--- a/security/nss/lib/softoken/legacydb/pcertdb.c
+++ b/security/nss/lib/softoken/legacydb/pcertdb.c
@@ -2572,24 +2572,23 @@ ReadDBSubjectEntry(NSSLOWCERTCertDBHandl
     PLArenaPool *arena = NULL;
     PORTCheapArenaPool tmpArena;
 
     certDBEntrySubject *entry;
     SECItem dbkey;
     SECItem dbentry;
     SECStatus rv;
 
+    PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     if (arena == NULL) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         goto loser;
     }
 
-    PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
-
     entry = (certDBEntrySubject *)PORT_ArenaAlloc(arena,
                                                   sizeof(certDBEntrySubject));
     if (entry == NULL) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         goto loser;
     }
     entry->common.arena = arena;
     entry->common.type = certDBEntryTypeSubject;
--- a/security/nss/lib/softoken/sftkpwd.c
+++ b/security/nss/lib/softoken/sftkpwd.c
@@ -133,22 +133,24 @@ const SEC_ASN1Template sftkdb_EncryptedD
  */
 static SECStatus
 sftkdb_decodeCipherText(SECItem *cipherText, sftkCipherValue *cipherValue)
 {
     PLArenaPool *arena = NULL;
     SFTKDBEncryptedDataInfo edi;
     SECStatus rv;
 
+    PORT_Assert(cipherValue);
+    cipherValue->arena = NULL;
+    cipherValue->param = NULL;
+
     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     if (arena == NULL) {
         return SECFailure;
     }
-    cipherValue->arena = NULL;
-    cipherValue->param = NULL;
 
     rv = SEC_QuickDERDecodeItem(arena, &edi, sftkdb_EncryptedDataInfoTemplate,
                                 cipherText);
     if (rv != SECSuccess) {
         goto loser;
     }
     cipherValue->alg = SECOID_GetAlgorithmTag(&edi.algorithm);
     cipherValue->param = nsspkcs5_AlgidToParam(&edi.algorithm);
--- a/security/nss/lib/ssl/dtlscon.c
+++ b/security/nss/lib/ssl/dtlscon.c
@@ -719,23 +719,26 @@ dtls_FragmentHandshake(sslSocket *ss, DT
                      SSL_GETPID(), ss->fd, msgSeq, fragmentOffset, end));
 
         /* Cut down to the data we have available. */
         PORT_Assert(fragmentOffset <= contentLen);
         PORT_Assert(fragmentOffset <= end);
         PORT_Assert(end <= contentLen);
         fragmentLen = PR_MIN(end, contentLen) - fragmentOffset;
 
-        /* Reduce to the space remaining in the MTU.  Allow for any existing
-         * messages, record expansion, and the handshake header. */
+        /* Limit further by the record size limit.  Account for the header. */
+        fragmentLen = PR_MIN(fragmentLen,
+                             msg->cwSpec->recordSizeLimit - DTLS_HS_HDR_LEN);
+
+        /* Reduce to the space remaining in the MTU. */
         fragmentLen = PR_MIN(fragmentLen,
                              ss->ssl3.mtu -           /* MTU estimate. */
-                                 ss->pendingBuf.len - /* Less unsent records. */
+                                 ss->pendingBuf.len - /* Less any unsent records. */
                                  DTLS_MAX_EXPANSION - /* Allow for expansion. */
-                                 DTLS_HS_HDR_LEN);    /* + handshake header. */
+                                 DTLS_HS_HDR_LEN);    /* And the handshake header. */
         PORT_Assert(fragmentLen > 0 || fragmentOffset == 0);
 
         /* Make totally sure that we will fit in the buffer. This should be
          * impossible; DTLS_MAX_MTU should always be more than ss->ssl3.mtu. */
         if (fragmentLen >= (DTLS_MAX_MTU - DTLS_HS_HDR_LEN)) {
             PORT_Assert(0);
             PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
             return SECFailure;
--- a/security/nss/lib/ssl/ssl.h
+++ b/security/nss/lib/ssl/ssl.h
@@ -238,16 +238,38 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRF
  * the rest of the TLS data. See [draft-ietf-tls-tls13; Section 8]
  * for more details.
  *
  * Note: when DTLS 1.3 is in use, any 0-RTT data received after EndOfEarlyData
  * (e.g., because of reordering) is discarded.
  */
 #define SSL_ENABLE_0RTT_DATA 33
 
+/* Sets a limit to the size of encrypted records (see
+ * draft-ietf-tls-record-limit). This is the value that is advertised to peers,
+ * not a limit on the size of records that will be created.  Setting this value
+ * reduces the size of records that will be received (not sent).
+ *
+ * This limit applies to the plaintext, but the records that appear on the wire
+ * will be bigger.  This doesn't include record headers, IVs, block cipher
+ * padding, and authentication tags or MACs.
+ *
+ * NSS always advertises the record size limit extension.  If this option is not
+ * set, the extension will contain the maximum allowed size for the selected TLS
+ * version (currently this is 16384 or 2^14 for TLS 1.2 and lower and 16385 for
+ * TLS 1.3).
+ *
+ * By default, NSS creates records that are the maximum size possible, using all
+ * the data that was written by the application.  Writes larger than the maximum
+ * are split into maximum sized records, and any remainder (unless
+ * SSL_CBC_RANDOM_IV is enabled and active).  If a peer advertises a record size
+ * limit then that value is used instead.
+ */
+#define SSL_RECORD_SIZE_LIMIT 34
+
 /* Enables TLS 1.3 compatibility mode.  In this mode, the client includes a fake
  * session ID in the handshake and sends a ChangeCipherSpec.  A server will
  * always use the setting chosen by the client, so the value of this option has
  * no effect for a server. This setting is ignored for DTLS. */
 #define SSL_ENABLE_TLS13_COMPAT_MODE 35
 
 /* Enables the sending of DTLS records using the short (two octet) record
  * header.  Only do this if there are 2^10 or fewer packets in flight at a time;
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -1471,16 +1471,23 @@ ssl3_SetupBothPendingCipherSpecs(sslSock
         goto loser;
     }
     rv = ssl3_SetupPendingCipherSpec(ss, CipherSpecWrite, suiteDef,
                                      &ss->ssl3.pwSpec);
     if (rv != SECSuccess) {
         goto loser;
     }
 
+    if (ssl3_ExtensionNegotiated(ss, ssl_record_size_limit_xtn)) {
+        ss->ssl3.prSpec->recordSizeLimit = PR_MIN(MAX_FRAGMENT_LENGTH,
+                                                  ss->opt.recordSizeLimit);
+        ss->ssl3.pwSpec->recordSizeLimit = PR_MIN(MAX_FRAGMENT_LENGTH,
+                                                  ss->xtnData.recordSizeLimit);
+    }
+
     ssl_ReleaseSpecWriteLock(ss); /*******************************/
     return SECSuccess;
 
 loser:
     ssl_ReleaseSpecWriteLock(ss);
     return SECFailure;
 }
 
@@ -2267,17 +2274,17 @@ ssl_ProtectNextRecord(sslSocket *ss, ssl
                       const PRUint8 *pIn, unsigned int nIn,
                       unsigned int *written)
 {
     sslBuffer *wrBuf = &ss->sec.writeBuf;
     unsigned int contentLen;
     unsigned int spaceNeeded;
     SECStatus rv;
 
-    contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH);
+    contentLen = PR_MIN(nIn, spec->recordSizeLimit);
     spaceNeeded = contentLen + SSL3_BUFFER_FUDGE;
     if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_1 &&
         spec->cipherDef->type == type_block) {
         spaceNeeded += spec->cipherDef->iv_size;
     }
     if (spaceNeeded > SSL_BUFFER_SPACE(wrBuf)) {
         rv = sslBuffer_Grow(wrBuf, spaceNeeded);
         if (rv != SECSuccess) {
@@ -12142,16 +12149,21 @@ ssl3_GetCipherSpec(sslSocket *ss, SSL3Ci
             return newSpec;
         }
     }
     SSL_TRC(10, ("%d: DTLS[%d]: Couldn't find cipherspec from epoch %d",
                  SSL_GETPID(), ss->fd, epoch));
     return NULL;
 }
 
+/* MAX_EXPANSION is the amount by which a record might plausibly be expanded
+ * when protected.  It's the worst case estimate, so the sum of block cipher
+ * padding (up to 256 octets) and HMAC (48 octets for SHA-384). */
+#define MAX_EXPANSION (256 + 48)
+
 /* if cText is non-null, then decipher and check the MAC of the
  * SSL record from cText->buf (typically gs->inbuf)
  * into databuf (typically gs->buf), and any previous contents of databuf
  * is lost.  Then handle databuf according to its SSL record type,
  * unless it's an application record.
  *
  * If cText is NULL, then the ciphertext has previously been deciphered and
  * checked, and is already sitting in databuf.  It is processed as an SSL
@@ -12171,16 +12183,17 @@ ssl3_GetCipherSpec(sslSocket *ss, SSL3Ci
  */
 SECStatus
 ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
 {
     SECStatus rv;
     PRBool isTLS;
     DTLSEpoch epoch;
     ssl3CipherSpec *spec = NULL;
+    PRUint16 recordSizeLimit;
     PRBool outOfOrderSpec = PR_FALSE;
     SSL3ContentType rType;
     sslBuffer *plaintext = &ss->gs.buf;
     SSL3AlertDescription alert = internal_error;
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
 
     /* check for Token Presence */
     if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) {
@@ -12225,22 +12238,30 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Cip
     if (cText->seqNum >= spec->cipherDef->max_records) {
         ssl_ReleaseSpecReadLock(ss); /*****************************/
         SSL_TRC(3, ("%d: SSL[%d]: read sequence number at limit 0x%0llx",
                     SSL_GETPID(), ss->fd, cText->seqNum));
         PORT_SetError(SSL_ERROR_TOO_MANY_RECORDS);
         return SECFailure;
     }
 
-    if (plaintext->space < MAX_FRAGMENT_LENGTH) {
-        rv = sslBuffer_Grow(plaintext, MAX_FRAGMENT_LENGTH + 2048);
+    recordSizeLimit = spec->recordSizeLimit;
+    if (cText->buf->len > recordSizeLimit + MAX_EXPANSION) {
+        ssl_ReleaseSpecReadLock(ss); /*****************************/
+        SSL3_SendAlert(ss, alert_fatal, record_overflow);
+        PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
+        return SECFailure;
+    }
+
+    if (plaintext->space < recordSizeLimit + MAX_EXPANSION) {
+        rv = sslBuffer_Grow(plaintext, recordSizeLimit + MAX_EXPANSION);
         if (rv != SECSuccess) {
             ssl_ReleaseSpecReadLock(ss); /*************************/
             SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes",
-                     SSL_GETPID(), ss->fd, MAX_FRAGMENT_LENGTH + 2048));
+                     SSL_GETPID(), ss->fd, recordSizeLimit + MAX_EXPANSION));
             /* sslBuffer_Grow has set a memory error code. */
             /* Perhaps we should send an alert. (but we have no memory!) */
             return SECFailure;
         }
     }
 
     /* Most record types aside from protected TLS 1.3 records carry the content
      * type in the first octet. TLS 1.3 will override this value later. */
@@ -12289,17 +12310,20 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Cip
             cText->buf->buf[0] == change_cipher_spec_choice) {
             /* Ignore the CCS. */
             return SECSuccess;
         }
 
         if (IS_DTLS(ss) ||
             (ss->sec.isServer &&
              ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_trial)) {
-            /* Silently drop the packet */
+            /* Silently drop the packet unless we sent a fatal alert. */
+            if (ss->ssl3.fatalAlertSent) {
+                return SECFailure;
+            }
             return SECSuccess;
         }
 
         int errCode = PORT_GetError();
         SSL3_SendAlert(ss, alert_fatal, alert);
         /* Reset the error code in case SSL3_SendAlert called
          * PORT_SetError(). */
         PORT_SetError(errCode);
@@ -12325,17 +12349,17 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Cip
      * from the wrong epoch. Divert to a divert processing function to make
      * sure we don't accidentally use the data unsafely. */
     if (outOfOrderSpec) {
         PORT_Assert(IS_DTLS(ss) && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
         return dtls13_HandleOutOfEpochRecord(ss, spec, rType, plaintext);
     }
 
     /* Check the length of the plaintext. */
-    if (isTLS && plaintext->len > MAX_FRAGMENT_LENGTH) {
+    if (isTLS && plaintext->len > recordSizeLimit) {
         plaintext->len = 0;
         SSL3_SendAlert(ss, alert_fatal, record_overflow);
         PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
         return SECFailure;
     }
 
     /* Application data records are processed by the caller of this
     ** function, not by this function.
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -45,16 +45,17 @@ static const ssl3ExtensionHandler client
     { ssl_signature_algorithms_xtn, &ssl3_HandleSigAlgsXtn },
     { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
     { ssl_signed_cert_timestamp_xtn, &ssl3_ServerHandleSignedCertTimestampXtn },
     { ssl_tls13_key_share_xtn, &tls13_ServerHandleKeyShareXtn },
     { ssl_tls13_pre_shared_key_xtn, &tls13_ServerHandlePreSharedKeyXtn },
     { ssl_tls13_early_data_xtn, &tls13_ServerHandleEarlyDataXtn },
     { ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ServerHandlePskModesXtn },
     { ssl_tls13_cookie_xtn, &tls13_ServerHandleCookieXtn },
+    { ssl_record_size_limit_xtn, &ssl_HandleRecordSizeLimitXtn },
     { 0, NULL }
 };
 
 /* These two tables are used by the client, to handle server hello
  * extensions. */
 static const ssl3ExtensionHandler serverHelloHandlersTLS[] = {
     { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
     /* TODO: add a handler for ssl_ec_point_formats_xtn */
@@ -63,16 +64,17 @@ static const ssl3ExtensionHandler server
     { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn },
     { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn },
     { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
     { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
     { ssl_signed_cert_timestamp_xtn, &ssl3_ClientHandleSignedCertTimestampXtn },
     { ssl_tls13_key_share_xtn, &tls13_ClientHandleKeyShareXtn },
     { ssl_tls13_pre_shared_key_xtn, &tls13_ClientHandlePreSharedKeyXtn },
     { ssl_tls13_early_data_xtn, &tls13_ClientHandleEarlyDataXtn },
+    { ssl_record_size_limit_xtn, &ssl_HandleRecordSizeLimitXtn },
     { 0, NULL }
 };
 
 static const ssl3ExtensionHandler helloRetryRequestHandlers[] = {
     { ssl_tls13_key_share_xtn, tls13_ClientHandleKeyShareXtnHrr },
     { ssl_tls13_cookie_xtn, tls13_ClientHandleHrrCookie },
     { 0, NULL }
 };
@@ -129,16 +131,17 @@ static const sslExtensionBuilder clientH
       /* Some servers (e.g. WebSphere Application Server 7.0 and Tomcat) will
        * time out or terminate the connection if the last extension in the
        * client hello is empty. They are not intolerant of TLS 1.2, so list
        * signature_algorithms at the end. See bug 1243641. */
       { ssl_tls13_supported_versions_xtn, &tls13_ClientSendSupportedVersionsXtn },
       { ssl_signature_algorithms_xtn, &ssl3_SendSigAlgsXtn },
       { ssl_tls13_cookie_xtn, &tls13_ClientSendHrrCookieXtn },
       { ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ClientSendPskModesXtn },
+      { ssl_record_size_limit_xtn, &ssl_SendRecordSizeLimitXtn },
       /* The pre_shared_key extension MUST be last. */
       { ssl_tls13_pre_shared_key_xtn, &tls13_ClientSendPreSharedKeyXtn },
       { 0, NULL }
     };
 
 static const sslExtensionBuilder clientHelloSendersSSL3[] = {
     { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn },
     { 0, NULL }
--- a/security/nss/lib/ssl/ssl3ext.h
+++ b/security/nss/lib/ssl/ssl3ext.h
@@ -93,16 +93,19 @@ struct TLSExtensionDataStr {
     SECItem pskBinder;                     /* The binder for the first PSK. */
     unsigned int pskBindersLen;            /* The length of the binders. */
     PRUint32 ticketAge;                    /* Used to accept early data. */
     SECItem cookie;                        /* HRR Cookie. */
     const sslNamedGroupDef *selectedGroup; /* For HRR. */
     /* The application token contains a value that was passed to the client via
      * a session ticket, or the cookie in a HelloRetryRequest. */
     SECItem applicationToken;
+
+    /* The record size limit set by the peer. Our value is kept in ss->opt. */
+    PRUint16 recordSizeLimit;
 };
 
 typedef struct TLSExtensionStr {
     PRCList link;  /* The linked list link */
     PRUint16 type; /* Extension type */
     SECItem data;  /* Pointers into the handshake data. */
 } TLSExtension;
 
--- a/security/nss/lib/ssl/ssl3exthandle.c
+++ b/security/nss/lib/ssl/ssl3exthandle.c
@@ -1863,8 +1863,72 @@ ssl_HandleSupportedGroupsXtn(const sslSo
         }
     }
 
     /* Remember that we negotiated this extension. */
     xtnData->negotiated[xtnData->numNegotiated++] = ssl_supported_groups_xtn;
 
     return SECSuccess;
 }
+
+SECStatus
+ssl_HandleRecordSizeLimitXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+                             SECItem *data)
+{
+    SECStatus rv;
+    PRUint32 limit;
+    PRUint32 maxLimit = (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3)
+                            ? (MAX_FRAGMENT_LENGTH + 1)
+                            : MAX_FRAGMENT_LENGTH;
+
+    rv = ssl3_ExtConsumeHandshakeNumber(ss, &limit, 2, &data->data, &data->len);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+    if (data->len != 0 || limit < 64) {
+        ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter);
+        PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
+        return SECFailure;
+    }
+
+    if (ss->sec.isServer) {
+        rv = ssl3_RegisterExtensionSender(ss, xtnData, ssl_record_size_limit_xtn,
+                                          &ssl_SendRecordSizeLimitXtn);
+        if (rv != SECSuccess) {
+            return SECFailure; /* error already set. */
+        }
+    } else if (limit > maxLimit) {
+        /* The client can sensibly check the maximum. */
+        ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter);
+        PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
+        return SECFailure;
+    }
+
+    /* We can't enforce the maximum on a server. But we do need to ensure
+     * that we don't apply a limit that is too large. */
+    xtnData->recordSizeLimit = PR_MIN(maxLimit, limit);
+    xtnData->negotiated[xtnData->numNegotiated++] = ssl_record_size_limit_xtn;
+    return SECSuccess;
+}
+
+SECStatus
+ssl_SendRecordSizeLimitXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+                           sslBuffer *buf, PRBool *added)
+{
+    PRUint32 maxLimit;
+    if (ss->sec.isServer) {
+        maxLimit = (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3)
+                       ? (MAX_FRAGMENT_LENGTH + 1)
+                       : MAX_FRAGMENT_LENGTH;
+    } else {
+        maxLimit = (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3)
+                       ? (MAX_FRAGMENT_LENGTH + 1)
+                       : MAX_FRAGMENT_LENGTH;
+    }
+    PRUint32 limit = PR_MIN(ss->opt.recordSizeLimit, maxLimit);
+    SECStatus rv = sslBuffer_AppendNumber(buf, limit, 2);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+
+    *added = PR_TRUE;
+    return SECSuccess;
+}
--- a/security/nss/lib/ssl/ssl3exthandle.h
+++ b/security/nss/lib/ssl/ssl3exthandle.h
@@ -114,9 +114,16 @@ SECStatus ssl3_ClientSendSessionTicketXt
                                           sslBuffer *buf, PRBool *added);
 
 SECStatus ssl_SendSupportedGroupsXtn(const sslSocket *ss,
                                      TLSExtensionData *xtnData,
                                      sslBuffer *buf, PRBool *added);
 SECStatus ssl3_SendSupportedPointFormatsXtn(const sslSocket *ss,
                                             TLSExtensionData *xtnData,
                                             sslBuffer *buf, PRBool *added);
+SECStatus ssl_HandleRecordSizeLimitXtn(const sslSocket *ss,
+                                       TLSExtensionData *xtnData,
+                                       SECItem *data);
+SECStatus ssl_SendRecordSizeLimitXtn(const sslSocket *ss,
+                                     TLSExtensionData *xtnData,
+                                     sslBuffer *buf, PRBool *added);
+
 #endif
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -231,16 +231,17 @@ typedef struct {
 
 /* MAX_SIGNATURE_SCHEMES allows for all the values we support. */
 #define MAX_SIGNATURE_SCHEMES 15
 
 typedef struct sslOptionsStr {
     /* If SSL_SetNextProtoNego has been called, then this contains the
      * list of supported protocols. */
     SECItem nextProtoNego;
+    PRUint16 recordSizeLimit;
 
     PRUint32 maxEarlyDataSize;
     unsigned int useSecurity : 1;
     unsigned int useSocks : 1;
     unsigned int requestCertificate : 1;
     unsigned int requireCertificate : 2;
     unsigned int handshakeAsClient : 1;
     unsigned int handshakeAsServer : 1;
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -50,16 +50,17 @@ static const sslSocketOps ssl_secure_ops
 };
 
 /*
 ** default settings for socket enables
 */
 static sslOptions ssl_defaults = {
     .nextProtoNego = { siBuffer, NULL, 0 },
     .maxEarlyDataSize = 1 << 16,
+    .recordSizeLimit = MAX_FRAGMENT_LENGTH + 1,
     .useSecurity = PR_TRUE,
     .useSocks = PR_FALSE,
     .requestCertificate = PR_FALSE,
     .requireCertificate = SSL_REQUIRE_FIRST_HANDSHAKE,
     .handshakeAsClient = PR_FALSE,
     .handshakeAsServer = PR_FALSE,
     .noCache = PR_FALSE,
     .fdx = PR_FALSE,
@@ -798,16 +799,25 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 wh
         case SSL_REQUIRE_DH_NAMED_GROUPS:
             ss->opt.requireDHENamedGroups = val;
             break;
 
         case SSL_ENABLE_0RTT_DATA:
             ss->opt.enable0RttData = val;
             break;
 
+        case SSL_RECORD_SIZE_LIMIT:
+            if (val < 64 || val > (MAX_FRAGMENT_LENGTH + 1)) {
+                PORT_SetError(SEC_ERROR_INVALID_ARGS);
+                rv = SECFailure;
+            } else {
+                ss->opt.recordSizeLimit = val;
+            }
+            break;
+
         case SSL_ENABLE_TLS13_COMPAT_MODE:
             ss->opt.enableTls13CompatMode = val;
             break;
 
         case SSL_ENABLE_DTLS_SHORT_HEADER:
             ss->opt.enableDtlsShortHeader = val;
             break;
 
@@ -939,16 +949,19 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 wh
             val = ss->opt.enableSignedCertTimestamps;
             break;
         case SSL_REQUIRE_DH_NAMED_GROUPS:
             val = ss->opt.requireDHENamedGroups;
             break;
         case SSL_ENABLE_0RTT_DATA:
             val = ss->opt.enable0RttData;
             break;
+        case SSL_RECORD_SIZE_LIMIT:
+            val = ss->opt.recordSizeLimit;
+            break;
         case SSL_ENABLE_TLS13_COMPAT_MODE:
             val = ss->opt.enableTls13CompatMode;
             break;
         case SSL_ENABLE_DTLS_SHORT_HEADER:
             val = ss->opt.enableDtlsShortHeader;
             break;
         default:
             PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -1062,16 +1075,19 @@ SSL_OptionGetDefault(PRInt32 which, PRIn
             val = ssl_defaults.enableExtendedMS;
             break;
         case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
             val = ssl_defaults.enableSignedCertTimestamps;
             break;
         case SSL_ENABLE_0RTT_DATA:
             val = ssl_defaults.enable0RttData;
             break;
+        case SSL_RECORD_SIZE_LIMIT:
+            val = ssl_defaults.recordSizeLimit;
+            break;
         case SSL_ENABLE_TLS13_COMPAT_MODE:
             val = ssl_defaults.enableTls13CompatMode;
             break;
         case SSL_ENABLE_DTLS_SHORT_HEADER:
             val = ssl_defaults.enableDtlsShortHeader;
             break;
         default:
             PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -1247,16 +1263,24 @@ SSL_OptionSetDefault(PRInt32 which, PRIn
         case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
             ssl_defaults.enableSignedCertTimestamps = val;
             break;
 
         case SSL_ENABLE_0RTT_DATA:
             ssl_defaults.enable0RttData = val;
             break;
 
+        case SSL_RECORD_SIZE_LIMIT:
+            if (val < 64 || val > (MAX_FRAGMENT_LENGTH + 1)) {
+                PORT_SetError(SEC_ERROR_INVALID_ARGS);
+                return SECFailure;
+            }
+            ssl_defaults.recordSizeLimit = val;
+            break;
+
         case SSL_ENABLE_TLS13_COMPAT_MODE:
             ssl_defaults.enableTls13CompatMode = val;
             break;
 
         case SSL_ENABLE_DTLS_SHORT_HEADER:
             ssl_defaults.enableDtlsShortHeader = val;
             break;
 
--- a/security/nss/lib/ssl/sslspec.c
+++ b/security/nss/lib/ssl/sslspec.c
@@ -138,16 +138,17 @@ ssl_CreateCipherSpec(sslSocket *ss, Ciph
 {
     ssl3CipherSpec *spec = PORT_ZNew(ssl3CipherSpec);
     if (!spec) {
         return NULL;
     }
     spec->refCt = 1;
     spec->version = ss->version;
     spec->direction = direction;
+    spec->recordSizeLimit = MAX_FRAGMENT_LENGTH;
     SSL_TRC(10, ("%d: SSL[%d]: new %s spec %d ct=%d",
                  SSL_GETPID(), ss->fd, SPEC_DIR(spec), spec,
                  spec->refCt));
     return spec;
 }
 
 void
 ssl_SaveCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
--- a/security/nss/lib/ssl/sslspec.h
+++ b/security/nss/lib/ssl/sslspec.h
@@ -165,16 +165,20 @@ struct ssl3CipherSpecStr {
 
     /* The next sequence number to be sent or received. */
     sslSequenceNumber nextSeqNum;
     DTLSRecvdRecords recvdRecords;
 
     /* The number of 0-RTT bytes that can be sent or received in TLS 1.3. This
      * will be zero for everything but 0-RTT. */
     PRUint32 earlyDataRemaining;
+    /* The maximum plaintext length.  This differs from the configured or
+     * negotiated value for TLS 1.3; it is reduced by one to account for the
+     * content type octet. */
+    PRUint16 recordSizeLimit;
 };
 
 typedef void (*sslCipherSpecChangedFunc)(void *arg,
                                          PRBool sending,
                                          ssl3CipherSpec *newSpec);
 
 const ssl3BulkCipherDef *ssl_GetBulkCipherDef(const ssl3CipherSuiteDef *cipher_def);
 const ssl3MACDef *ssl_GetMacDefByAlg(SSL3MACAlgorithm mac);
--- a/security/nss/lib/ssl/sslt.h
+++ b/security/nss/lib/ssl/sslt.h
@@ -427,16 +427,17 @@ typedef enum {
     ssl_ec_point_formats_xtn = 11,
     ssl_signature_algorithms_xtn = 13,
     ssl_use_srtp_xtn = 14,
     ssl_app_layer_protocol_xtn = 16,
     /* signed_certificate_timestamp extension, RFC 6962 */
     ssl_signed_cert_timestamp_xtn = 18,
     ssl_padding_xtn = 21,
     ssl_extended_master_secret_xtn = 23,
+    ssl_record_size_limit_xtn = 28,
     ssl_session_ticket_xtn = 35,
     /* 40 was used in draft versions of TLS 1.3; it is now reserved. */
     ssl_tls13_pre_shared_key_xtn = 41,
     ssl_tls13_early_data_xtn = 42,
     ssl_tls13_supported_versions_xtn = 43,
     ssl_tls13_cookie_xtn = 44,
     ssl_tls13_psk_key_exchange_modes_xtn = 45,
     ssl_tls13_ticket_early_data_info_xtn = 46, /* Deprecated. */
@@ -449,17 +450,17 @@ typedef enum {
 } SSLExtensionType;
 
 /* This is the old name for the supported_groups extensions. */
 #define ssl_elliptic_curves_xtn ssl_supported_groups_xtn
 
 /* SSL_MAX_EXTENSIONS includes the maximum number of extensions that are
  * supported for any single message type.  That is, a ClientHello; ServerHello
  * and TLS 1.3 NewSessionTicket and HelloRetryRequest extensions have fewer. */
-#define SSL_MAX_EXTENSIONS 20
+#define SSL_MAX_EXTENSIONS 21
 
 /* Deprecated */
 typedef enum {
     ssl_dhe_group_none = 0,
     ssl_ff_dhe_2048_group = 1,
     ssl_ff_dhe_3072_group = 2,
     ssl_ff_dhe_4096_group = 3,
     ssl_ff_dhe_6144_group = 4,
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -3249,16 +3249,27 @@ tls13_SetupPendingCipherSpec(sslSocket *
     }
 
     if (spec->epoch == TrafficKeyEarlyApplicationData) {
         spec->earlyDataRemaining =
             ss->sec.ci.sid->u.ssl3.locked.sessionTicket.max_early_data_size;
     }
 
     tls13_SetSpecRecordVersion(ss, spec);
+
+    /* The record size limit is reduced by one so that the remainder of the
+     * record handling code can use the same checks for all versions. */
+    if (ssl3_ExtensionNegotiated(ss, ssl_record_size_limit_xtn)) {
+        spec->recordSizeLimit = ((spec->direction == CipherSpecRead)
+                                     ? ss->opt.recordSizeLimit
+                                     : ss->xtnData.recordSizeLimit) -
+                                1;
+    } else {
+        spec->recordSizeLimit = MAX_FRAGMENT_LENGTH;
+    }
     return SECSuccess;
 }
 
 /*
  * Called before sending alerts to set up the right key on the client.
  * We might encounter errors during the handshake where the current
  * key is ClearText or EarlyApplicationData. This
  * function switches to the Handshake key if possible.
@@ -4741,17 +4752,18 @@ static const struct {
                                     new_session_ticket) },
     { ssl_signed_cert_timestamp_xtn, _M3(client_hello, certificate_request,
                                          certificate) },
     { ssl_cert_status_xtn, _M3(client_hello, certificate_request,
                                certificate) },
     { ssl_tls13_cookie_xtn, _M2(client_hello, hello_retry_request) },
     { ssl_tls13_certificate_authorities_xtn, _M1(certificate_request) },
     { ssl_tls13_supported_versions_xtn, _M3(client_hello, server_hello,
-                                            hello_retry_request) }
+                                            hello_retry_request) },
+    { ssl_record_size_limit_xtn, _M2(client_hello, encrypted_extensions) }
 };
 
 tls13ExtensionStatus
 tls13_ExtensionStatus(PRUint16 extension, SSLHandshakeType message)
 {
     unsigned int i;
 
     PORT_Assert((message == ssl_hs_client_hello) ||
@@ -5010,16 +5022,26 @@ tls13_UnprotectRecord(sslSocket *ss,
     if (rv != SECSuccess) {
         SSL_TRC(3,
                 ("%d: TLS13[%d]: record has bogus MAC",
                  SSL_GETPID(), ss->fd));
         PORT_SetError(SSL_ERROR_BAD_MAC_READ);
         return SECFailure;
     }
 
+    /* There is a similar test in ssl3_HandleRecord, but this test is needed to
+     * account for padding.  It's safe to do this here (including the alert),
+     * because it only confirms that the record exceeded the size limit, which
+     * is apparent from the size of the ciphertext. */
+    if (plaintext->len > spec->recordSizeLimit + 1) {
+        SSL3_SendAlert(ss, alert_fatal, record_overflow);
+        PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
+        return SECFailure;
+    }
+
     /* The record is right-padded with 0s, followed by the true
      * content type, so read from the right until we receive a
      * nonzero byte. */
     while (plaintext->len > 0 && !(plaintext->buf[plaintext->len - 1])) {
         --plaintext->len;
     }
 
     /* Bogus padding. */
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -27,17 +27,17 @@ gecko_debug = ["nsstring/gecko_debug"]
 [dependencies]
 app_units = "0.6"
 arrayvec = "0.4.6"
 atomic_refcell = "0.1"
 bitflags = "1.0"
 byteorder = "1.0"
 cfg-if = "0.1.0"
 cssparser = "0.23.0"
-debug_unreachable = "0.1.1"
+new_debug_unreachable = "1.0"
 encoding_rs = {version = "0.7", optional = true}
 euclid = "0.17"
 fallible = { path = "../fallible" }
 fnv = "1.0"
 hashglobe = { path = "../hashglobe" }
 html5ever = {version = "0.22", optional = true}
 itertools = "0.7.6"
 itoa = "0.3"
@@ -45,17 +45,17 @@ lazy_static = "1"
 log = "0.4"
 malloc_size_of = { path = "../malloc_size_of" }
 malloc_size_of_derive = { path = "../malloc_size_of_derive" }
 matches = "0.1"
 nsstring = {path = "../../support/gecko/nsstring", optional = true}
 num_cpus = {version = "1.1.0", optional = true}
 num-integer = "0.1.32"
 num-traits = "0.1.32"
-ordered-float = "0.4"
+new-ordered-float = "1.0"
 owning_ref = "0.3.3"
 parking_lot = "0.5"
 precomputed-hash = "0.1.1"
 rayon = "1"
 selectors = { path = "../selectors" }
 serde = {version = "1.0", optional = true, features = ["derive"]}
 servo_arc = { path = "../servo_arc" }
 servo_atoms = {path = "../atoms", optional = true}
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -26,20 +26,21 @@ use smallvec::SmallVec;
 use std::{cmp, ptr};
 use std::mem::{self, ManuallyDrop};
 #[cfg(feature = "gecko")] use hash::FnvHashMap;
 use super::ComputedValues;
 use values::CSSFloat;
 use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
 use values::animated::color::RGBA as AnimatedRGBA;
 use values::animated::effects::Filter as AnimatedFilter;
+#[cfg(feature = "gecko")] use values::computed::TransitionProperty;
 use values::computed::{Angle, CalcLengthOrPercentage};
 use values::computed::{ClipRect, Context};
 use values::computed::{Length, LengthOrPercentage, LengthOrPercentageOrAuto};
-use values::computed::{LengthOrPercentageOrNone, MaxLength, TransitionProperty};
+use values::computed::{LengthOrPercentageOrNone, MaxLength};
 use values::computed::{NonNegativeNumber, Number, NumberOrPercentage, Percentage};
 use values::computed::length::NonNegativeLengthOrPercentage;
 use values::computed::ToComputedValue;
 use values::computed::transform::{DirectionVector, Matrix, Matrix3D};
 use values::computed::transform::TransformOperation as ComputedTransformOperation;
 use values::computed::transform::Transform as ComputedTransform;
 use values::computed::transform::Rotate as ComputedRotate;
 use values::computed::transform::Translate as ComputedTranslate;
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -14,17 +14,18 @@
 ${helpers.predefined_type(
     "display",
     "Display",
     "computed::Display::inline()",
     initial_specified_value="specified::Display::inline()",
     animation_value_type="discrete",
     flags="APPLIES_TO_PLACEHOLDER",
     spec="https://drafts.csswg.org/css-display/#propdef-display",
-    servo_restyle_damage="rebuild_and_reflow"
+    servo_restyle_damage="rebuild_and_reflow",
+    needs_context=product == "gecko"
 )}
 
 // FIXME(emilio): Listing all the display values here is very unfortunate, we should teach C++ to use the
 // Rust enum directly, or generate the conversions to `StyleDisplay`.
 ${helpers.gecko_keyword_conversion(
     Keyword('display', """
         inline block inline-block
         table inline-table table-row-group table-header-group table-footer-group
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -2496,16 +2496,17 @@ pub mod style_structs {
                 self.transition_duration_iter()
                     .take(self.transition_property_count())
                     .any(|t| t.seconds() > 0.)
             }
         % elif style_struct.name == "Column":
             /// Whether this is a multicol style.
             #[cfg(feature = "servo")]
             pub fn is_multicol(&self) -> bool {
+                use values::Either;
                 match self.column_width {
                     Either::First(_width) => true,
                     Either::Second(_auto) => !self.column_count.is_auto(),
                 }
             }
         % endif
     }
 
@@ -2694,16 +2695,36 @@ impl ComputedValues {
                 ${style_struct.ident},
             % endfor
             }
         })
     }
 
     /// Get the initial computed values.
     pub fn initial_values() -> &'static Self { &*INITIAL_SERVO_VALUES }
+
+    /// Serializes the computed value of this property as a string.
+    pub fn computed_value_to_string(&self, property: PropertyDeclarationId) -> String {
+        match property {
+            PropertyDeclarationId::Longhand(id) => {
+                let mut s = String::new();
+                self.get_longhand_property_value(
+                    id,
+                    &mut CssWriter::new(&mut s)
+                ).unwrap();
+                s
+            }
+            PropertyDeclarationId::Custom(name) => {
+                self.custom_properties
+                    .as_ref()
+                    .and_then(|map| map.get(name))
+                    .map_or(String::new(), |value| value.to_css_string())
+            }
+        }
+    }
 }
 
 #[cfg(feature = "servo")]
 impl ops::Deref for ComputedValues {
     type Target = ComputedValuesInner;
     fn deref(&self) -> &ComputedValuesInner {
         &self.inner
     }
@@ -2932,36 +2953,16 @@ impl ComputedValuesInner {
                 }
                 _ => {}
             }
         }
 
         // Neither perspective nor transform present
         false
     }
-
-    /// Serializes the computed value of this property as a string.
-    pub fn computed_value_to_string(&self, property: PropertyDeclarationId) -> String {
-        match property {
-            PropertyDeclarationId::Longhand(id) => {
-                let mut s = String::new();
-                self.get_longhand_property_value(
-                    property,
-                    &mut CssWriter::new(&mut s)
-                ).unwrap();
-                s
-            }
-            PropertyDeclarationId::Custom(name) => {
-                self.custom_properties
-                    .as_ref()
-                    .and_then(|map| map.get(name))
-                    .map_or(String::new(), |value| value.to_css_string())
-            }
-        }
-    }
 }
 
 % if product == "gecko":
     pub use ::servo_arc::RawOffsetArc as BuilderArc;
     /// Clone an arc, returning a regular arc
     fn clone_arc<T: 'static>(x: &BuilderArc<T>) -> Arc<T> {
         Arc::from_raw_offset(x.clone())
     }
--- a/servo/components/style/values/computed/length.rs
+++ b/servo/components/style/values/computed/length.rs
@@ -1,17 +1,17 @@
 /* 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/. */
 
 //! `<length>` computed values, and related ones.
 
 use app_units::Au;
 use logical_geometry::WritingMode;
-use ordered_float::NotNaN;
+use ordered_float::NotNan;
 use properties::LonghandId;
 use std::fmt::{self, Write};
 use std::ops::{Add, Neg};
 use style_traits::{CssWriter, ToCss};
 use style_traits::values::specified::AllowedNumericType;
 use super::{Context, Number, Percentage, ToComputedValue};
 use values::{specified, Auto, CSSFloat, Either, Normal};
 use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
@@ -386,24 +386,24 @@ impl LengthOrPercentage {
             Percentage(p) => p.0 == 0.0,
             Calc(_) => false,
         }
     }
 
     // CSSFloat doesn't implement Hash, so does CSSPixelLength. Therefore, we still use Au as the
     // hash key.
     #[allow(missing_docs)]
-    pub fn to_hash_key(&self) -> (Au, NotNaN<f32>) {
+    pub fn to_hash_key(&self) -> (Au, NotNan<f32>) {
         use self::LengthOrPercentage::*;
         match *self {
-            Length(l) => (Au::from(l), NotNaN::new(0.0).unwrap()),
-            Percentage(p) => (Au(0), NotNaN::new(p.0).unwrap()),
+            Length(l) => (Au::from(l), NotNan::new(0.0).unwrap()),
+            Percentage(p) => (Au(0), NotNan::new(p.0).unwrap()),
             Calc(c) => (
                 Au::from(c.unclamped_length()),
-                NotNaN::new(c.percentage()).unwrap(),
+                NotNan::new(c.percentage()).unwrap(),
             ),
         }
     }
 
     /// Returns the used value.
     pub fn to_used_value(&self, containing_length: Au) -> Au {
         Au::from(self.to_pixel_length(containing_length))
     }
--- a/servo/components/style_derive/specified_value_info.rs
+++ b/servo/components/style_derive/specified_value_info.rs
@@ -1,17 +1,17 @@
 /* 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/. */
 
 use cg;
+use parse::ParseVariantAttrs;
 use quote::Tokens;
 use syn::{Data, DeriveInput, Fields, Ident, Type};
 use to_css::{CssFieldAttrs, CssInputAttrs, CssVariantAttrs};
-use parse::ParseVariantAttrs;
 
 pub fn derive(mut input: DeriveInput) -> Tokens {
     let css_attrs = cg::parse_input_attrs::<CssInputAttrs>(&input);
     let mut types = vec![];
     let mut values = vec![];
 
     let input_ident = input.ident;
     let input_name = || cg::to_css_identifier(input_ident.as_ref());
deleted file mode 100644
--- a/third_party/rust/debug_unreachable/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{".travis.yml":"d91d0d75087934c2d0503a8c04439fea459a19182021bb0b699644d442f5b6fc","Cargo.toml":"f6be96c7687e8e39cffc3f22aff16d12d669a31e932c1b98ba590dbaa181ab22","README.md":"0311a4ecf6dd300c555ef0f2316e4ba919476782b6aed1c35b01d8cc2f958c72","examples/simple.rs":"c05b124bdad67bfe9e48998bff6a7c6a8789e7f7c9fb3f318f8028a68ef944ed","src/lib.rs":"ef4e6d5732fcad9da5a500f401ccd0b538b489ae50771d15d5a2ec0f501cd0f9","tests/check.rs":"ac8691f78269e1cb0cd010150e707f5ea5df14055883f0ee5a5b55a686c5b8de"},"package":"9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"}
\ No newline at end of file
deleted file mode 100644
--- a/third_party/rust/debug_unreachable/Cargo.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[package]
-
-name = "debug_unreachable"
-version = "0.1.1"
-authors = ["Jonathan Reem <jonathan.reem@gmail.com>"]
-repository = "https://github.com/reem/rust-debug-unreachable.git"
-description = "unreachable!() in debug, std::intrinsics::unreachable() in release."
-documentation = "https://crates.fyi/crates/debug_unreachable/0.1.1"
-readme = "README.md"
-license = "MIT"
-
-[lib]
-name = "debug_unreachable"
-path = "src/lib.rs"
-
-[dependencies]
-unreachable = "0.1"
-
deleted file mode 100644
--- a/third_party/rust/debug_unreachable/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# debug_unreachable
-
-> unreachable!() in debug, std::intrinsics::unreachable() in release.
-
-## [Documentation](https://crates.fyi/crates/debug_unreachable/0.1.1)
-
-## Usage
-
-Use the crates.io repository; add this to your `Cargo.toml` along
-with the rest of your dependencies:
-
-```toml
-[dependencies]
-debug_unreachable = "0.1"
-```
-
-## Author
-
-[Jonathan Reem](https://medium.com/@jreem) is the primary author and maintainer of debug-unreachable.
-
-## License
-
-MIT
-
deleted file mode 100644
--- a/third_party/rust/debug_unreachable/src/lib.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-#![deny(missing_docs, warnings)]
-
-//! `panic!()` in debug builds, optimization hint in release.
-
-extern crate unreachable;
-
-#[doc(hidden)]
-pub use unreachable::unreachable as __unreachable;
-
-#[macro_export]
-/// `panic!()` in debug builds, optimization hint in release.
-macro_rules! debug_unreachable {
-    () => { debug_unreachable!("entered unreachable code") };
-    ($e:expr) => {
-        if cfg!(ndebug) {
-            $crate::__unreachable()
-        } else {
-            panic!($e);
-        }
-    }
-}
-
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new-ordered-float/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".travis.yml":"b828951788f67d00e3869f32b15076dcd8b64d71889c9dacda339571d7da93ac","Cargo.toml":"b2d65471546d2c240fcc7522e68967a5ec9d13bf829dffd708a55739ef337a28","LICENSE-MIT":"f7715d38a3fa1b4ac97c5729740752505a39cb92ee83ab5b102aeb5eaa7cdea4","README.md":"53364727f8bdc8dac2f5a55e7b9741981b757ba5b9331e3ac8ed433b09ee2409","src/lib.rs":"a1fd03bd7601b842b60a94c6161c436befaf25b38f74b247a20e90c24fb2bd9f","tests/test.rs":"1bbfc79ee6e1ffa3fcc384e9ce1f5a9000a63a8ddbc84264caba0454d657f40a","tests/test_deprecated_names.rs":"6f661c27e8b4d625c02202895f220d573e3dccc8cf684c77e754c444403939f7"},"package":"8ccbebba6fb53a6d2bdcfaf79cb339bc136dee3bfff54dc337a334bafe36476a"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new-ordered-float/.travis.yml
@@ -0,0 +1,9 @@
+language: rust
+rust: nightly
+sudo: false
+env:
+    matrix:
+        - FEATURES=
+        - FEATURES="serde"
+script:
+    - cargo test -v --features "$FEATURES"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new-ordered-float/Cargo.toml
@@ -0,0 +1,34 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "new-ordered-float"
+version = "1.0.1"
+authors = ["Jonathan Reem <jonathan.reem@gmail.com>", "Matt Brubeck <mbrubeck@limpet.net>"]
+description = "Wrappers for total ordering on floats (fork of ordered-float)"
+readme = "README.md"
+license = "MIT"
+repository = "https://github.com/mbrubeck/rust-ordered-float"
+
+[lib]
+name = "ordered_float"
+[dependencies.num-traits]
+version = "0.2"
+
+[dependencies.serde]
+version = "1.0"
+optional = true
+
+[dependencies.unreachable]
+version = "1"
+[dev-dependencies.serde_test]
+version = "1.0"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new-ordered-float/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2015 Jonathan Reem
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new-ordered-float/README.md
@@ -0,0 +1,27 @@
+# Ordered Floats
+
+Provides several wrapper types for Ord and Eq implementations on f64.
+
+This is a fork of https://crates.io/crates/ordered-float
+
+## Usage
+
+Use the crates.io repository; add this to your `Cargo.toml` along
+with the rest of your dependencies:
+
+```toml
+[dependencies]
+new-ordered-float = "1.0"
+```
+
+In your Rust code, the library name is still `ordered_float`:
+
+```rust
+extern crate ordered_float;
+```
+
+See the [API documentation](https://docs.rs/new-ordered-float) for further details.
+
+## License
+
+MIT
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new-ordered-float/src/lib.rs
@@ -0,0 +1,741 @@
+#![cfg_attr(test, deny(warnings))]
+#![deny(missing_docs)]
+
+//! Wrappers for total order on Floats.
+
+extern crate num_traits;
+extern crate unreachable;
+
+use std::cmp::Ordering;
+use std::error::Error;
+use std::ops::{Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Rem,
+               RemAssign, Sub, SubAssign};
+use std::hash::{Hash, Hasher};
+use std::fmt;
+use std::io;
+use std::mem;
+use unreachable::unreachable;
+use num_traits::{Bounded, Float, FromPrimitive, Num, NumCast, One, Signed, ToPrimitive,
+                 Zero};
+
+/// A wrapper around Floats providing an implementation of Ord and Hash.
+///
+/// A NaN value cannot be stored in this type.
+#[deprecated(since = "0.6.0", note = "renamed to `NotNan`")]
+pub type NotNaN<T> = NotNan<T>;
+
+/// An error indicating an attempt to construct NotNan from a NaN
+#[deprecated(since = "0.6.0", note = "renamed to `FloatIsNan`")]
+pub type FloatIsNaN = FloatIsNan;
+
+// masks for the parts of the IEEE 754 float
+const SIGN_MASK: u64 = 0x8000000000000000u64;
+const EXP_MASK: u64 = 0x7ff0000000000000u64;
+const MAN_MASK: u64 = 0x000fffffffffffffu64;
+
+// canonical raw bit patterns (for hashing)
+const CANONICAL_NAN_BITS: u64 = 0x7ff8000000000000u64;
+const CANONICAL_ZERO_BITS: u64 = 0x0u64;
+
+/// A wrapper around Floats providing an implementation of Ord and Hash.
+///
+/// NaN is sorted as *greater* than all other values and *equal*
+/// to itself, in contradiction with the IEEE standard.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct OrderedFloat<T: Float>(pub T);
+
+impl<T: Float> OrderedFloat<T> {
+    /// Get the value out.
+    pub fn into_inner(self) -> T {
+        let OrderedFloat(val) = self;
+        val
+    }
+}
+
+impl<T: Float> AsRef<T> for OrderedFloat<T> {
+    fn as_ref(&self) -> &T {
+        let OrderedFloat(ref val) = *self;
+        val
+    }
+}
+
+impl<T: Float> AsMut<T> for OrderedFloat<T> {
+    fn as_mut(&mut self) -> &mut T {
+        let OrderedFloat(ref mut val) = *self;
+        val
+    }
+}
+
+impl<T: Float> PartialOrd for OrderedFloat<T> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl<T: Float> Ord for OrderedFloat<T> {
+    fn cmp(&self, other: &Self) -> Ordering {
+        let lhs = self.as_ref();
+        let rhs = other.as_ref();
+        match lhs.partial_cmp(&rhs) {
+            Some(ordering) => ordering,
+            None => {
+                if lhs.is_nan() {
+                    if rhs.is_nan() {
+                        Ordering::Equal
+                    } else {
+                        Ordering::Greater
+                    }
+                } else {
+                    Ordering::Less
+                }
+            }
+        }
+    }
+}
+
+impl<T: Float + PartialEq> PartialEq for OrderedFloat<T> {
+    fn eq(&self, other: &OrderedFloat<T>) -> bool {
+        if self.as_ref().is_nan() {
+            other.as_ref().is_nan()
+        } else if other.as_ref().is_nan() {
+            false
+        } else {
+            self.as_ref() == other.as_ref()
+        }
+    }
+}
+
+impl<T: Float> Hash for OrderedFloat<T> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        if self.is_nan() {
+            // normalize to one representation of NaN
+            hash_float(&T::nan(), state)
+        } else {
+            hash_float(self.as_ref(), state)
+        }
+    }
+}
+
+impl<T: Float + fmt::Display> fmt::Display for OrderedFloat<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.as_ref().fmt(f)
+    }
+}
+
+impl Into<f32> for OrderedFloat<f32> {
+    fn into(self) -> f32 {
+        self.into_inner()
+    }
+}
+
+impl Into<f64> for OrderedFloat<f64> {
+    fn into(self) -> f64 {
+        self.into_inner()
+    }
+}
+
+impl<T: Float> From<T> for OrderedFloat<T> {
+    fn from(val: T) -> Self {
+        OrderedFloat(val)
+    }
+}
+
+impl<T: Float> Deref for OrderedFloat<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        self.as_ref()
+    }
+}
+
+impl<T: Float> DerefMut for OrderedFloat<T> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        self.as_mut()
+    }
+}
+
+impl<T: Float + PartialEq> Eq for OrderedFloat<T> {}
+
+/// A wrapper around Floats providing an implementation of Ord and Hash.
+///
+/// A NaN value cannot be stored in this type.
+#[derive(PartialOrd, PartialEq, Debug, Default, Clone, Copy)]
+pub struct NotNan<T: Float>(T);
+
+impl<T: Float> NotNan<T> {
+    /// Create a NotNan value.
+    ///
+    /// Returns Err if val is NaN
+    pub fn new(val: T) -> Result<Self, FloatIsNan> {
+        match val {
+            ref val if val.is_nan() => Err(FloatIsNan),
+            val => Ok(NotNan(val)),
+        }
+    }
+
+    /// Create a NotNan value from a value that is guaranteed to not be NaN
+    ///
+    /// Behaviour is undefined if `val` is NaN
+    pub unsafe fn unchecked_new(val: T) -> Self {
+        debug_assert!(!val.is_nan());
+        NotNan(val)
+    }
+
+    /// Get the value out.
+    pub fn into_inner(self) -> T {
+        let NotNan(val) = self;
+        val
+    }
+}
+
+impl<T: Float> AsRef<T> for NotNan<T> {
+    fn as_ref(&self) -> &T {
+        let NotNan(ref val) = *self;
+        val
+    }
+}
+
+impl<T: Float> Ord for NotNan<T> {
+    fn cmp(&self, other: &NotNan<T>) -> Ordering {
+        match self.partial_cmp(&other) {
+            Some(ord) => ord,
+            None => unsafe { unreachable() },
+        }
+    }
+}
+
+impl<T: Float> Hash for NotNan<T> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        hash_float(self.as_ref(), state)
+    }
+}
+
+impl<T: Float + fmt::Display> fmt::Display for NotNan<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.as_ref().fmt(f)
+    }
+}
+
+impl Into<f32> for NotNan<f32> {
+    fn into(self) -> f32 {
+        self.into_inner()
+    }
+}
+
+impl Into<f64> for NotNan<f64> {
+    fn into(self) -> f64 {
+        self.into_inner()
+    }
+}
+
+/// Creates a NotNan value from a Float.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl<T: Float> From<T> for NotNan<T> {
+    fn from(v: T) -> Self {
+        assert!(!v.is_nan());
+        NotNan(v)
+    }
+}
+
+impl<T: Float> Deref for NotNan<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        self.as_ref()
+    }
+}
+
+impl<T: Float + PartialEq> Eq for NotNan<T> {}
+
+impl<T: Float> Add for NotNan<T> {
+    type Output = Self;
+
+    fn add(self, other: Self) -> Self {
+        NotNan(self.0 + other.0)
+    }
+}
+
+/// Adds a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl<T: Float> Add<T> for NotNan<T> {
+    type Output = Self;
+
+    fn add(self, other: T) -> Self {
+        assert!(!other.is_nan());
+        NotNan::new(self.0 + other).expect("Addition resulted in NaN")
+    }
+}
+
+impl AddAssign for NotNan<f64> {
+    fn add_assign(&mut self, other: Self) {
+        self.0 += other.0;
+        assert!(!self.0.is_nan(), "Addition resulted in NaN")
+    }
+}
+
+impl AddAssign for NotNan<f32> {
+    fn add_assign(&mut self, other: Self) {
+        self.0 += other.0;
+        assert!(!self.0.is_nan(), "Addition resulted in NaN")
+    }
+}
+
+/// Adds a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl AddAssign<f64> for NotNan<f64> {
+    fn add_assign(&mut self, other: f64) {
+        assert!(!other.is_nan());
+        self.0 += other;
+        assert!(!self.0.is_nan(), "Addition resulted in NaN")
+    }
+}
+
+/// Adds a float directly.
+///
+/// Panics if the provided value is NaN.
+impl AddAssign<f32> for NotNan<f32> {
+    fn add_assign(&mut self, other: f32) {
+        assert!(!other.is_nan());
+        self.0 += other;
+        assert!(!self.0.is_nan(), "Addition resulted in NaN")
+    }
+}
+
+impl<T: Float> Sub for NotNan<T> {
+    type Output = Self;
+
+    fn sub(self, other: Self) -> Self {
+        NotNan::new(self.0 - other.0).expect("Subtraction resulted in NaN")
+    }
+}
+
+/// Subtracts a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl<T: Float> Sub<T> for NotNan<T> {
+    type Output = Self;
+
+    fn sub(self, other: T) -> Self {
+        assert!(!other.is_nan());
+        NotNan::new(self.0 - other).expect("Subtraction resulted in NaN")
+    }
+}
+
+impl SubAssign for NotNan<f64> {
+    fn sub_assign(&mut self, other: Self) {
+        self.0 -= other.0;
+        assert!(!self.0.is_nan(), "Subtraction resulted in NaN")
+    }
+}
+
+impl SubAssign for NotNan<f32> {
+    fn sub_assign(&mut self, other: Self) {
+        self.0 -= other.0;
+        assert!(!self.0.is_nan(), "Subtraction resulted in NaN")
+    }
+}
+
+/// Subtracts a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl SubAssign<f64> for NotNan<f64> {
+    fn sub_assign(&mut self, other: f64) {
+        assert!(!other.is_nan());
+        self.0 -= other;
+        assert!(!self.0.is_nan(), "Subtraction resulted in NaN")
+    }
+}
+
+/// Subtracts a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl SubAssign<f32> for NotNan<f32> {
+    fn sub_assign(&mut self, other: f32) {
+        assert!(!other.is_nan());
+        self.0 -= other;
+        assert!(!self.0.is_nan(), "Subtraction resulted in NaN")
+    }
+}
+
+impl<T: Float> Mul for NotNan<T> {
+    type Output = Self;
+
+    fn mul(self, other: Self) -> Self {
+        NotNan::new(self.0 * other.0).expect("Multiplication resulted in NaN")
+    }
+}
+
+/// Multiplies a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl<T: Float> Mul<T> for NotNan<T> {
+    type Output = Self;
+
+    fn mul(self, other: T) -> Self {
+        assert!(!other.is_nan());
+        NotNan::new(self.0 * other).expect("Multiplication resulted in NaN")
+    }
+}
+
+impl MulAssign for NotNan<f64> {
+    fn mul_assign(&mut self, other: Self) {
+        self.0 *= other.0;
+        assert!(!self.0.is_nan(), "Multiplication resulted in NaN")
+    }
+}
+
+impl MulAssign for NotNan<f32> {
+    fn mul_assign(&mut self, other: Self) {
+        self.0 *= other.0;
+        assert!(!self.0.is_nan(), "Multiplication resulted in NaN")
+    }
+}
+
+/// Multiplies a float directly.
+///
+/// Panics if the provided value is NaN.
+impl MulAssign<f64> for NotNan<f64> {
+    fn mul_assign(&mut self, other: f64) {
+        assert!(!other.is_nan());
+        self.0 *= other;
+    }
+}
+
+/// Multiplies a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl MulAssign<f32> for NotNan<f32> {
+    fn mul_assign(&mut self, other: f32) {
+        assert!(!other.is_nan());
+        self.0 *= other;
+        assert!(!self.0.is_nan(), "Multiplication resulted in NaN")
+    }
+}
+
+impl<T: Float> Div for NotNan<T> {
+    type Output = Self;
+
+    fn div(self, other: Self) -> Self {
+        NotNan::new(self.0 / other.0).expect("Division resulted in NaN")
+    }
+}
+
+/// Divides a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl<T: Float> Div<T> for NotNan<T> {
+    type Output = Self;
+
+    fn div(self, other: T) -> Self {
+        assert!(!other.is_nan());
+        NotNan::new(self.0 / other).expect("Division resulted in NaN")
+    }
+}
+
+impl DivAssign for NotNan<f64> {
+    fn div_assign(&mut self, other: Self) {
+        self.0 /= other.0;
+        assert!(!self.0.is_nan(), "Division resulted in NaN")
+    }
+}
+
+impl DivAssign for NotNan<f32> {
+    fn div_assign(&mut self, other: Self) {
+        self.0 /= other.0;
+        assert!(!self.0.is_nan(), "Division resulted in NaN")
+    }
+}
+
+/// Divides a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl DivAssign<f64> for NotNan<f64> {
+    fn div_assign(&mut self, other: f64) {
+        assert!(!other.is_nan());
+        self.0 /= other;
+        assert!(!self.0.is_nan(), "Division resulted in NaN")
+    }
+}
+
+/// Divides a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl DivAssign<f32> for NotNan<f32> {
+    fn div_assign(&mut self, other: f32) {
+        assert!(!other.is_nan());
+        self.0 /= other;
+        assert!(!self.0.is_nan(), "Division resulted in NaN")
+    }
+}
+
+impl<T: Float> Rem for NotNan<T> {
+    type Output = Self;
+
+    fn rem(self, other: Self) -> Self {
+        NotNan::new(self.0 % other.0).expect("Rem resulted in NaN")
+    }
+}
+
+/// Calculates `%` with a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl<T: Float> Rem<T> for NotNan<T> {
+    type Output = Self;
+
+    fn rem(self, other: T) -> Self {
+        assert!(!other.is_nan());
+        NotNan::new(self.0 % other).expect("Rem resulted in NaN")
+    }
+}
+
+impl RemAssign for NotNan<f64> {
+    fn rem_assign(&mut self, other: Self) {
+        self.0 %= other.0;
+        assert!(!self.0.is_nan(), "Rem resulted in NaN")
+    }
+}
+
+impl RemAssign for NotNan<f32> {
+    fn rem_assign(&mut self, other: Self) {
+        self.0 %= other.0;
+        assert!(!self.0.is_nan(), "Rem resulted in NaN")
+    }
+}
+
+/// Calculates `%=` with a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl RemAssign<f64> for NotNan<f64> {
+    fn rem_assign(&mut self, other: f64) {
+        assert!(!other.is_nan());
+        self.0 %= other;
+        assert!(!self.0.is_nan(), "Rem resulted in NaN")
+    }
+}
+
+/// Calculates `%=` with a float directly.
+///
+/// Panics if the provided value is NaN or the computation results in NaN
+impl RemAssign<f32> for NotNan<f32> {
+    fn rem_assign(&mut self, other: f32) {
+        assert!(!other.is_nan());
+        self.0 %= other;
+        assert!(!self.0.is_nan(), "Rem resulted in NaN")
+    }
+}
+
+impl<T: Float> Neg for NotNan<T> {
+    type Output = Self;
+
+    fn neg(self) -> Self {
+        NotNan::new(-self.0).expect("Negation resulted in NaN")
+    }
+}
+
+/// An error indicating an attempt to construct NotNan from a NaN
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub struct FloatIsNan;
+
+impl Error for FloatIsNan {
+    fn description(&self) -> &str {
+        "NotNan constructed with NaN"
+    }
+}
+
+impl fmt::Display for FloatIsNan {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        <Self as fmt::Debug>::fmt(self, f)
+    }
+}
+
+impl Into<io::Error> for FloatIsNan {
+    fn into(self) -> io::Error {
+        io::Error::new(io::ErrorKind::InvalidInput, self)
+    }
+}
+
+#[inline]
+fn hash_float<F: Float, H: Hasher>(f: &F, state: &mut H) {
+    raw_double_bits(f).hash(state);
+}
+
+#[inline]
+fn raw_double_bits<F: Float>(f: &F) -> u64 {
+    if f.is_nan() {
+        return CANONICAL_NAN_BITS;
+    }
+
+    let (man, exp, sign) = f.integer_decode();
+    if man == 0 {
+        return CANONICAL_ZERO_BITS;
+    }
+
+    let exp_u64 = unsafe { mem::transmute::<i16, u16>(exp) } as u64;
+    let sign_u64 = if sign > 0 { 1u64 } else { 0u64 };
+    (man & MAN_MASK) | ((exp_u64 << 52) & EXP_MASK) | ((sign_u64 << 63) & SIGN_MASK)
+}
+
+impl<T: Float + Zero> Zero for NotNan<T> {
+    fn zero() -> Self { NotNan(T::zero()) }
+
+    fn is_zero(&self) -> bool { self.0.is_zero() }
+}
+
+impl<T: Float + One> One for NotNan<T> {
+    fn one() -> Self { NotNan(T::one()) }
+}
+
+impl<T: Float + Bounded> Bounded for NotNan<T> {
+    fn min_value() -> Self {
+        NotNan(Bounded::min_value())
+    }
+
+    fn max_value() -> Self {
+        NotNan(Bounded::max_value())
+    }
+}
+
+impl<T: Float + FromPrimitive> FromPrimitive for NotNan<T> {
+    fn from_i64(n: i64) -> Option<Self> { T::from_i64(n).and_then(|n| NotNan::new(n).ok()) }
+    fn from_u64(n: u64) -> Option<Self> { T::from_u64(n).and_then(|n| NotNan::new(n).ok()) }
+
+    fn from_isize(n: isize) -> Option<Self> { T::from_isize(n).and_then(|n| NotNan::new(n).ok()) }
+    fn from_i8(n: i8) -> Option<Self> { T::from_i8(n).and_then(|n| NotNan::new(n).ok()) }
+    fn from_i16(n: i16) -> Option<Self> { T::from_i16(n).and_then(|n| NotNan::new(n).ok()) }
+    fn from_i32(n: i32) -> Option<Self> { T::from_i32(n).and_then(|n| NotNan::new(n).ok()) }
+    fn from_usize(n: usize) -> Option<Self> { T::from_usize(n).and_then(|n| NotNan::new(n).ok()) }
+    fn from_u8(n: u8) -> Option<Self> { T::from_u8(n).and_then(|n| NotNan::new(n).ok()) }
+    fn from_u16(n: u16) -> Option<Self> { T::from_u16(n).and_then(|n| NotNan::new(n).ok()) }
+    fn from_u32(n: u32) -> Option<Self> { T::from_u32(n).and_then(|n| NotNan::new(n).ok()) }
+    fn from_f32(n: f32) -> Option<Self> { T::from_f32(n).and_then(|n| NotNan::new(n).ok()) }
+    fn from_f64(n: f64) -> Option<Self> { T::from_f64(n).and_then(|n| NotNan::new(n).ok()) }
+}
+
+impl<T: Float + ToPrimitive> ToPrimitive for NotNan<T> {
+    fn to_i64(&self) -> Option<i64> { self.0.to_i64() }
+    fn to_u64(&self) -> Option<u64> { self.0.to_u64() }
+
+    fn to_isize(&self) -> Option<isize> { self.0.to_isize() }
+    fn to_i8(&self) -> Option<i8> { self.0.to_i8() }
+    fn to_i16(&self) -> Option<i16> { self.0.to_i16() }
+    fn to_i32(&self) -> Option<i32> { self.0.to_i32() }
+    fn to_usize(&self) -> Option<usize> { self.0.to_usize() }
+    fn to_u8(&self) -> Option<u8> { self.0.to_u8() }
+    fn to_u16(&self) -> Option<u16> { self.0.to_u16() }
+    fn to_u32(&self) -> Option<u32> { self.0.to_u32() }
+    fn to_f32(&self) -> Option<f32> { self.0.to_f32() }
+    fn to_f64(&self) -> Option<f64> { self.0.to_f64() }
+}
+
+/// An error indicating a parse error from a string for `NotNan`.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum ParseNotNanError<E> {
+    /// A plain parse error from the underlying float type.
+    ParseFloatError(E),
+    /// The parsed float value resulted in a NaN.
+    IsNaN,
+}
+
+impl<E: fmt::Debug> Error for ParseNotNanError<E> {
+    fn description(&self) -> &str {
+        return "Error parsing a not-NaN floating point value";
+    }
+}
+
+impl<E: fmt::Debug> fmt::Display for ParseNotNanError<E> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        <Self as fmt::Debug>::fmt(self, f)
+    }
+}
+
+impl<T: Float + Num> Num for NotNan<T> {
+    type FromStrRadixErr = ParseNotNanError<T::FromStrRadixErr>;
+
+    fn from_str_radix(src: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
+        T::from_str_radix(src, radix)
+            .map_err(|err| ParseNotNanError::ParseFloatError(err))
+            .and_then(|n| NotNan::new(n).map_err(|_| ParseNotNanError::IsNaN))
+    }
+}
+
+impl<T: Float + Signed> Signed for NotNan<T> {
+    fn abs(&self) -> Self { NotNan(self.0.abs()) }
+
+    fn abs_sub(&self, other: &Self) -> Self {
+        NotNan::new(self.0.abs_sub(other.0)).expect("Subtraction resulted in NaN")
+    }
+
+    fn signum(&self) -> Self { NotNan(self.0.signum()) }
+    fn is_positive(&self) -> bool { self.0.is_positive() }
+    fn is_negative(&self) -> bool { self.0.is_negative() }
+}
+
+impl<T: Float + NumCast> NumCast for NotNan<T> {
+    fn from<F: ToPrimitive>(n: F) -> Option<Self> {
+        T::from(n).and_then(|n| NotNan::new(n).ok())
+    }
+}
+
+#[cfg(feature = "serde")]
+mod impl_serde {
+    extern crate serde;
+    use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
+    use self::serde::de::{Error, Unexpected};
+    use super::{OrderedFloat, NotNan};
+    use num_traits::Float;
+    use std::f64;
+
+    #[cfg(test)]
+    extern crate serde_test;
+    #[cfg(test)]
+    use self::serde_test::{Token, assert_tokens, assert_de_tokens_error};
+
+    impl<T: Float + Serialize> Serialize for OrderedFloat<T> {
+        fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
+            self.0.serialize(s)
+        }
+    }
+
+    impl<'de, T: Float + Deserialize<'de>> Deserialize<'de> for OrderedFloat<T> {
+        fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
+            T::deserialize(d).map(OrderedFloat)
+        }
+    }
+
+    impl<T: Float + Serialize> Serialize for NotNan<T> {
+        fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
+            self.0.serialize(s)
+        }
+    }
+
+    impl<'de, T: Float + Deserialize<'de>> Deserialize<'de> for NotNan<T> {
+        fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
+            let float = T::deserialize(d)?;
+            NotNan::new(float).map_err(|_| {
+                Error::invalid_value(Unexpected::Float(f64::NAN), &"float (but not NaN)")
+            })
+        }
+    }
+
+    #[test]
+    fn test_ordered_float() {
+        let float = OrderedFloat(1.0f64);
+        assert_tokens(&float, &[Token::F64(1.0)]);
+    }
+
+    #[test]
+    fn test_not_nan() {
+        let float = NotNan(1.0f64);
+        assert_tokens(&float, &[Token::F64(1.0)]);
+    }
+
+    #[test]
+    fn test_fail_on_nan() {
+        assert_de_tokens_error::<NotNan<f64>>(
+            &[Token::F64(f64::NAN)],
+            "invalid value: floating point `NaN`, expected float (but not NaN)");
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new-ordered-float/tests/test.rs
@@ -0,0 +1,524 @@
+extern crate num_traits;
+extern crate ordered_float;
+
+pub use ordered_float::*;
+pub use num_traits::{Bounded, Float, FromPrimitive, Num, One, Signed, ToPrimitive, Zero};
+pub use std::cmp::Ordering::*;
+pub use std::{f32, f64, panic};
+
+pub use std::collections::hash_map::RandomState;
+pub use std::collections::HashSet;
+pub use std::hash::*;
+
+#[test]
+fn ordered_f32_compare_regular_floats() {
+    assert_eq!(OrderedFloat(7.0f32).cmp(&OrderedFloat(7.0)), Equal);
+    assert_eq!(OrderedFloat(8.0f32).cmp(&OrderedFloat(7.0)), Greater);
+    assert_eq!(OrderedFloat(4.0f32).cmp(&OrderedFloat(7.0)), Less);
+}
+
+#[test]
+fn ordered_f32_compare_regular_floats_op() {
+    assert!(OrderedFloat(7.0f32) == OrderedFloat(7.0));
+    assert!(OrderedFloat(7.0f32) <= OrderedFloat(7.0));
+    assert!(OrderedFloat(7.0f32) >= OrderedFloat(7.0));
+    assert!(OrderedFloat(8.0f32) > OrderedFloat(7.0));
+    assert!(OrderedFloat(8.0f32) >= OrderedFloat(7.0));
+    assert!(OrderedFloat(4.0f32) < OrderedFloat(7.0));
+    assert!(OrderedFloat(4.0f32) <= OrderedFloat(7.0));
+}
+
+#[test]
+fn ordered_f32_compare_nan() {
+    let f32_nan: f32 = Float::nan();
+    assert_eq!(OrderedFloat(f32_nan).cmp(&OrderedFloat(Float::nan())), Equal);
+    assert_eq!(OrderedFloat(f32_nan).cmp(&OrderedFloat(-100000.0f32)), Greater);
+    assert_eq!(OrderedFloat(-100.0f32).cmp(&OrderedFloat(Float::nan())), Less);
+}
+
+#[test]
+fn ordered_f32_compare_nan_op() {
+    let f32_nan: OrderedFloat<f32> = OrderedFloat(Float::nan());
+    assert!(f32_nan == f32_nan);
+    assert!(f32_nan <= f32_nan);
+    assert!(f32_nan >= f32_nan);
+    assert!(f32_nan > OrderedFloat(-100000.0f32));
+    assert!(f32_nan >= OrderedFloat(-100000.0f32));
+    assert!(OrderedFloat(-100.0f32) < f32_nan);
+    assert!(OrderedFloat(-100.0f32) <= f32_nan);
+    assert!(f32_nan > OrderedFloat(Float::infinity()));
+    assert!(f32_nan >= OrderedFloat(Float::infinity()));
+    assert!(f32_nan > OrderedFloat(Float::neg_infinity()));
+    assert!(f32_nan >= OrderedFloat(Float::neg_infinity()));
+}
+
+#[test]
+fn ordered_f64_compare_regular_floats() {
+    assert_eq!(OrderedFloat(7.0f64).cmp(&OrderedFloat(7.0)), Equal);
+    assert_eq!(OrderedFloat(8.0f64).cmp(&OrderedFloat(7.0)), Greater);
+    assert_eq!(OrderedFloat(4.0f64).cmp(&OrderedFloat(7.0)), Less);
+}
+
+#[test]
+fn not_nan32_zero() {
+    assert_eq!(NotNan::<f32>::zero(), NotNan::from(0.0f32));
+    assert!(NotNan::<f32>::zero().is_zero());
+}
+
+#[test]
+fn not_nan32_one() {
+    assert_eq!(NotNan::<f32>::one(), NotNan::from(1.0f32))
+}
+
+#[test]
+fn not_nan32_bounded() {
+    assert_eq!(NotNan::<f32>::min_value(), NotNan::from(<f32 as Bounded>::min_value()));
+    assert_eq!(NotNan::<f32>::max_value(), NotNan::from(<f32 as Bounded>::max_value()));
+}
+
+#[test]
+fn not_nan32_from_primitive() {
+    assert_eq!(NotNan::<f32>::from_i8(42i8), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_u8(42u8), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_i16(42i16), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_u16(42u16), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_i32(42i32), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_u32(42u32), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_i64(42i64), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_u64(42u64), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_isize(42isize), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_usize(42usize), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_f32(42f32), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_f32(42f32), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_f64(42f64), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_f64(42f64), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f32>::from_f32(Float::nan()), None);
+    assert_eq!(NotNan::<f32>::from_f64(Float::nan()), None);
+}
+
+#[test]
+fn not_nan32_to_primitive() {
+    let x = NotNan::from(42.0f32);
+    assert_eq!(x.to_u8(), Some(42u8));
+    assert_eq!(x.to_i8(), Some(42i8));
+    assert_eq!(x.to_u16(), Some(42u16));
+    assert_eq!(x.to_i16(), Some(42i16));
+    assert_eq!(x.to_u32(), Some(42u32));
+    assert_eq!(x.to_i32(), Some(42i32));
+    assert_eq!(x.to_u64(), Some(42u64));
+    assert_eq!(x.to_i64(), Some(42i64));
+    assert_eq!(x.to_usize(), Some(42usize));
+    assert_eq!(x.to_isize(), Some(42isize));
+    assert_eq!(x.to_f32(), Some(42f32));
+    assert_eq!(x.to_f32(), Some(42f32));
+    assert_eq!(x.to_f64(), Some(42f64));
+    assert_eq!(x.to_f64(), Some(42f64));
+}
+
+#[test]
+fn not_nan32_num() {
+    assert_eq!(NotNan::<f32>::from_str_radix("42.0", 10).unwrap(), NotNan::from(42.0f32));
+    assert!(NotNan::<f32>::from_str_radix("NaN", 10).is_err());
+}
+
+#[test]
+fn not_nan32_signed() {
+    assert_eq!(NotNan::from(42f32).abs(), NotNan::from(42f32));
+    assert_eq!(NotNan::from(-42f32).abs(), NotNan::from(42f32));
+
+    assert_eq!(NotNan::from(50f32).abs_sub(&NotNan::from(8f32)), NotNan::from(42f32));
+    assert_eq!(NotNan::from(8f32).abs_sub(&NotNan::from(50f32)), NotNan::from(0f32));
+}
+
+#[test]
+fn not_nan32_num_cast() {
+    assert_eq!(<NotNan<f32> as num_traits::NumCast>::from(42), Some(NotNan::from(42f32)));
+    assert_eq!(<NotNan<f32> as num_traits::NumCast>::from(f32::nan()), None);
+}
+
+#[test]
+fn ordered_f64_compare_nan() {
+    let f64_nan: f64 = Float::nan();
+    assert_eq!(
+        OrderedFloat(f64_nan).cmp(&OrderedFloat(Float::nan())),
+        Equal
+    );
+    assert_eq!(
+        OrderedFloat(f64_nan).cmp(&OrderedFloat(-100000.0f64)),
+        Greater
+    );
+    assert_eq!(
+        OrderedFloat(-100.0f64).cmp(&OrderedFloat(Float::nan())),
+        Less
+    );
+}
+
+#[test]
+fn ordered_f64_compare_regular_floats_op() {
+    assert!(OrderedFloat(7.0) == OrderedFloat(7.0));
+    assert!(OrderedFloat(7.0) <= OrderedFloat(7.0));
+    assert!(OrderedFloat(7.0) >= OrderedFloat(7.0));
+    assert!(OrderedFloat(8.0) > OrderedFloat(7.0));
+    assert!(OrderedFloat(8.0) >= OrderedFloat(7.0));
+    assert!(OrderedFloat(4.0) < OrderedFloat(7.0));
+    assert!(OrderedFloat(4.0) <= OrderedFloat(7.0));
+}
+
+#[test]
+fn ordered_f64_compare_nan_op() {
+    let f64_nan: OrderedFloat<f64> = OrderedFloat(Float::nan());
+    assert!(f64_nan == f64_nan);
+    assert!(f64_nan <= f64_nan);
+    assert!(f64_nan >= f64_nan);
+    assert!(f64_nan > OrderedFloat(-100000.0));
+    assert!(f64_nan >= OrderedFloat(-100000.0));
+    assert!(OrderedFloat(-100.0) < f64_nan);
+    assert!(OrderedFloat(-100.0) <= f64_nan);
+    assert!(f64_nan > OrderedFloat(Float::infinity()));
+    assert!(f64_nan >= OrderedFloat(Float::infinity()));
+    assert!(f64_nan > OrderedFloat(Float::neg_infinity()));
+    assert!(f64_nan >= OrderedFloat(Float::neg_infinity()));
+}
+
+#[test]
+fn not_nan32_compare_regular_floats() {
+    assert_eq!(NotNan::from(7.0f32).cmp(&NotNan::from(7.0)), Equal);
+    assert_eq!(NotNan::from(8.0f32).cmp(&NotNan::from(7.0)), Greater);
+    assert_eq!(NotNan::from(4.0f32).cmp(&NotNan::from(7.0)), Less);
+}
+
+#[test]
+fn not_nan32_fail_when_constructing_with_nan() {
+    let f32_nan: f32 = Float::nan();
+    assert!(NotNan::new(f32_nan).is_err());
+}
+
+#[test]
+fn not_nan32_calculate_correctly() {
+    assert_eq!(
+        *(NotNan::from(5.0f32) + NotNan::from(4.0f32)),
+        5.0f32 + 4.0f32
+    );
+    assert_eq!(*(NotNan::from(5.0f32) + 4.0f32), 5.0f32 + 4.0f32);
+    assert_eq!(
+        *(NotNan::from(5.0f32) - NotNan::from(4.0f32)),
+        5.0f32 - 4.0f32
+    );
+    assert_eq!(*(NotNan::from(5.0f32) - 4.0f32), 5.0f32 - 4.0f32);
+    assert_eq!(
+        *(NotNan::from(5.0f32) * NotNan::from(4.0f32)),
+        5.0f32 * 4.0f32
+    );
+    assert_eq!(*(NotNan::from(5.0f32) * 4.0f32), 5.0f32 * 4.0f32);
+    assert_eq!(
+        *(NotNan::from(8.0f32) / NotNan::from(4.0f32)),
+        8.0f32 / 4.0f32
+    );
+    assert_eq!(*(NotNan::from(8.0f32) / 4.0f32), 8.0f32 / 4.0f32);
+    assert_eq!(
+        *(NotNan::from(8.0f32) % NotNan::from(4.0f32)),
+        8.0f32 % 4.0f32
+    );
+    assert_eq!(*(NotNan::from(8.0f32) % 4.0f32), 8.0f32 % 4.0f32);
+    assert_eq!(*(-NotNan::from(1.0f32)), -1.0f32);
+
+    assert!(panic::catch_unwind(|| NotNan::from(0.0f32) + f32::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNan::from(0.0f32) - f32::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNan::from(0.0f32) * f32::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNan::from(0.0f32) / f32::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNan::from(0.0f32) % f32::NAN).is_err());
+
+    let mut number = NotNan::from(5.0f32);
+    number += NotNan::from(4.0f32);
+    assert_eq!(*number, 9.0f32);
+    number -= NotNan::from(4.0f32);
+    assert_eq!(*number, 5.0f32);
+    number *= NotNan::from(4.0f32);
+    assert_eq!(*number, 20.0f32);
+    number /= NotNan::from(4.0f32);
+    assert_eq!(*number, 5.0f32);
+    number %= NotNan::from(4.0f32);
+    assert_eq!(*number, 1.0f32);
+
+    number = NotNan::from(5.0f32);
+    number += 4.0f32;
+    assert_eq!(*number, 9.0f32);
+    number -= 4.0f32;
+    assert_eq!(*number, 5.0f32);
+    number *= 4.0f32;
+    assert_eq!(*number, 20.0f32);
+    number /= 4.0f32;
+    assert_eq!(*number, 5.0f32);
+    number %= 4.0f32;
+    assert_eq!(*number, 1.0f32);
+
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNan::from(0.0f32);
+            tmp += f32::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNan::from(0.0f32);
+            tmp -= f32::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNan::from(0.0f32);
+            tmp *= f32::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNan::from(0.0f32);
+            tmp /= f32::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNan::from(0.0f32);
+            tmp %= f32::NAN;
+        }).is_err()
+    );
+}
+
+#[test]
+fn not_nan64_compare_regular_floats() {
+    assert_eq!(NotNan::from(7.0f64).cmp(&NotNan::from(7.0)), Equal);
+    assert_eq!(NotNan::from(8.0f64).cmp(&NotNan::from(7.0)), Greater);
+    assert_eq!(NotNan::from(4.0f64).cmp(&NotNan::from(7.0)), Less);
+}
+
+#[test]
+fn not_nan64_fail_when_constructing_with_nan() {
+    let f64_nan: f64 = Float::nan();
+    assert!(NotNan::new(f64_nan).is_err());
+}
+
+#[test]
+fn not_nan64_calculate_correctly() {
+    assert_eq!(
+        *(NotNan::from(5.0f64) + NotNan::from(4.0f64)),
+        5.0f64 + 4.0f64
+    );
+    assert_eq!(*(NotNan::from(5.0f64) + 4.0f64), 5.0f64 + 4.0f64);
+    assert_eq!(
+        *(NotNan::from(5.0f64) - NotNan::from(4.0f64)),
+        5.0f64 - 4.0f64
+    );
+    assert_eq!(*(NotNan::from(5.0f64) - 4.0f64), 5.0f64 - 4.0f64);
+    assert_eq!(
+        *(NotNan::from(5.0f64) * NotNan::from(4.0f64)),
+        5.0f64 * 4.0f64
+    );
+    assert_eq!(*(NotNan::from(5.0f64) * 4.0f64), 5.0f64 * 4.0f64);
+    assert_eq!(
+        *(NotNan::from(8.0f64) / NotNan::from(4.0f64)),
+        8.0f64 / 4.0f64
+    );
+    assert_eq!(*(NotNan::from(8.0f64) / 4.0f64), 8.0f64 / 4.0f64);
+    assert_eq!(
+        *(NotNan::from(8.0f64) % NotNan::from(4.0f64)),
+        8.0f64 % 4.0f64
+    );
+    assert_eq!(*(NotNan::from(8.0f64) % 4.0f64), 8.0f64 % 4.0f64);
+    assert_eq!(*(-NotNan::from(1.0f64)), -1.0f64);
+
+    assert!(panic::catch_unwind(|| NotNan::from(0.0f64) + f64::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNan::from(0.0f64) - f64::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNan::from(0.0f64) * f64::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNan::from(0.0f64) / f64::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNan::from(0.0f64) % f64::NAN).is_err());
+
+    let mut number = NotNan::from(5.0f64);
+    number += NotNan::from(4.0f64);
+    assert_eq!(*number, 9.0f64);
+    number -= NotNan::from(4.0f64);
+    assert_eq!(*number, 5.0f64);
+    number *= NotNan::from(4.0f64);
+    assert_eq!(*number, 20.0f64);
+    number /= NotNan::from(4.0f64);
+    assert_eq!(*number, 5.0f64);
+    number %= NotNan::from(4.0f64);
+    assert_eq!(*number, 1.0f64);
+
+    number = NotNan::from(5.0f64);
+    number += 4.0f64;
+    assert_eq!(*number, 9.0f64);
+    number -= 4.0f64;
+    assert_eq!(*number, 5.0f64);
+    number *= 4.0f64;
+    assert_eq!(*number, 20.0f64);
+    number /= 4.0f64;
+    assert_eq!(*number, 5.0f64);
+    number %= 4.0f64;
+    assert_eq!(*number, 1.0f64);
+
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNan::from(0.0f64);
+            tmp += f64::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNan::from(0.0f64);
+            tmp -= f64::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNan::from(0.0f64);
+            tmp *= f64::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNan::from(0.0f64);
+            tmp /= f64::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNan::from(0.0f64);
+            tmp %= f64::NAN;
+        }).is_err()
+    );
+}
+
+#[test]
+fn not_nan64_zero() {
+    assert_eq!(NotNan::<f64>::zero(), NotNan::from(0.0f64));
+    assert!(NotNan::<f64>::zero().is_zero());
+}
+
+#[test]
+fn not_nan64_one() {
+    assert_eq!(NotNan::<f64>::one(), NotNan::from(1.0f64))
+}
+
+#[test]
+fn not_nan64_bounded() {
+    assert_eq!(NotNan::<f64>::min_value(), NotNan::from(<f64 as Bounded>::min_value()));
+    assert_eq!(NotNan::<f64>::max_value(), NotNan::from(<f64 as Bounded>::max_value()));
+}
+
+#[test]
+fn not_nan64_from_primitive() {
+    assert_eq!(NotNan::<f64>::from_i8(42i8), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_u8(42u8), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_i16(42i16), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_u16(42u16), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_i32(42i32), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_u32(42u32), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_i64(42i64), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_u64(42u64), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_isize(42isize), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_usize(42usize), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_f64(42f64), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_f64(42f64), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_f64(42f64), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_f64(42f64), Some(NotNan::from(42.0)));
+    assert_eq!(NotNan::<f64>::from_f64(Float::nan()), None);
+    assert_eq!(NotNan::<f64>::from_f64(Float::nan()), None);
+}
+
+#[test]
+fn not_nan64_to_primitive() {
+    let x = NotNan::from(42.0f64);
+    assert_eq!(x.to_u8(), Some(42u8));
+    assert_eq!(x.to_i8(), Some(42i8));
+    assert_eq!(x.to_u16(), Some(42u16));
+    assert_eq!(x.to_i16(), Some(42i16));
+    assert_eq!(x.to_u32(), Some(42u32));
+    assert_eq!(x.to_i32(), Some(42i32));
+    assert_eq!(x.to_u64(), Some(42u64));
+    assert_eq!(x.to_i64(), Some(42i64));
+    assert_eq!(x.to_usize(), Some(42usize));
+    assert_eq!(x.to_isize(), Some(42isize));
+    assert_eq!(x.to_f64(), Some(42f64));
+    assert_eq!(x.to_f64(), Some(42f64));
+    assert_eq!(x.to_f64(), Some(42f64));
+    assert_eq!(x.to_f64(), Some(42f64));
+}
+
+#[test]
+fn not_nan64_num() {
+    assert_eq!(NotNan::<f64>::from_str_radix("42.0", 10).unwrap(), NotNan::from(42.0f64));
+    assert!(NotNan::<f64>::from_str_radix("NaN", 10).is_err());
+}
+
+#[test]
+fn not_nan64_signed() {
+    assert_eq!(NotNan::from(42f64).abs(), NotNan::from(42f64));
+    assert_eq!(NotNan::from(-42f64).abs(), NotNan::from(42f64));
+
+    assert_eq!(NotNan::from(50f64).abs_sub(&NotNan::from(8f64)), NotNan::from(42f64));
+    assert_eq!(NotNan::from(8f64).abs_sub(&NotNan::from(50f64)), NotNan::from(0f64));
+}
+
+#[test]
+fn not_nan64_num_cast() {
+    assert_eq!(<NotNan<f64> as num_traits::NumCast>::from(42), Some(NotNan::from(42f64)));
+    assert_eq!(<NotNan<f64> as num_traits::NumCast>::from(f64::nan()), None);
+}
+
+#[test]
+fn hash_zero_and_neg_zero_to_the_same_hc() {
+    let state = RandomState::new();
+    let mut h1 = state.build_hasher();
+    let mut h2 = state.build_hasher();
+    OrderedFloat::from(0f64).hash(&mut h1);
+    OrderedFloat::from(-0f64).hash(&mut h2);
+    assert_eq!(h1.finish(), h2.finish());
+}
+
+#[test]
+fn hash_inf_and_neg_inf_to_different_hcs() {
+    let state = RandomState::new();
+    let mut h1 = state.build_hasher();
+    let mut h2 = state.build_hasher();
+    OrderedFloat::from(f64::INFINITY).hash(&mut h1);
+    OrderedFloat::from(f64::NEG_INFINITY).hash(&mut h2);
+    assert!(h1.finish() != h2.finish());
+}
+
+#[test]
+fn hash_is_good_for_whole_numbers() {
+    let state = RandomState::new();
+    let limit = 10000;
+
+    let mut set = ::std::collections::HashSet::with_capacity(limit);
+    for i in 0..limit {
+        let mut h = state.build_hasher();
+        OrderedFloat::from(i as f64).hash(&mut h);
+        set.insert(h.finish());
+    }
+
+    // This allows 100 collisions, which is far too
+    // many, but should guard against transient issues
+    // that will result from using RandomState
+    let pct_unique = set.len() as f64 / limit as f64;
+    assert!(0.99f64 < pct_unique, "percent-unique={}", pct_unique);
+}
+
+#[test]
+fn hash_is_good_for_fractional_numbers() {
+    let state = RandomState::new();
+    let limit = 10000;
+
+    let mut set = ::std::collections::HashSet::with_capacity(limit);
+    for i in 0..limit {
+        let mut h = state.build_hasher();
+        OrderedFloat::from(i as f64 * (1f64 / limit as f64)).hash(&mut h);
+        set.insert(h.finish());
+    }
+
+    // This allows 100 collisions, which is far too
+    // many, but should guard against transient issues
+    // that will result from using RandomState
+    let pct_unique = set.len() as f64 / limit as f64;
+    assert!(0.99f64 < pct_unique, "percent-unique={}", pct_unique);
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new-ordered-float/tests/test_deprecated_names.rs
@@ -0,0 +1,526 @@
+#![allow(deprecated)]
+
+extern crate num_traits;
+extern crate ordered_float;
+
+pub use ordered_float::*;
+pub use num_traits::{Bounded, Float, FromPrimitive, Num, One, Signed, ToPrimitive, Zero};
+pub use std::cmp::Ordering::*;
+pub use std::{f32, f64, panic};
+
+pub use std::collections::hash_map::RandomState;
+pub use std::collections::HashSet;
+pub use std::hash::*;
+
+#[test]
+fn ordered_f32_compare_regular_floats() {
+    assert_eq!(OrderedFloat(7.0f32).cmp(&OrderedFloat(7.0)), Equal);
+    assert_eq!(OrderedFloat(8.0f32).cmp(&OrderedFloat(7.0)), Greater);
+    assert_eq!(OrderedFloat(4.0f32).cmp(&OrderedFloat(7.0)), Less);
+}
+
+#[test]
+fn ordered_f32_compare_regular_floats_op() {
+    assert!(OrderedFloat(7.0f32) == OrderedFloat(7.0));
+    assert!(OrderedFloat(7.0f32) <= OrderedFloat(7.0));
+    assert!(OrderedFloat(7.0f32) >= OrderedFloat(7.0));
+    assert!(OrderedFloat(8.0f32) > OrderedFloat(7.0));
+    assert!(OrderedFloat(8.0f32) >= OrderedFloat(7.0));
+    assert!(OrderedFloat(4.0f32) < OrderedFloat(7.0));
+    assert!(OrderedFloat(4.0f32) <= OrderedFloat(7.0));
+}
+
+#[test]
+fn ordered_f32_compare_nan() {
+    let f32_nan: f32 = Float::nan();
+    assert_eq!(OrderedFloat(f32_nan).cmp(&OrderedFloat(Float::nan())), Equal);
+    assert_eq!(OrderedFloat(f32_nan).cmp(&OrderedFloat(-100000.0f32)), Greater);
+    assert_eq!(OrderedFloat(-100.0f32).cmp(&OrderedFloat(Float::nan())), Less);
+}
+
+#[test]
+fn ordered_f32_compare_nan_op() {
+    let f32_nan: OrderedFloat<f32> = OrderedFloat(Float::nan());
+    assert!(f32_nan == f32_nan);
+    assert!(f32_nan <= f32_nan);
+    assert!(f32_nan >= f32_nan);
+    assert!(f32_nan > OrderedFloat(-100000.0f32));
+    assert!(f32_nan >= OrderedFloat(-100000.0f32));
+    assert!(OrderedFloat(-100.0f32) < f32_nan);
+    assert!(OrderedFloat(-100.0f32) <= f32_nan);
+    assert!(f32_nan > OrderedFloat(Float::infinity()));
+    assert!(f32_nan >= OrderedFloat(Float::infinity()));
+    assert!(f32_nan > OrderedFloat(Float::neg_infinity()));
+    assert!(f32_nan >= OrderedFloat(Float::neg_infinity()));
+}
+
+#[test]
+fn ordered_f64_compare_regular_floats() {
+    assert_eq!(OrderedFloat(7.0f64).cmp(&OrderedFloat(7.0)), Equal);
+    assert_eq!(OrderedFloat(8.0f64).cmp(&OrderedFloat(7.0)), Greater);
+    assert_eq!(OrderedFloat(4.0f64).cmp(&OrderedFloat(7.0)), Less);
+}
+
+#[test]
+fn not_nan32_zero() {
+    assert_eq!(NotNaN::<f32>::zero(), NotNaN::from(0.0f32));
+    assert!(NotNaN::<f32>::zero().is_zero());
+}
+
+#[test]
+fn not_nan32_one() {
+    assert_eq!(NotNaN::<f32>::one(), NotNaN::from(1.0f32))
+}
+
+#[test]
+fn not_nan32_bounded() {
+    assert_eq!(NotNaN::<f32>::min_value(), NotNaN::from(<f32 as Bounded>::min_value()));
+    assert_eq!(NotNaN::<f32>::max_value(), NotNaN::from(<f32 as Bounded>::max_value()));
+}
+
+#[test]
+fn not_nan32_from_primitive() {
+    assert_eq!(NotNaN::<f32>::from_i8(42i8), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_u8(42u8), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_i16(42i16), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_u16(42u16), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_i32(42i32), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_u32(42u32), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_i64(42i64), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_u64(42u64), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_isize(42isize), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_usize(42usize), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_f32(42f32), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_f32(42f32), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_f64(42f64), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_f64(42f64), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f32>::from_f32(Float::nan()), None);
+    assert_eq!(NotNaN::<f32>::from_f64(Float::nan()), None);
+}
+
+#[test]
+fn not_nan32_to_primitive() {
+    let x = NotNaN::from(42.0f32);
+    assert_eq!(x.to_u8(), Some(42u8));
+    assert_eq!(x.to_i8(), Some(42i8));
+    assert_eq!(x.to_u16(), Some(42u16));
+    assert_eq!(x.to_i16(), Some(42i16));
+    assert_eq!(x.to_u32(), Some(42u32));
+    assert_eq!(x.to_i32(), Some(42i32));
+    assert_eq!(x.to_u64(), Some(42u64));
+    assert_eq!(x.to_i64(), Some(42i64));
+    assert_eq!(x.to_usize(), Some(42usize));
+    assert_eq!(x.to_isize(), Some(42isize));
+    assert_eq!(x.to_f32(), Some(42f32));
+    assert_eq!(x.to_f32(), Some(42f32));
+    assert_eq!(x.to_f64(), Some(42f64));
+    assert_eq!(x.to_f64(), Some(42f64));
+}
+
+#[test]
+fn not_nan32_num() {
+    assert_eq!(NotNaN::<f32>::from_str_radix("42.0", 10).unwrap(), NotNaN::from(42.0f32));
+    assert!(NotNaN::<f32>::from_str_radix("NaN", 10).is_err());
+}
+
+#[test]
+fn not_nan32_signed() {
+    assert_eq!(NotNaN::from(42f32).abs(), NotNaN::from(42f32));
+    assert_eq!(NotNaN::from(-42f32).abs(), NotNaN::from(42f32));
+
+    assert_eq!(NotNaN::from(50f32).abs_sub(&NotNaN::from(8f32)), NotNaN::from(42f32));
+    assert_eq!(NotNaN::from(8f32).abs_sub(&NotNaN::from(50f32)), NotNaN::from(0f32));
+}
+
+#[test]
+fn not_nan32_num_cast() {
+    assert_eq!(<NotNaN<f32> as num_traits::NumCast>::from(42), Some(NotNaN::from(42f32)));
+    assert_eq!(<NotNaN<f32> as num_traits::NumCast>::from(f32::nan()), None);
+}
+
+#[test]
+fn ordered_f64_compare_nan() {
+    let f64_nan: f64 = Float::nan();
+    assert_eq!(
+        OrderedFloat(f64_nan).cmp(&OrderedFloat(Float::nan())),
+        Equal
+    );
+    assert_eq!(
+        OrderedFloat(f64_nan).cmp(&OrderedFloat(-100000.0f64)),
+        Greater
+    );
+    assert_eq!(
+        OrderedFloat(-100.0f64).cmp(&OrderedFloat(Float::nan())),
+        Less
+    );
+}
+
+#[test]
+fn ordered_f64_compare_regular_floats_op() {
+    assert!(OrderedFloat(7.0) == OrderedFloat(7.0));
+    assert!(OrderedFloat(7.0) <= OrderedFloat(7.0));
+    assert!(OrderedFloat(7.0) >= OrderedFloat(7.0));
+    assert!(OrderedFloat(8.0) > OrderedFloat(7.0));
+    assert!(OrderedFloat(8.0) >= OrderedFloat(7.0));
+    assert!(OrderedFloat(4.0) < OrderedFloat(7.0));
+    assert!(OrderedFloat(4.0) <= OrderedFloat(7.0));
+}
+
+#[test]
+fn ordered_f64_compare_nan_op() {
+    let f64_nan: OrderedFloat<f64> = OrderedFloat(Float::nan());
+    assert!(f64_nan == f64_nan);
+    assert!(f64_nan <= f64_nan);
+    assert!(f64_nan >= f64_nan);
+    assert!(f64_nan > OrderedFloat(-100000.0));
+    assert!(f64_nan >= OrderedFloat(-100000.0));
+    assert!(OrderedFloat(-100.0) < f64_nan);
+    assert!(OrderedFloat(-100.0) <= f64_nan);
+    assert!(f64_nan > OrderedFloat(Float::infinity()));
+    assert!(f64_nan >= OrderedFloat(Float::infinity()));
+    assert!(f64_nan > OrderedFloat(Float::neg_infinity()));
+    assert!(f64_nan >= OrderedFloat(Float::neg_infinity()));
+}
+
+#[test]
+fn not_nan32_compare_regular_floats() {
+    assert_eq!(NotNaN::from(7.0f32).cmp(&NotNaN::from(7.0)), Equal);
+    assert_eq!(NotNaN::from(8.0f32).cmp(&NotNaN::from(7.0)), Greater);
+    assert_eq!(NotNaN::from(4.0f32).cmp(&NotNaN::from(7.0)), Less);
+}
+
+#[test]
+fn not_nan32_fail_when_constructing_with_nan() {
+    let f32_nan: f32 = Float::nan();
+    assert!(NotNaN::new(f32_nan).is_err());
+}
+
+#[test]
+fn not_nan32_calculate_correctly() {
+    assert_eq!(
+        *(NotNaN::from(5.0f32) + NotNaN::from(4.0f32)),
+        5.0f32 + 4.0f32
+    );
+    assert_eq!(*(NotNaN::from(5.0f32) + 4.0f32), 5.0f32 + 4.0f32);
+    assert_eq!(
+        *(NotNaN::from(5.0f32) - NotNaN::from(4.0f32)),
+        5.0f32 - 4.0f32
+    );
+    assert_eq!(*(NotNaN::from(5.0f32) - 4.0f32), 5.0f32 - 4.0f32);
+    assert_eq!(
+        *(NotNaN::from(5.0f32) * NotNaN::from(4.0f32)),
+        5.0f32 * 4.0f32
+    );
+    assert_eq!(*(NotNaN::from(5.0f32) * 4.0f32), 5.0f32 * 4.0f32);
+    assert_eq!(
+        *(NotNaN::from(8.0f32) / NotNaN::from(4.0f32)),
+        8.0f32 / 4.0f32
+    );
+    assert_eq!(*(NotNaN::from(8.0f32) / 4.0f32), 8.0f32 / 4.0f32);
+    assert_eq!(
+        *(NotNaN::from(8.0f32) % NotNaN::from(4.0f32)),
+        8.0f32 % 4.0f32
+    );
+    assert_eq!(*(NotNaN::from(8.0f32) % 4.0f32), 8.0f32 % 4.0f32);
+    assert_eq!(*(-NotNaN::from(1.0f32)), -1.0f32);
+
+    assert!(panic::catch_unwind(|| NotNaN::from(0.0f32) + f32::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNaN::from(0.0f32) - f32::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNaN::from(0.0f32) * f32::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNaN::from(0.0f32) / f32::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNaN::from(0.0f32) % f32::NAN).is_err());
+
+    let mut number = NotNaN::from(5.0f32);
+    number += NotNaN::from(4.0f32);
+    assert_eq!(*number, 9.0f32);
+    number -= NotNaN::from(4.0f32);
+    assert_eq!(*number, 5.0f32);
+    number *= NotNaN::from(4.0f32);
+    assert_eq!(*number, 20.0f32);
+    number /= NotNaN::from(4.0f32);
+    assert_eq!(*number, 5.0f32);
+    number %= NotNaN::from(4.0f32);
+    assert_eq!(*number, 1.0f32);
+
+    number = NotNaN::from(5.0f32);
+    number += 4.0f32;
+    assert_eq!(*number, 9.0f32);
+    number -= 4.0f32;
+    assert_eq!(*number, 5.0f32);
+    number *= 4.0f32;
+    assert_eq!(*number, 20.0f32);
+    number /= 4.0f32;
+    assert_eq!(*number, 5.0f32);
+    number %= 4.0f32;
+    assert_eq!(*number, 1.0f32);
+
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNaN::from(0.0f32);
+            tmp += f32::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNaN::from(0.0f32);
+            tmp -= f32::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNaN::from(0.0f32);
+            tmp *= f32::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNaN::from(0.0f32);
+            tmp /= f32::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNaN::from(0.0f32);
+            tmp %= f32::NAN;
+        }).is_err()
+    );
+}
+
+#[test]
+fn not_nan64_compare_regular_floats() {
+    assert_eq!(NotNaN::from(7.0f64).cmp(&NotNaN::from(7.0)), Equal);
+    assert_eq!(NotNaN::from(8.0f64).cmp(&NotNaN::from(7.0)), Greater);
+    assert_eq!(NotNaN::from(4.0f64).cmp(&NotNaN::from(7.0)), Less);
+}
+
+#[test]
+fn not_nan64_fail_when_constructing_with_nan() {
+    let f64_nan: f64 = Float::nan();
+    assert!(NotNaN::new(f64_nan).is_err());
+}
+
+#[test]
+fn not_nan64_calculate_correctly() {
+    assert_eq!(
+        *(NotNaN::from(5.0f64) + NotNaN::from(4.0f64)),
+        5.0f64 + 4.0f64
+    );
+    assert_eq!(*(NotNaN::from(5.0f64) + 4.0f64), 5.0f64 + 4.0f64);
+    assert_eq!(
+        *(NotNaN::from(5.0f64) - NotNaN::from(4.0f64)),
+        5.0f64 - 4.0f64
+    );
+    assert_eq!(*(NotNaN::from(5.0f64) - 4.0f64), 5.0f64 - 4.0f64);
+    assert_eq!(
+        *(NotNaN::from(5.0f64) * NotNaN::from(4.0f64)),
+        5.0f64 * 4.0f64
+    );
+    assert_eq!(*(NotNaN::from(5.0f64) * 4.0f64), 5.0f64 * 4.0f64);
+    assert_eq!(
+        *(NotNaN::from(8.0f64) / NotNaN::from(4.0f64)),
+        8.0f64 / 4.0f64
+    );
+    assert_eq!(*(NotNaN::from(8.0f64) / 4.0f64), 8.0f64 / 4.0f64);
+    assert_eq!(
+        *(NotNaN::from(8.0f64) % NotNaN::from(4.0f64)),
+        8.0f64 % 4.0f64
+    );
+    assert_eq!(*(NotNaN::from(8.0f64) % 4.0f64), 8.0f64 % 4.0f64);
+    assert_eq!(*(-NotNaN::from(1.0f64)), -1.0f64);
+
+    assert!(panic::catch_unwind(|| NotNaN::from(0.0f64) + f64::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNaN::from(0.0f64) - f64::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNaN::from(0.0f64) * f64::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNaN::from(0.0f64) / f64::NAN).is_err());
+    assert!(panic::catch_unwind(|| NotNaN::from(0.0f64) % f64::NAN).is_err());
+
+    let mut number = NotNaN::from(5.0f64);
+    number += NotNaN::from(4.0f64);
+    assert_eq!(*number, 9.0f64);
+    number -= NotNaN::from(4.0f64);
+    assert_eq!(*number, 5.0f64);
+    number *= NotNaN::from(4.0f64);
+    assert_eq!(*number, 20.0f64);
+    number /= NotNaN::from(4.0f64);
+    assert_eq!(*number, 5.0f64);
+    number %= NotNaN::from(4.0f64);
+    assert_eq!(*number, 1.0f64);
+
+    number = NotNaN::from(5.0f64);
+    number += 4.0f64;
+    assert_eq!(*number, 9.0f64);
+    number -= 4.0f64;
+    assert_eq!(*number, 5.0f64);
+    number *= 4.0f64;
+    assert_eq!(*number, 20.0f64);
+    number /= 4.0f64;
+    assert_eq!(*number, 5.0f64);
+    number %= 4.0f64;
+    assert_eq!(*number, 1.0f64);
+
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNaN::from(0.0f64);
+            tmp += f64::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNaN::from(0.0f64);
+            tmp -= f64::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNaN::from(0.0f64);
+            tmp *= f64::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNaN::from(0.0f64);
+            tmp /= f64::NAN;
+        }).is_err()
+    );
+    assert!(
+        panic::catch_unwind(|| {
+            let mut tmp = NotNaN::from(0.0f64);
+            tmp %= f64::NAN;
+        }).is_err()
+    );
+}
+
+#[test]
+fn not_nan64_zero() {
+    assert_eq!(NotNaN::<f64>::zero(), NotNaN::from(0.0f64));
+    assert!(NotNaN::<f64>::zero().is_zero());
+}
+
+#[test]
+fn not_nan64_one() {
+    assert_eq!(NotNaN::<f64>::one(), NotNaN::from(1.0f64))
+}
+
+#[test]
+fn not_nan64_bounded() {
+    assert_eq!(NotNaN::<f64>::min_value(), NotNaN::from(<f64 as Bounded>::min_value()));
+    assert_eq!(NotNaN::<f64>::max_value(), NotNaN::from(<f64 as Bounded>::max_value()));
+}
+
+#[test]
+fn not_nan64_from_primitive() {
+    assert_eq!(NotNaN::<f64>::from_i8(42i8), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_u8(42u8), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_i16(42i16), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_u16(42u16), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_i32(42i32), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_u32(42u32), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_i64(42i64), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_u64(42u64), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_isize(42isize), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_usize(42usize), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_f64(42f64), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_f64(42f64), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_f64(42f64), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_f64(42f64), Some(NotNaN::from(42.0)));
+    assert_eq!(NotNaN::<f64>::from_f64(Float::nan()), None);
+    assert_eq!(NotNaN::<f64>::from_f64(Float::nan()), None);
+}
+
+#[test]
+fn not_nan64_to_primitive() {
+    let x = NotNaN::from(42.0f64);
+    assert_eq!(x.to_u8(), Some(42u8));
+    assert_eq!(x.to_i8(), Some(42i8));
+    assert_eq!(x.to_u16(), Some(42u16));
+    assert_eq!(x.to_i16(), Some(42i16));
+    assert_eq!(x.to_u32(), Some(42u32));
+    assert_eq!(x.to_i32(), Some(42i32));
+    assert_eq!(x.to_u64(), Some(42u64));
+    assert_eq!(x.to_i64(), Some(42i64));
+    assert_eq!(x.to_usize(), Some(42usize));
+    assert_eq!(x.to_isize(), Some(42isize));
+    assert_eq!(x.to_f64(), Some(42f64));
+    assert_eq!(x.to_f64(), Some(42f64));
+    assert_eq!(x.to_f64(), Some(42f64));
+    assert_eq!(x.to_f64(), Some(42f64));
+}
+
+#[test]
+fn not_nan64_num() {
+    assert_eq!(NotNaN::<f64>::from_str_radix("42.0", 10).unwrap(), NotNaN::from(42.0f64));
+    assert!(NotNaN::<f64>::from_str_radix("NaN", 10).is_err());
+}
+
+#[test]
+fn not_nan64_signed() {
+    assert_eq!(NotNaN::from(42f64).abs(), NotNaN::from(42f64));
+    assert_eq!(NotNaN::from(-42f64).abs(), NotNaN::from(42f64));
+
+    assert_eq!(NotNaN::from(50f64).abs_sub(&NotNaN::from(8f64)), NotNaN::from(42f64));
+    assert_eq!(NotNaN::from(8f64).abs_sub(&NotNaN::from(50f64)), NotNaN::from(0f64));
+}
+
+#[test]
+fn not_nan64_num_cast() {
+    assert_eq!(<NotNaN<f64> as num_traits::NumCast>::from(42), Some(NotNaN::from(42f64)));
+    assert_eq!(<NotNaN<f64> as num_traits::NumCast>::from(f64::nan()), None);
+}
+
+#[test]
+fn hash_zero_and_neg_zero_to_the_same_hc() {
+    let state = RandomState::new();
+    let mut h1 = state.build_hasher();
+    let mut h2 = state.build_hasher();
+    OrderedFloat::from(0f64).hash(&mut h1);
+    OrderedFloat::from(-0f64).hash(&mut h2);
+    assert_eq!(h1.finish(), h2.finish());
+}
+
+#[test]
+fn hash_inf_and_neg_inf_to_different_hcs() {
+    let state = RandomState::new();
+    let mut h1 = state.build_hasher();
+    let mut h2 = state.build_hasher();
+    OrderedFloat::from(f64::INFINITY).hash(&mut h1);
+    OrderedFloat::from(f64::NEG_INFINITY).hash(&mut h2);
+    assert!(h1.finish() != h2.finish());
+}
+
+#[test]
+fn hash_is_good_for_whole_numbers() {
+    let state = RandomState::new();
+    let limit = 10000;
+
+    let mut set = ::std::collections::HashSet::with_capacity(limit);
+    for i in 0..limit {
+        let mut h = state.build_hasher();
+        OrderedFloat::from(i as f64).hash(&mut h);
+        set.insert(h.finish());
+    }
+
+    // This allows 100 collisions, which is far too
+    // many, but should guard against transient issues
+    // that will result from using RandomState
+    let pct_unique = set.len() as f64 / limit as f64;
+    assert!(0.99f64 < pct_unique, "percent-unique={}", pct_unique);
+}
+
+#[test]
+fn hash_is_good_for_fractional_numbers() {
+    let state = RandomState::new();
+    let limit = 10000;
+
+    let mut set = ::std::collections::HashSet::with_capacity(limit);
+    for i in 0..limit {
+        let mut h = state.build_hasher();
+        OrderedFloat::from(i as f64 * (1f64 / limit as f64)).hash(&mut h);
+        set.insert(h.finish());
+    }
+
+    // This allows 100 collisions, which is far too
+    // many, but should guard against transient issues
+    // that will result from using RandomState
+    let pct_unique = set.len() as f64 / limit as f64;
+    assert!(0.99f64 < pct_unique, "percent-unique={}", pct_unique);
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new_debug_unreachable/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".travis.yml":"d91d0d75087934c2d0503a8c04439fea459a19182021bb0b699644d442f5b6fc","Cargo.toml":"4081c443d3318411bec6bf1dd8284b7ef4eb39994ca2be66292f0bce6ffae9f6","LICENSE-MIT":"f7715d38a3fa1b4ac97c5729740752505a39cb92ee83ab5b102aeb5eaa7cdea4","README.md":"36ffe300159d4ce4c8224969723606312770117a0a25fbcb3534922c8248b0e9","examples/simple.rs":"c05b124bdad67bfe9e48998bff6a7c6a8789e7f7c9fb3f318f8028a68ef944ed","src/lib.rs":"08a58847b86729b9b2a4eb1125457fc5e76206f9f86a014c1ba26ce6e3f0ebac","tests/check.rs":"ac8691f78269e1cb0cd010150e707f5ea5df14055883f0ee5a5b55a686c5b8de"},"package":"0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"}
\ No newline at end of file
rename from third_party/rust/debug_unreachable/.travis.yml
rename to third_party/rust/new_debug_unreachable/.travis.yml
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new_debug_unreachable/Cargo.toml
@@ -0,0 +1,27 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "new_debug_unreachable"
+version = "1.0.1"
+authors = ["Matt Brubeck <mbrubeck@limpet.net>", "Jonathan Reem <jonathan.reem@gmail.com>"]
+description = "panic in debug, intrinsics::unreachable() in release (fork of debug_unreachable)"
+documentation = "https://docs.rs/new_debug_unreachable"
+readme = "README.md"
+license = "MIT"
+repository = "https://github.com/mbrubeck/rust-debug-unreachable"
+
+[lib]
+name = "debug_unreachable"
+path = "src/lib.rs"
+[dependencies.unreachable]
+version = "1.0"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new_debug_unreachable/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2015 Jonathan Reem
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new_debug_unreachable/README.md
@@ -0,0 +1,27 @@
+# new_debug_unreachable
+
+> unreachable!() in debug, std::intrinsics::unreachable() in release.
+
+This is a fork of [`debug_unreachable`](https://crates.io/crates/debug_unreachable).
+
+## [Documentation](https://docs.rs/new_debug_unreachable)
+
+## Usage
+
+Use the crates.io repository; add this to your `Cargo.toml` along
+with the rest of your dependencies:
+
+```toml
+[dependencies]
+new_debug_unreachable = "1.0"
+```
+
+## Author
+
+[Jonathan Reem](https://medium.com/@jreem) is the original author of debug-unreachable.
+
+[Matt Brubeck](https://limpet.net/mbrubeck/) is the maintainer of this fork.
+
+## License
+
+MIT
rename from third_party/rust/debug_unreachable/examples/simple.rs
rename to third_party/rust/new_debug_unreachable/examples/simple.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/new_debug_unreachable/src/lib.rs
@@ -0,0 +1,24 @@
+#![deny(missing_docs, warnings)]
+
+#![no_std]
+
+//! `panic!()` in debug builds, optimization hint in release.
+
+extern crate unreachable;
+
+#[doc(hidden)]
+pub use unreachable::unreachable as __unreachable;
+
+#[macro_export]
+/// `panic!()` in debug builds, optimization hint in release.
+macro_rules! debug_unreachable {
+    () => { debug_unreachable!("entered unreachable code") };
+    ($e:expr) => {
+        if cfg!(debug_assertions) {
+            panic!($e);
+        } else {
+            $crate::__unreachable()
+        }
+    }
+}
+
rename from third_party/rust/debug_unreachable/tests/check.rs
rename to third_party/rust/new_debug_unreachable/tests/check.rs
deleted file mode 100644
--- a/third_party/rust/ordered-float/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{".travis.yml":"836b2a8c7fc40a6b7fafc7ae6d4cc0cfc5e8cd1ce9023843ed471f1d5f41af8b","Cargo.toml":"fa8d70d0447555cbda365af477d0bb43fefa964562d76b262ec67f0f2e658bd4","README.md":"10c54822e3ec242a69f9abcbf15cec555f666280336b0e650d6f008c982adc7c","src/lib.rs":"d0dbfdac8aa6d7be0bf0d4e443a197b88f73262f88670df531c84993aa4bc45c","tests/test.rs":"f339d8b594fb450903349fba93d04d91322a2c947b5d5ebb475ca10ae04a0eb2"},"package":"da12c96037889ae0be29dd2bdd260e5a62a7df24e6466d5a15bb8131c1c200a8"}
\ No newline at end of file
deleted file mode 100644
--- a/third_party/rust/ordered-float/.travis.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-language: rust
-rust: nightly
-sudo: false
-env:
-    matrix:
-        - FEATURES=
-        - FEATURES="serde"
-        - FEATURES="rustc-serialize"
-        - FEATURES="serde rustc-serialize"
-script:
-    - cargo test -v --features "$FEATURES"
deleted file mode 100644
--- a/third_party/rust/ordered-float/Cargo.toml
+++ /dev/null
@@ -1,17 +0,0 @@
-[package]
-
-name = "ordered-float"
-version = "0.4.0"
-authors = ["Jonathan Reem <jonathan.reem@gmail.com>"]
-license = "MIT"
-description = "Wrappers for total ordering on floats."
-repository = "https://github.com/reem/rust-ordered-float"
-
-[dependencies]
-num-traits = { version = "0.1", default_features = false }
-serde = { version = "0.8", optional = true }
-rustc-serialize = { version = "0.3", optional = true }
-unreachable = "0.1"
-
-[dev-dependencies]
-stainless = "0.1"
deleted file mode 100644
--- a/third_party/rust/ordered-float/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Ordered Floats
-
-Provides several wrapper types for Ord and Eq implementations on f64.
-
-See `src/lib.rs` for documentation and details.
-
-## License
-
-MIT
-
-## Tools
-
-Built using Cargo
-Tested using Stainless
-
deleted file mode 100644
--- a/third_party/rust/ordered-float/src/lib.rs
+++ /dev/null
@@ -1,629 +0,0 @@
-#![cfg_attr(test, deny(warnings))]
-#![deny(missing_docs)]
-
-//! Wrappers for total order on Floats.
-
-extern crate num_traits;
-extern crate unreachable;
-
-use std::cmp::Ordering;
-use std::error::Error;
-use std::ops::{Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Rem,
-               RemAssign, Sub, SubAssign};
-use std::hash::{Hash, Hasher};
-use std::fmt;
-use std::io;
-use std::mem;
-use unreachable::unreachable;
-use num_traits::Float;
-
-// masks for the parts of the IEEE 754 float
-const SIGN_MASK: u64 = 0x8000000000000000u64;
-const EXP_MASK: u64 = 0x7ff0000000000000u64;
-const MAN_MASK: u64 = 0x000fffffffffffffu64;
-
-// canonical raw bit patterns (for hashing)
-const CANONICAL_NAN_BITS: u64 = 0x7ff8000000000000u64;
-const CANONICAL_ZERO_BITS: u64 = 0x0u64;
-
-/// A wrapper around Floats providing an implementation of Ord and Hash.
-///
-/// NaN is sorted as *greater* than all other values and *equal*
-/// to itself, in contradiction with the IEEE standard.
-#[derive(PartialOrd, Debug, Default, Clone, Copy)]
-pub struct OrderedFloat<T: Float>(pub T);
-
-impl<T: Float> OrderedFloat<T> {
-    /// Get the value out.
-    pub fn into_inner(self) -> T {
-        let OrderedFloat(val) = self;
-        val
-    }
-}
-
-impl<T: Float> AsRef<T> for OrderedFloat<T> {
-    fn as_ref(&self) -> &T {
-        let OrderedFloat(ref val) = *self;
-        val
-    }
-}
-
-impl<T: Float> AsMut<T> for OrderedFloat<T> {
-    fn as_mut(&mut self) -> &mut T {
-        let OrderedFloat(ref mut val) = *self;
-        val
-    }
-}
-
-impl<T: Float + PartialOrd> Ord for OrderedFloat<T> {
-    fn cmp(&self, other: &OrderedFloat<T>) -> Ordering {
-        match self.partial_cmp(&other) {
-            Some(ordering) => ordering,
-            None => {
-                if self.as_ref().is_nan() {
-                    if other.as_ref().is_nan() {
-                        Ordering::Equal
-                    } else {
-                        Ordering::Greater
-                    }
-                } else {
-                    Ordering::Less
-                }
-            }
-        }
-    }
-}
-
-impl<T: Float + PartialEq> PartialEq for OrderedFloat<T> {
-    fn eq(&self, other: &OrderedFloat<T>) -> bool {
-        if self.as_ref().is_nan() {
-            if other.as_ref().is_nan() { true } else { false }
-        } else if other.as_ref().is_nan() {
-            false
-        } else {
-            self.as_ref() == other.as_ref()
-        }
-    }
-}
-
-impl<T: Float> Hash for OrderedFloat<T> {
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        if self.is_nan() {
-            // normalize to one representation of NaN
-            hash_float(&T::nan(), state)
-        } else {
-            hash_float(self.as_ref(), state)
-        }
-    }
-}
-
-impl<T: Float + fmt::Display> fmt::Display for OrderedFloat<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.as_ref().fmt(f)
-    }
-}
-
-impl Into<f32> for OrderedFloat<f32> {
-    fn into(self) -> f32 {
-        self.into_inner()
-    }
-}
-
-impl Into<f64> for OrderedFloat<f64> {
-    fn into(self) -> f64 {
-        self.into_inner()
-    }
-}
-
-impl<T: Float> From<T> for OrderedFloat<T> {
-    fn from(val: T) -> Self {
-        OrderedFloat(val)
-    }
-}
-
-impl<T: Float> Deref for OrderedFloat<T> {
-    type Target = T;
-
-    fn deref(&self) -> &Self::Target {
-        self.as_ref()
-    }
-}
-
-impl<T: Float> DerefMut for OrderedFloat<T> {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        self.as_mut()
-    }
-}
-
-impl<T: Float + PartialEq> Eq for OrderedFloat<T> {}
-
-/// A wrapper around Floats providing an implementation of Ord and Hash.
-///
-/// A NaN value cannot be stored in this type.
-#[derive(PartialOrd, PartialEq, Debug, Default, Clone, Copy)]
-pub struct NotNaN<T: Float>(T);
-
-impl<T: Float> NotNaN<T> {
-    /// Create a NotNaN value.
-    ///
-    /// Returns Err if val is NaN
-    pub fn new(val: T) -> Result<Self, FloatIsNaN> {
-        match val {
-            ref val if val.is_nan() => Err(FloatIsNaN),
-            val => Ok(NotNaN(val)),
-        }
-    }
-
-    /// Create a NotNaN value from a value that is guaranteed to not be NaN
-    ///
-    /// Behaviour is undefined if `val` is NaN
-    pub unsafe fn unchecked_new(val: T) -> Self {
-        debug_assert!(!val.is_nan());
-        NotNaN(val)
-    }
-
-    /// Get the value out.
-    pub fn into_inner(self) -> T {
-        let NotNaN(val) = self;
-        val
-    }
-}
-
-impl<T: Float> AsRef<T> for NotNaN<T> {
-    fn as_ref(&self) -> &T {
-        let NotNaN(ref val) = *self;
-        val
-    }
-}
-
-impl<T: Float + PartialOrd> Ord for NotNaN<T> {
-    fn cmp(&self, other: &NotNaN<T>) -> Ordering {
-        match self.partial_cmp(&other) {
-            Some(ord) => ord,
-            None => unsafe { unreachable() },
-        }
-    }
-}
-
-impl<T: Float> Hash for NotNaN<T> {
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        hash_float(self.as_ref(), state)
-    }
-}
-
-impl<T: Float + fmt::Display> fmt::Display for NotNaN<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.as_ref().fmt(f)
-    }
-}
-
-impl Into<f32> for NotNaN<f32> {
-    fn into(self) -> f32 {
-        self.into_inner()
-    }
-}
-
-impl Into<f64> for NotNaN<f64> {
-    fn into(self) -> f64 {
-        self.into_inner()
-    }
-}
-
-/// Creates a NotNaN value from a Float.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl<T: Float> From<T> for NotNaN<T> {
-    fn from(v: T) -> Self {
-        assert!(!v.is_nan());
-        NotNaN(v)
-    }
-}
-
-impl<T: Float> Deref for NotNaN<T> {
-    type Target = T;
-
-    fn deref(&self) -> &Self::Target {
-        self.as_ref()
-    }
-}
-
-impl<T: Float + PartialEq> Eq for NotNaN<T> {}
-
-impl<T: Float> Add for NotNaN<T> {
-    type Output = Self;
-
-    fn add(self, other: Self) -> Self {
-        NotNaN(self.0 + other.0)
-    }
-}
-
-/// Adds a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl<T: Float> Add<T> for NotNaN<T> {
-    type Output = Self;
-
-    fn add(self, other: T) -> Self {
-        assert!(!other.is_nan());
-        NotNaN::new(self.0 + other).expect("Addition resulted in NaN")
-    }
-}
-
-impl AddAssign for NotNaN<f64> {
-    fn add_assign(&mut self, other: Self) {
-        self.0 += other.0;
-        assert!(!self.0.is_nan(), "Addition resulted in NaN")
-    }
-}
-
-impl AddAssign for NotNaN<f32> {
-    fn add_assign(&mut self, other: Self) {
-        self.0 += other.0;
-        assert!(!self.0.is_nan(), "Addition resulted in NaN")
-    }
-}
-
-/// Adds a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl AddAssign<f64> for NotNaN<f64> {
-    fn add_assign(&mut self, other: f64) {
-        assert!(!other.is_nan());
-        self.0 += other;
-        assert!(!self.0.is_nan(), "Addition resulted in NaN")
-    }
-}
-
-/// Adds a float directly.
-///
-/// Panics if the provided value is NaN.
-impl AddAssign<f32> for NotNaN<f32> {
-    fn add_assign(&mut self, other: f32) {
-        assert!(!other.is_nan());
-        self.0 += other;
-        assert!(!self.0.is_nan(), "Addition resulted in NaN")
-    }
-}
-
-impl<T: Float> Sub for NotNaN<T> {
-    type Output = Self;
-
-    fn sub(self, other: Self) -> Self {
-        NotNaN::new(self.0 - other.0).expect("Subtraction resulted in NaN")
-    }
-}
-
-/// Subtracts a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl<T: Float> Sub<T> for NotNaN<T> {
-    type Output = Self;
-
-    fn sub(self, other: T) -> Self {
-        assert!(!other.is_nan());
-        NotNaN::new(self.0 - other).expect("Subtraction resulted in NaN")
-    }
-}
-
-impl SubAssign for NotNaN<f64> {
-    fn sub_assign(&mut self, other: Self) {
-        self.0 -= other.0;
-        assert!(!self.0.is_nan(), "Subtraction resulted in NaN")
-    }
-}
-
-impl SubAssign for NotNaN<f32> {
-    fn sub_assign(&mut self, other: Self) {
-        self.0 -= other.0;
-        assert!(!self.0.is_nan(), "Subtraction resulted in NaN")
-    }
-}
-
-/// Subtracts a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl SubAssign<f64> for NotNaN<f64> {
-    fn sub_assign(&mut self, other: f64) {
-        assert!(!other.is_nan());
-        self.0 -= other;
-        assert!(!self.0.is_nan(), "Subtraction resulted in NaN")
-    }
-}
-
-/// Subtracts a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl SubAssign<f32> for NotNaN<f32> {
-    fn sub_assign(&mut self, other: f32) {
-        assert!(!other.is_nan());
-        self.0 -= other;
-        assert!(!self.0.is_nan(), "Subtraction resulted in NaN")
-    }
-}
-
-impl<T: Float> Mul for NotNaN<T> {
-    type Output = Self;
-
-    fn mul(self, other: Self) -> Self {
-        NotNaN::new(self.0 * other.0).expect("Multiplication resulted in NaN")
-    }
-}
-
-/// Multiplies a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl<T: Float> Mul<T> for NotNaN<T> {
-    type Output = Self;
-
-    fn mul(self, other: T) -> Self {
-        assert!(!other.is_nan());
-        NotNaN::new(self.0 * other).expect("Multiplication resulted in NaN")
-    }
-}
-
-impl MulAssign for NotNaN<f64> {
-    fn mul_assign(&mut self, other: Self) {
-        self.0 *= other.0;
-        assert!(!self.0.is_nan(), "Multiplication resulted in NaN")
-    }
-}
-
-impl MulAssign for NotNaN<f32> {
-    fn mul_assign(&mut self, other: Self) {
-        self.0 *= other.0;
-        assert!(!self.0.is_nan(), "Multiplication resulted in NaN")
-    }
-}
-
-/// Multiplies a float directly.
-///
-/// Panics if the provided value is NaN.
-impl MulAssign<f64> for NotNaN<f64> {
-    fn mul_assign(&mut self, other: f64) {
-        assert!(!other.is_nan());
-        self.0 *= other;
-    }
-}
-
-/// Multiplies a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl MulAssign<f32> for NotNaN<f32> {
-    fn mul_assign(&mut self, other: f32) {
-        assert!(!other.is_nan());
-        self.0 *= other;
-        assert!(!self.0.is_nan(), "Multiplication resulted in NaN")
-    }
-}
-
-impl<T: Float> Div for NotNaN<T> {
-    type Output = Self;
-
-    fn div(self, other: Self) -> Self {
-        NotNaN::new(self.0 / other.0).expect("Division resulted in NaN")
-    }
-}
-
-/// Divides a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl<T: Float> Div<T> for NotNaN<T> {
-    type Output = Self;
-
-    fn div(self, other: T) -> Self {
-        assert!(!other.is_nan());
-        NotNaN::new(self.0 / other).expect("Division resulted in NaN")
-    }
-}
-
-impl DivAssign for NotNaN<f64> {
-    fn div_assign(&mut self, other: Self) {
-        self.0 /= other.0;
-        assert!(!self.0.is_nan(), "Division resulted in NaN")
-    }
-}
-
-impl DivAssign for NotNaN<f32> {
-    fn div_assign(&mut self, other: Self) {
-        self.0 /= other.0;
-        assert!(!self.0.is_nan(), "Division resulted in NaN")
-    }
-}
-
-/// Divides a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl DivAssign<f64> for NotNaN<f64> {
-    fn div_assign(&mut self, other: f64) {
-        assert!(!other.is_nan());
-        self.0 /= other;
-        assert!(!self.0.is_nan(), "Division resulted in NaN")
-    }
-}
-
-/// Divides a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl DivAssign<f32> for NotNaN<f32> {
-    fn div_assign(&mut self, other: f32) {
-        assert!(!other.is_nan());
-        self.0 /= other;
-        assert!(!self.0.is_nan(), "Division resulted in NaN")
-    }
-}
-
-impl<T: Float> Rem for NotNaN<T> {
-    type Output = Self;
-
-    fn rem(self, other: Self) -> Self {
-        NotNaN::new(self.0 % other.0).expect("Rem resulted in NaN")
-    }
-}
-
-/// Calculates `%` with a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl<T: Float> Rem<T> for NotNaN<T> {
-    type Output = Self;
-
-    fn rem(self, other: T) -> Self {
-        assert!(!other.is_nan());
-        NotNaN::new(self.0 % other).expect("Rem resulted in NaN")
-    }
-}
-
-impl RemAssign for NotNaN<f64> {
-    fn rem_assign(&mut self, other: Self) {
-        self.0 %= other.0;
-        assert!(!self.0.is_nan(), "Rem resulted in NaN")
-    }
-}
-
-impl RemAssign for NotNaN<f32> {
-    fn rem_assign(&mut self, other: Self) {
-        self.0 %= other.0;
-        assert!(!self.0.is_nan(), "Rem resulted in NaN")
-    }
-}
-
-/// Calculates `%=` with a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl RemAssign<f64> for NotNaN<f64> {
-    fn rem_assign(&mut self, other: f64) {
-        assert!(!other.is_nan());
-        self.0 %= other;
-        assert!(!self.0.is_nan(), "Rem resulted in NaN")
-    }
-}
-
-/// Calculates `%=` with a float directly.
-///
-/// Panics if the provided value is NaN or the computation results in NaN
-impl RemAssign<f32> for NotNaN<f32> {
-    fn rem_assign(&mut self, other: f32) {
-        assert!(!other.is_nan());
-        self.0 %= other;
-        assert!(!self.0.is_nan(), "Rem resulted in NaN")
-    }
-}
-
-impl<T: Float> Neg for NotNaN<T> {
-    type Output = Self;
-
-    fn neg(self) -> Self {
-        NotNaN::new(-self.0).expect("Negation resulted in NaN")
-    }
-}
-
-/// An error indicating an attempt to construct NotNaN from a NaN
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub struct FloatIsNaN;
-
-impl Error for FloatIsNaN {
-    fn description(&self) -> &str {
-        return "NotNaN constructed with NaN";
-    }
-}
-
-impl fmt::Display for FloatIsNaN {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        <Self as fmt::Debug>::fmt(self, f)
-    }
-}
-
-impl Into<io::Error> for FloatIsNaN {
-    fn into(self) -> io::Error {
-        io::Error::new(io::ErrorKind::InvalidInput, self)
-    }
-}
-
-#[inline]
-fn hash_float<F: Float, H: Hasher>(f: &F, state: &mut H) {
-    raw_double_bits(f).hash(state);
-}
-
-#[inline]
-fn raw_double_bits<F: Float>(f: &F) -> u64 {
-    if f.is_nan() {
-        return CANONICAL_NAN_BITS;
-    }
-
-    let (man, exp, sign) = f.integer_decode();
-    if man == 0 {
-        return CANONICAL_ZERO_BITS;
-    }
-
-    let exp_u64 = unsafe { mem::transmute::<i16, u16>(exp) } as u64;
-    let sign_u64 = if sign > 0 { 1u64 } else { 0u64 };
-    (man & MAN_MASK) | ((exp_u64 << 52) & EXP_MASK) | ((sign_u64 << 63) & SIGN_MASK)
-}
-
-#[cfg(feature = "rustc-serialize")]
-mod impl_rustc {
-    extern crate rustc_serialize;
-    use self::rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
-    use super::{OrderedFloat, NotNaN};
-    use std::error::Error;
-    use num_traits::Float;
-
-    impl<T: Float + Encodable> Encodable for OrderedFloat<T> {
-        fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-            self.0.encode(s)
-        }
-    }
-
-    impl<T: Float + Decodable> Decodable for OrderedFloat<T> {
-        fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
-            T::decode(d).map(OrderedFloat)
-        }
-    }
-
-    impl<T: Float + Encodable> Encodable for NotNaN<T> {
-        fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-            self.0.encode(s)
-        }
-    }
-
-    impl<T: Float + Decodable> Decodable for NotNaN<T> {
-        fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
-            T::decode(d).and_then(|v| NotNaN::new(v).map_err(|e| d.error(e.description())))
-        }
-    }
-}
-
-#[cfg(feature = "serde")]
-mod impl_serde {
-    extern crate serde;
-    use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
-    use self::serde::de::Error;
-    use super::{OrderedFloat, NotNaN};
-    use num_traits::Float;
-
-    impl<T: Float + Serialize> Serialize for OrderedFloat<T> {
-        fn serialize<S: Serializer>(&self, s: &mut S) -> Result<(), S::Error> {
-            self.0.serialize(s)
-        }
-    }
-
-    impl<T: Float + Deserialize> Deserialize for OrderedFloat<T> {
-        fn deserialize<D: Deserializer>(d: &mut D) -> Result<Self, D::Error> {
-            T::deserialize(d).map(OrderedFloat)
-        }
-    }
-
-    impl<T: Float + Serialize> Serialize for NotNaN<T> {
-        fn serialize<S: Serializer>(&self, s: &mut S) -> Result<(), S::Error> {
-            self.0.serialize(s)
-        }
-    }
-
-    impl<T: Float + Deserialize> Deserialize for NotNaN<T> {
-        fn deserialize<D: Deserializer>(d: &mut D) -> Result<Self, D::Error> {
-            T::deserialize(d).and_then(|v| {
-                NotNaN::new(v)
-                    .map_err(|_| <D::Error as Error>::invalid_value("value cannot be NaN"))
-            })
-        }
-    }
-}
deleted file mode 100644
--- a/third_party/rust/ordered-float/tests/test.rs
+++ /dev/null
@@ -1,226 +0,0 @@
-#![feature(plugin)]
-#![plugin(stainless)]
-
-extern crate ordered_float;
-extern crate num_traits;
-
-pub use ordered_float::*;
-pub use num_traits::Float;
-pub use std::cmp::Ordering::*;
-pub use std::{f32, f64, panic};
-
-pub use std::collections::HashSet;
-pub use std::collections::hash_map::RandomState;
-pub use std::hash::*;
-
-describe! ordered_float32 {
-    it "should compare regular floats" {
-        assert_eq!(OrderedFloat(7.0f32).cmp(&OrderedFloat(7.0)), Equal);
-        assert_eq!(OrderedFloat(8.0f32).cmp(&OrderedFloat(7.0)), Greater);
-        assert_eq!(OrderedFloat(4.0f32).cmp(&OrderedFloat(7.0)), Less);
-    }
-
-    it "should compare NaN" {
-        let f32_nan: f32 = Float::nan();
-        assert_eq!(OrderedFloat(f32_nan).cmp(&OrderedFloat(Float::nan())), Equal);
-        assert_eq!(OrderedFloat(f32_nan).cmp(&OrderedFloat(-100000.0f32)), Greater);
-        assert_eq!(OrderedFloat(-100.0f32).cmp(&OrderedFloat(Float::nan())), Less);
-    }
-}
-
-describe! ordered_float64 {
-    it "should compare regular floats" {
-        assert_eq!(OrderedFloat(7.0f64).cmp(&OrderedFloat(7.0)), Equal);
-        assert_eq!(OrderedFloat(8.0f64).cmp(&OrderedFloat(7.0)), Greater);
-        assert_eq!(OrderedFloat(4.0f64).cmp(&OrderedFloat(7.0)), Less);
-    }
-
-    it "should compare NaN" {
-        let f64_nan: f64 = Float::nan();
-        assert_eq!(OrderedFloat(f64_nan).cmp(&OrderedFloat(Float::nan())), Equal);
-        assert_eq!(OrderedFloat(f64_nan).cmp(&OrderedFloat(-100000.0f64)), Greater);
-        assert_eq!(OrderedFloat(-100.0f64).cmp(&OrderedFloat(Float::nan())), Less);
-    }
-}
-
-describe! not_nan32 {
-    it "should compare regular floats" {
-        assert_eq!(NotNaN::from(7.0f32).cmp(&NotNaN::from(7.0)), Equal);
-        assert_eq!(NotNaN::from(8.0f32).cmp(&NotNaN::from(7.0)), Greater);
-        assert_eq!(NotNaN::from(4.0f32).cmp(&NotNaN::from(7.0)), Less);
-    }
-
-    it "should fail when constructing NotNaN with NaN" {
-        let f32_nan: f32 = Float::nan();
-        assert!(NotNaN::new(f32_nan).is_err());
-    }
-    
-    it "should calculate correctly" {
-        assert_eq!(*(NotNaN::from(5.0f32) + NotNaN::from(4.0f32)), 5.0f32 + 4.0f32);
-        assert_eq!(*(NotNaN::from(5.0f32) + 4.0f32), 5.0f32 + 4.0f32);
-        assert_eq!(*(NotNaN::from(5.0f32) - NotNaN::from(4.0f32)), 5.0f32 - 4.0f32);
-        assert_eq!(*(NotNaN::from(5.0f32) - 4.0f32), 5.0f32 - 4.0f32);
-        assert_eq!(*(NotNaN::from(5.0f32) * NotNaN::from(4.0f32)), 5.0f32 * 4.0f32);
-        assert_eq!(*(NotNaN::from(5.0f32) * 4.0f32), 5.0f32 * 4.0f32);
-        assert_eq!(*(NotNaN::from(8.0f32) / NotNaN::from(4.0f32)), 8.0f32 / 4.0f32);
-        assert_eq!(*(NotNaN::from(8.0f32) / 4.0f32), 8.0f32 / 4.0f32);
-        assert_eq!(*(NotNaN::from(8.0f32) % NotNaN::from(4.0f32)), 8.0f32 % 4.0f32);
-        assert_eq!(*(NotNaN::from(8.0f32) % 4.0f32), 8.0f32 % 4.0f32);
-        assert_eq!(*(-NotNaN::from(1.0f32)), -1.0f32);
-        
-        assert!(panic::catch_unwind(|| {NotNaN::from(0.0f32) + f32::NAN}).is_err());
-        assert!(panic::catch_unwind(|| {NotNaN::from(0.0f32) - f32::NAN}).is_err());
-        assert!(panic::catch_unwind(|| {NotNaN::from(0.0f32) * f32::NAN}).is_err());
-        assert!(panic::catch_unwind(|| {NotNaN::from(0.0f32) / f32::NAN}).is_err());
-        assert!(panic::catch_unwind(|| {NotNaN::from(0.0f32) % f32::NAN}).is_err());
-        
-        let mut number = NotNaN::from(5.0f32);
-        number += NotNaN::from(4.0f32);
-        assert_eq!(*number, 9.0f32);
-        number -= NotNaN::from(4.0f32);
-        assert_eq!(*number, 5.0f32);
-        number *= NotNaN::from(4.0f32);
-        assert_eq!(*number, 20.0f32);
-        number /= NotNaN::from(4.0f32);
-        assert_eq!(*number, 5.0f32);
-        number %= NotNaN::from(4.0f32);
-        assert_eq!(*number, 1.0f32);
-        
-        number = NotNaN::from(5.0f32);
-        number += 4.0f32;
-        assert_eq!(*number, 9.0f32);
-        number -= 4.0f32;
-        assert_eq!(*number, 5.0f32);
-        number *= 4.0f32;
-        assert_eq!(*number, 20.0f32);
-        number /= 4.0f32;
-        assert_eq!(*number, 5.0f32);
-        number %= 4.0f32;
-        assert_eq!(*number, 1.0f32);
-        
-        assert!(panic::catch_unwind(|| {let mut tmp = NotNaN::from(0.0f32); tmp += f32::NAN;}).is_err());
-        assert!(panic::catch_unwind(|| {let mut tmp = NotNaN::from(0.0f32); tmp -= f32::NAN;}).is_err());
-        assert!(panic::catch_unwind(|| {let mut tmp = NotNaN::from(0.0f32); tmp *= f32::NAN;}).is_err());
-        assert!(panic::catch_unwind(|| {let mut tmp = NotNaN::from(0.0f32); tmp /= f32::NAN;}).is_err());
-        assert!(panic::catch_unwind(|| {let mut tmp = NotNaN::from(0.0f32); tmp %= f32::NAN;}).is_err());
-    }
-}
-
-describe! not_nan64 {
-    it "should compare regular floats" {
-        assert_eq!(NotNaN::from(7.0f64).cmp(&NotNaN::from(7.0)), Equal);
-        assert_eq!(NotNaN::from(8.0f64).cmp(&NotNaN::from(7.0)), Greater);
-        assert_eq!(NotNaN::from(4.0f64).cmp(&NotNaN::from(7.0)), Less);
-    }
-
-    it "should fail when constructing NotNaN with NaN" {
-        let f64_nan: f64 = Float::nan();
-        assert!(NotNaN::new(f64_nan).is_err());
-    }
-    
-    it "should calculate correctly" {
-        assert_eq!(*(NotNaN::from(5.0f64) + NotNaN::from(4.0f64)), 5.0f64 + 4.0f64);
-        assert_eq!(*(NotNaN::from(5.0f64) + 4.0f64), 5.0f64 + 4.0f64);
-        assert_eq!(*(NotNaN::from(5.0f64) - NotNaN::from(4.0f64)), 5.0f64 - 4.0f64);
-        assert_eq!(*(NotNaN::from(5.0f64) - 4.0f64), 5.0f64 - 4.0f64);
-        assert_eq!(*(NotNaN::from(5.0f64) * NotNaN::from(4.0f64)), 5.0f64 * 4.0f64);
-        assert_eq!(*(NotNaN::from(5.0f64) * 4.0f64), 5.0f64 * 4.0f64);
-        assert_eq!(*(NotNaN::from(8.0f64) / NotNaN::from(4.0f64)), 8.0f64 / 4.0f64);
-        assert_eq!(*(NotNaN::from(8.0f64) / 4.0f64), 8.0f64 / 4.0f64);
-        assert_eq!(*(NotNaN::from(8.0f64) % NotNaN::from(4.0f64)), 8.0f64 % 4.0f64);
-        assert_eq!(*(NotNaN::from(8.0f64) % 4.0f64), 8.0f64 % 4.0f64);
-        assert_eq!(*(-NotNaN::from(1.0f64)), -1.0f64);
-        
-        assert!(panic::catch_unwind(|| {NotNaN::from(0.0f64) + f64::NAN}).is_err());
-        assert!(panic::catch_unwind(|| {NotNaN::from(0.0f64) - f64::NAN}).is_err());
-        assert!(panic::catch_unwind(|| {NotNaN::from(0.0f64) * f64::NAN}).is_err());
-        assert!(panic::catch_unwind(|| {NotNaN::from(0.0f64) / f64::NAN}).is_err());
-        assert!(panic::catch_unwind(|| {NotNaN::from(0.0f64) % f64::NAN}).is_err());
-        
-        let mut number = NotNaN::from(5.0f64);
-        number += NotNaN::from(4.0f64);
-        assert_eq!(*number, 9.0f64);
-        number -= NotNaN::from(4.0f64);
-        assert_eq!(*number, 5.0f64);
-        number *= NotNaN::from(4.0f64);
-        assert_eq!(*number, 20.0f64);
-        number /= NotNaN::from(4.0f64);
-        assert_eq!(*number, 5.0f64);
-        number %= NotNaN::from(4.0f64);
-        assert_eq!(*number, 1.0f64);
-        
-        number = NotNaN::from(5.0f64);
-        number += 4.0f64;
-        assert_eq!(*number, 9.0f64);
-        number -= 4.0f64;
-        assert_eq!(*number, 5.0f64);
-        number *= 4.0f64;
-        assert_eq!(*number, 20.0f64);
-        number /= 4.0f64;
-        assert_eq!(*number, 5.0f64);
-        number %= 4.0f64;
-        assert_eq!(*number, 1.0f64);
-        
-        assert!(panic::catch_unwind(|| {let mut tmp = NotNaN::from(0.0f64); tmp += f64::NAN;}).is_err());
-        assert!(panic::catch_unwind(|| {let mut tmp = NotNaN::from(0.0f64); tmp -= f64::NAN;}).is_err());
-        assert!(panic::catch_unwind(|| {let mut tmp = NotNaN::from(0.0f64); tmp *= f64::NAN;}).is_err());
-        assert!(panic::catch_unwind(|| {let mut tmp = NotNaN::from(0.0f64); tmp /= f64::NAN;}).is_err());
-        assert!(panic::catch_unwind(|| {let mut tmp = NotNaN::from(0.0f64); tmp %= f64::NAN;}).is_err());
-    }
-}
-
-describe! hashing {
-    it "should hash zero and neg-zero to the same hc" {
-        let state = RandomState::new();
-        let mut h1 = state.build_hasher();
-        let mut h2 = state.build_hasher();
-        OrderedFloat::from(0f64).hash(&mut h1);
-        OrderedFloat::from(-0f64).hash(&mut h2);
-        assert_eq!(h1.finish(), h2.finish());
-    }
-
-    it "should hash inf and neg-inf to different hcs" {
-        let state = RandomState::new();
-        let mut h1 = state.build_hasher();
-        let mut h2 = state.build_hasher();
-        OrderedFloat::from(f64::INFINITY).hash(&mut h1);
-        OrderedFloat::from(f64::NEG_INFINITY).hash(&mut h2);
-        assert!(h1.finish() != h2.finish());
-    }
-
-    it "should have a good hash function for whole numbers" {
-        let state = RandomState::new();
-        let limit = 10000;
-
-        let mut set = ::std::collections::HashSet::with_capacity(limit);
-        for i in 0..limit {
-            let mut h = state.build_hasher();
-            OrderedFloat::from(i as f64).hash(&mut h);
-            set.insert(h.finish());
-        }
-
-        // This allows 100 collisions, which is far too
-        // many, but should guard against transient issues
-        // that will result from using RandomState
-        let pct_unique = set.len() as f64 / limit as f64;
-        assert!(0.99f64 < pct_unique, "percent-unique={}", pct_unique);
-    }
-
-    it "should have a good hash function for fractional numbers" {
-        let state = RandomState::new();
-        let limit = 10000;
-
-        let mut set = ::std::collections::HashSet::with_capacity(limit);
-        for i in 0..limit {
-            let mut h = state.build_hasher();
-            OrderedFloat::from(i as f64 * (1f64 / limit as f64)).hash(&mut h);
-            set.insert(h.finish());
-        }
-
-        // This allows 100 collisions, which is far too
-        // many, but should guard against transient issues
-        // that will result from using RandomState
-        let pct_unique = set.len() as f64 / limit as f64;
-        assert!(0.99f64 < pct_unique, "percent-unique={}", pct_unique);
-    }
-}
--- a/third_party/rust/string_cache/.cargo-checksum.json
+++ b/third_party/rust/string_cache/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".travis.yml":"dc24c2b07c61ee79ec6190cf2245f9522b86af8468301270fc3d65ffbbe3afd2","Cargo.toml":"54737ed24e861323b4aa09439d84d523126075a5f04c76e8b90107e1b74d6c24","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"9998bb7a1a14ca250c3571ae2beed5905824057359aef2c7f19c8f4aeedc996f","build.rs":"c9fd295a8a84459f29ba6e1460118efab8d02f875d95eccc36d7ca66876f6713","src/atom.rs":"fe85bb6aa6f40dc69ffe0537445ba5dd46f83e93bac95316178d72d01e5b8f7c","src/bench.rs":"c4738a6709ca77e99f174d6c0b640c72c20cbe49a10e4765e4df79882dfd2983","src/event.rs":"b97e45ed554583f7badb83fa751fc2260a87348dc7a4cd4fa00befe345cf7638","src/lib.rs":"0c546862d24fbfedba0192b0e52e00487a76b7a6de5b8a57daa07f108c21c4d9"},"package":"39cb4173bcbd1319da31faa5468a7e3870683d7a237150b0b0aaafd546f6ad12"}
\ No newline at end of file
+{"files":{".travis.yml":"dc24c2b07c61ee79ec6190cf2245f9522b86af8468301270fc3d65ffbbe3afd2","Cargo.toml":"57167143541db9e97ff783f9c4c0569fe120f83bd4c53d12ff34a088bd539248","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"9998bb7a1a14ca250c3571ae2beed5905824057359aef2c7f19c8f4aeedc996f","build.rs":"c9fd295a8a84459f29ba6e1460118efab8d02f875d95eccc36d7ca66876f6713","src/atom.rs":"4613a3226d95d666c5cd0f879305e27e2c20594b6257038065182c50ddc29bdd","src/bench.rs":"c4738a6709ca77e99f174d6c0b640c72c20cbe49a10e4765e4df79882dfd2983","src/event.rs":"b97e45ed554583f7badb83fa751fc2260a87348dc7a4cd4fa00befe345cf7638","src/lib.rs":"0c546862d24fbfedba0192b0e52e00487a76b7a6de5b8a57daa07f108c21c4d9"},"package":"25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"}
\ No newline at end of file
--- a/third_party/rust/string_cache/Cargo.toml
+++ b/third_party/rust/string_cache/Cargo.toml
@@ -7,43 +7,43 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "string_cache"
-version = "0.7.1"
+version = "0.7.3"
 authors = ["The Servo Project Developers"]
 build = "build.rs"
 description = "A string interning library for Rust, developed as part of the Servo project."
 documentation = "https://docs.rs/string_cache/"
 license = "MIT / Apache-2.0"
 repository = "https://github.com/servo/string-cache"
 
 [lib]
 name = "string_cache"
-[dependencies.debug_unreachable]
-version = "0.1.1"
-
 [dependencies.lazy_static]
 version = "1"
 
+[dependencies.new_debug_unreachable]
+version = "1.0"
+
 [dependencies.phf_shared]
 version = "0.7.4"
 
 [dependencies.precomputed-hash]
 version = "0.1"
 
 [dependencies.serde]
 version = "1"
 
 [dependencies.string_cache_shared]
 version = "0.3"
 [dev-dependencies.rand]
-version = "0.3"
+version = "0.4"
 [build-dependencies.string_cache_codegen]
 version = "0.4"
 
 [features]
 log-events = []
 unstable = []
--- a/third_party/rust/string_cache/src/atom.rs
+++ b/third_party/rust/string_cache/src/atom.rs
@@ -7,17 +7,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 #![allow(non_upper_case_globals)]
 
 use phf_shared;
 use serde::{Deserialize, Deserializer, Serialize, Serializer};
 
-#[allow(unused_imports)] use std::ascii::AsciiExt;
 use std::borrow::Cow;
 use std::cmp::Ordering::{self, Equal};
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::marker::PhantomData;
 use std::mem;
 use std::ops;
 use std::slice;
deleted file mode 100644
--- a/third_party/rust/unreachable-0.1.1/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{".travis.yml":"180cc837b1ea2ce0ed737c2e15208e83abf6f92291a77ed1ebcc564c628c2077","Cargo.toml":"cc09349f0610a327f3562a4c44b9c3889e5a9bf43c290ce436bfb98a4e66b0ed","README.md":"447088161e4b8c6060ae830d41ba2adf3cac2dbd8b1195c618b062878832be82","src/lib.rs":"2cb4bbb6a0c7058e49f5bbc0c1e2f208b5374cf70c495813401a357f9dfad188"},"package":"1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"}
\ No newline at end of file
deleted file mode 100644
--- a/third_party/rust/unreachable-0.1.1/.travis.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-language: rust
-sudo: false
-
-script:
-    - cargo build
-    - cargo test
-    - cargo bench --no-run
-    - cargo doc
-
-after_success:
-    - if [ "$TRAVIS_PULL_REQUEST" == false && test == "TRAVIS_BRANCH" == "master" ]; then
-    - curl https://raw.githubusercontent.com/reem/rust-gh-docs/master/make-docs.sh > docs.sh
-    - chmod u+x docs.sh
-    - ./docs.sh reem project-name
-
-env:
-  global:
-    secure: QPYL1XUr4CyK/2DXlsYC1eCpWRpyEiqQSd/FFVR+YdP/rOJ7AyAXQqPhfgjDBQwvc6E2fUiyYjoV/xe1a757DDeZKlgd8Lp20fSDwvNt/Ejx8ueh3h3kuOtgDpIGSKX/l+XC+ltDpzjhh7bowI2/fOEf+kE53jvu9i4PiLnKdlY=
-
deleted file mode 100644
--- a/third_party/rust/unreachable-0.1.1/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-
-name = "unreachable"
-version = "0.1.1"
-authors = ["Jonathan Reem <jonathan.reem@gmail.com>"]
-repository = "https://github.com/reem/rust-unreachable.git"
-description = "An unreachable code optimization hint in stable rust."
-readme = "README.md"
-license = "MIT"
-
-[dependencies.void]
-version = "1"
-default-features = false
deleted file mode 100644
--- a/third_party/rust/unreachable-0.1.1/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# unreachable
-
-> An unreachable code optimization hint in stable rust.
-
-## [Documentation](https://crates.fyi/crates/unreachable/0.1.1)
-
-## Usage