Merge mozilla-inbound to mozilla-central a=merge
authorCoroiu Cristina <ccoroiu@mozilla.com>
Tue, 12 Jun 2018 12:19:21 +0300
changeset 422329 87b46cd1c941782b75fcaa6b311bd9d7bd7f2120
parent 422328 ffdeb96ca6d01019a4f8414ae21d1ac6dc51edbd (current diff)
parent 422315 def346f39b1d0427cc62676dfd470e95d6ed015f (diff)
child 422330 f69e46cd335123845b2535b46308c4959cfb65cc
child 422331 af37f60c83d59e82e557f9065c0fff206bc14aa2
child 422350 937e4ecdc133d6d7ff859174c0ec85a680ddc66c
push id104217
push userccoroiu@mozilla.com
push dateTue, 12 Jun 2018 09:27:15 +0000
treeherdermozilla-inbound@f69e46cd3351 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone62.0a1
first release with
nightly linux32
87b46cd1c941 / 62.0a1 / 20180612100037 / files
nightly linux64
87b46cd1c941 / 62.0a1 / 20180612100037 / files
nightly mac
87b46cd1c941 / 62.0a1 / 20180612100037 / files
nightly win32
87b46cd1c941 / 62.0a1 / 20180612100037 / files
nightly win64
87b46cd1c941 / 62.0a1 / 20180612100037 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-inbound to mozilla-central a=merge
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
+++ /de