Merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Coroiu Cristina 2018-06-12 12:19:21 +03:00
Родитель da355c78c8 0300566d26
Коммит 4b2243fe17
99 изменённых файлов: 2362 добавлений и 4419 удалений

61
Cargo.lock сгенерированный
Просмотреть файл

@ -558,14 +558,6 @@ dependencies = [
"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"
@ -1015,7 +1007,7 @@ dependencies = [
"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)",
]
@ -1041,7 +1033,7 @@ dependencies = [
"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)",
]
@ -1363,6 +1355,23 @@ dependencies = [
"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"
@ -1442,15 +1451,6 @@ 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"
@ -1864,11 +1864,11 @@ 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)",
@ -1909,7 +1909,6 @@ dependencies = [
"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)",
@ -1922,11 +1921,12 @@ dependencies = [
"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)",
@ -2216,14 +2216,6 @@ 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"
@ -2553,7 +2545,6 @@ dependencies = [
"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"
@ -2623,6 +2614,8 @@ dependencies = [
"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"
@ -2631,7 +2624,6 @@ dependencies = [
"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"
@ -2681,7 +2673,7 @@ dependencies = [
"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"
@ -2710,7 +2702,6 @@ dependencies = [
"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"

Просмотреть файл

@ -4,16 +4,24 @@
"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 = {
@ -38,7 +46,7 @@ const reducers = {
};
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;

Просмотреть файл

@ -6,23 +6,13 @@
"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.
@ -87,8 +77,6 @@ class HighlightersOverlay {
this.inspector.on("markupmutation", this.onMarkupMutation);
this.inspector.target.on("will-navigate", this.onWillNavigate);
this.loadGridHighlighterSettings();
EventEmitter.decorate(this);
}
@ -132,21 +120,6 @@ class HighlightersOverlay {
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.

Просмотреть файл

@ -1281,7 +1281,9 @@ FireForgetSkippable(uint32_t aSuspected, bool aRemoveChildless,
if (!aDeadline.IsNull()) {
if (aDeadline < now) {
// This slice overflowed the idle period.
idleDuration = aDeadline - startTimeStamp;
if (aDeadline > startTimeStamp) {
idleDuration = aDeadline - startTimeStamp;
}
} else {
idleDuration = duration;
}

Просмотреть файл

@ -52,9 +52,10 @@ ParentLayerCoord GetCurrentSpan(const MultiTouchInput& aEvent)
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;
}
@ -313,6 +314,9 @@ nsEventStatus GestureEventListener::HandleInputTouchMove()
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,
@ -388,7 +392,7 @@ nsEventStatus GestureEventListener::HandleInputTouchMove()
}
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;

Просмотреть файл

@ -150,10 +150,10 @@ private:
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.
@ -208,6 +208,16 @@ private:
*/
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

Просмотреть файл

@ -590,7 +590,9 @@ LoadInfoToParentLoadInfoForwarder(nsILoadInfo* aLoadInfo,
ParentLoadInfoForwarderArgs* aForwarderArgsOut)
{
if (!aLoadInfo) {
*aForwarderArgsOut = ParentLoadInfoForwarderArgs(false, void_t());
*aForwarderArgsOut = ParentLoadInfoForwarderArgs(false, void_t(),
nsILoadInfo::TAINTING_BASIC,
false);
return;
}
@ -600,9 +602,14 @@ LoadInfoToParentLoadInfoForwarder(nsILoadInfo* aLoadInfo,
ipcController = controller.ref().ToIPC();
}
uint32_t tainting = nsILoadInfo::TAINTING_BASIC;
Unused << aLoadInfo->GetTainting(&tainting);
*aForwarderArgsOut = ParentLoadInfoForwarderArgs(
aLoadInfo->GetAllowInsecureRedirectToDataURI(),
ipcController
ipcController,
tainting,
aLoadInfo->GetServiceWorkerTaintingSynthesized()
);
}
@ -627,6 +634,13 @@ MergeParentLoadInfoForwarder(ParentLoadInfoForwarderArgs const& aForwarderArgs,
ServiceWorkerDescriptor(controller.get_IPCServiceWorkerDescriptor()));
}
if (aForwarderArgs.serviceWorkerTaintingSynthesized()) {
aLoadInfo->SynthesizeServiceWorkerTainting(
static_cast<LoadTainting>(aForwarderArgs.tainting()));
} else {
aLoadInfo->MaybeIncreaseTainting(aForwarderArgs.tainting());
}
return NS_OK;
}

Просмотреть файл

@ -3595,6 +3595,7 @@ WorkerMain(void* arg)
sc->isWorker = true;
JS_SetContextPrivate(cx, sc);
JS_SetGrayGCRootsTracer(cx, TraceGrayRoots, nullptr);
SetWorkerContextOptions(cx);
JS::SetBuildIdOp(cx, ShellBuildId);

Просмотреть файл

@ -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);

Просмотреть файл

@ -5,23 +5,22 @@
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;
@ -299,13 +298,23 @@ public final class NotificationClient implements NotificationListener {
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) {
@ -328,6 +337,6 @@ public final class NotificationClient implements NotificationListener {
}
}
setForegroundNotificationLocked(null, null);
removeForegroundNotificationLocked();
}
}

Просмотреть файл

@ -18,15 +18,8 @@ public final class NotificationService extends Service {
@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;
}

Просмотреть файл

@ -993,12 +993,13 @@ interface nsILoadInfo : nsISupports
[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);

Просмотреть файл

@ -132,6 +132,14 @@ struct ParentLoadInfoForwarderArgs
// 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!

Просмотреть файл

@ -1 +1 @@
8232a58332dd
30a4b03cd9d1

Просмотреть файл

@ -8,8 +8,8 @@ MAINTAINER Franziskus Kiefer <franziskuskiefer@gmail.com>
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

Просмотреть файл

@ -178,7 +178,7 @@ loser:
SECKEY_DestroyPrivateKey(privKey);
}
if (data) {
PORT_Free(data);
PR_Free(data);
}
PORT_FreeArena(arena, PR_FALSE);

Просмотреть файл

@ -10,4 +10,3 @@
*/
#error "Do not include this header file."

Просмотреть файл

@ -36,6 +36,7 @@ CPPSRCS = \
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 \

Просмотреть файл

@ -68,6 +68,7 @@ static const uint16_t kManyExtensions[] = {
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),

Просмотреть файл

@ -37,6 +37,7 @@
'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',

Просмотреть файл

@ -104,15 +104,13 @@ TEST_P(TlsPaddingTest, LastByteOfPadWrong) {
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_);
@ -120,17 +118,33 @@ class RecordReplacer : public TlsRecordFilter {
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();

Просмотреть файл

@ -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

Просмотреть файл

@ -939,9 +939,9 @@ static bool ErrorIsNonFatal(PRErrorCode code) {
}
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);

Просмотреть файл

@ -410,7 +410,7 @@ bool TlsRecordFilter::Unprotect(const TlsRecordHeader& header,
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;
@ -418,8 +418,10 @@ bool TlsRecordFilter::Protect(const TlsRecordHeader& header,
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);
}

Просмотреть файл

@ -120,7 +120,8 @@ class TlsRecordFilter : public PacketFilter {
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
@ -506,6 +507,22 @@ class TlsClientHelloVersionChanger : public TlsHandshakeFilter {
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 {

Просмотреть файл

@ -33,7 +33,3 @@ ifdef NSS_BUILD_CAPI
DIRS += capi
endif
endif
#ifeq ($(OS_ARCH), Darwin)
#DIRS += nssmkey
#endif

Просмотреть файл

@ -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

Просмотреть файл

@ -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.

Просмотреть файл

@ -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

Просмотреть файл

@ -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;

Просмотреть файл

@ -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 =

Просмотреть файл

@ -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"

Просмотреть файл

@ -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

Просмотреть файл

@ -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";

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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 */
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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 */
};

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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 */
};

Просмотреть файл

@ -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 */
};

Просмотреть файл

@ -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:
;+*;
;+};

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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;

Просмотреть файл

@ -16,14 +16,11 @@
#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.
@ -168,7 +165,7 @@ dsa_NewKeyExtended(const PQGParams *params, const SECItem *seed,
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;
@ -213,8 +210,9 @@ cleanup:
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;
@ -321,6 +319,7 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
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;
@ -364,6 +363,7 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
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));
@ -372,6 +372,7 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
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.
*/
@ -397,14 +398,28 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
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.
@ -438,7 +453,7 @@ cleanup:
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;

Просмотреть файл

@ -653,6 +653,7 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
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 };
@ -674,6 +675,7 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
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)) {
@ -700,6 +702,7 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
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);
@ -815,12 +818,25 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
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);
@ -858,6 +874,7 @@ cleanup:
mp_clear(&s);
mp_clear(&n);
mp_clear(&t);
mp_clear(&ar);
if (t2) {
PORT_Free(t2);

Просмотреть файл

@ -884,7 +884,9 @@ sec_PKCS12AddAttributeToBag(SEC_PKCS12ExportContext *p12ctxt,
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;
}
@ -1589,6 +1591,7 @@ sec_pkcs12_encoder_start_context(SEC_PKCS12ExportContext *p12exp)
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 */

Просмотреть файл

@ -2577,14 +2577,13 @@ ReadDBSubjectEntry(NSSLOWCERTCertDBHandle *handle, SECItem *derSubject)
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) {

Просмотреть файл

@ -138,12 +138,14 @@ sftkdb_decodeCipherText(SECItem *cipherText, sftkCipherValue *cipherValue)
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);

Просмотреть файл

@ -724,13 +724,16 @@ dtls_FragmentHandshake(sslSocket *ss, DTLSQueuedMessage *msg)
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

Просмотреть файл

@ -243,6 +243,28 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
*/
#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

Просмотреть файл

@ -1476,6 +1476,13 @@ ssl3_SetupBothPendingCipherSpecs(sslSocket *ss)
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;
@ -2272,7 +2279,7 @@ ssl_ProtectNextRecord(sslSocket *ss, ssl3CipherSpec *spec, SSL3ContentType type,
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) {
@ -12147,6 +12154,11 @@ ssl3_GetCipherSpec(sslSocket *ss, SSL3Ciphertext *cText)
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
@ -12176,6 +12188,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
PRBool isTLS;
DTLSEpoch epoch;
ssl3CipherSpec *spec = NULL;
PRUint16 recordSizeLimit;
PRBool outOfOrderSpec = PR_FALSE;
SSL3ContentType rType;
sslBuffer *plaintext = &ss->gs.buf;
@ -12230,12 +12243,20 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
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;
@ -12294,7 +12315,10 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
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;
}
@ -12330,7 +12354,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
}
/* 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);

Просмотреть файл

@ -50,6 +50,7 @@ static const ssl3ExtensionHandler clientHelloHandlers[] = {
{ 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 }
};
@ -68,6 +69,7 @@ static const ssl3ExtensionHandler serverHelloHandlersTLS[] = {
{ 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 }
};
@ -134,6 +136,7 @@ static const sslExtensionBuilder clientHelloSendersTLS[] =
{ 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 }

Просмотреть файл

@ -98,6 +98,9 @@ struct TLSExtensionDataStr {
/* 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 {

Просмотреть файл

@ -1868,3 +1868,67 @@ ssl_HandleSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData,
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;
}

Просмотреть файл

@ -119,4 +119,11 @@ SECStatus ssl_SendSupportedGroupsXtn(const sslSocket *ss,
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

Просмотреть файл

@ -236,6 +236,7 @@ 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;

Просмотреть файл

@ -55,6 +55,7 @@ static const sslSocketOps ssl_secure_ops = { /* SSL. */
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,
@ -803,6 +804,15 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRIntn val)
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;
@ -944,6 +954,9 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRIntn *pVal)
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;
@ -1067,6 +1080,9 @@ SSL_OptionGetDefault(PRInt32 which, PRIntn *pVal)
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;
@ -1252,6 +1268,14 @@ SSL_OptionSetDefault(PRInt32 which, PRIntn val)
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;

Просмотреть файл

@ -143,6 +143,7 @@ ssl_CreateCipherSpec(sslSocket *ss, CipherSpecDirection direction)
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));

Просмотреть файл

@ -170,6 +170,10 @@ struct ssl3CipherSpecStr {
/* 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,

Просмотреть файл

@ -432,6 +432,7 @@ typedef enum {
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,
@ -454,7 +455,7 @@ typedef enum {
/* 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 {

Просмотреть файл

@ -3254,6 +3254,17 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
}
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;
}
@ -4746,7 +4757,8 @@ static const struct {
{ 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
@ -5015,6 +5027,16 @@ tls13_UnprotectRecord(sslSocket *ss,
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. */

Просмотреть файл

@ -32,7 +32,7 @@ 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" }
@ -50,7 +50,7 @@ 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"

Просмотреть файл

@ -31,10 +31,11 @@ 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;

Просмотреть файл

@ -19,7 +19,8 @@ ${helpers.predefined_type(
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

Просмотреть файл

@ -2501,6 +2501,7 @@ pub mod style_structs {
/// 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(),
@ -2699,6 +2700,26 @@ impl ComputedValues {
/// 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")]
@ -2937,26 +2958,6 @@ 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":

Просмотреть файл

@ -6,7 +6,7 @@
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};
@ -391,14 +391,14 @@ impl LengthOrPercentage {
// 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(),
),
}
}

Просмотреть файл

@ -3,10 +3,10 @@
* 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);

Просмотреть файл

@ -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"}

18
third_party/rust/debug_unreachable/Cargo.toml поставляемый
Просмотреть файл

@ -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"

24
third_party/rust/debug_unreachable/README.md поставляемый
Просмотреть файл

@ -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

1
third_party/rust/new-ordered-float/.cargo-checksum.json поставляемый Normal file
Просмотреть файл

@ -0,0 +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"}

Просмотреть файл

@ -5,7 +5,5 @@ env:
matrix:
- FEATURES=
- FEATURES="serde"
- FEATURES="rustc-serialize"
- FEATURES="serde rustc-serialize"
script:
- cargo test -v --features "$FEATURES"

34
third_party/rust/new-ordered-float/Cargo.toml поставляемый Normal file
Просмотреть файл

@ -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"

25
third_party/rust/new-ordered-float/LICENSE-MIT поставляемый Normal file
Просмотреть файл

@ -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.

27
third_party/rust/new-ordered-float/README.md поставляемый Normal file
Просмотреть файл

@ -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

Просмотреть файл

@ -15,7 +15,18 @@ use std::fmt;
use std::io;
use std::mem;
use unreachable::unreachable;
use num_traits::Float;
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;
@ -30,7 +41,7 @@ const CANONICAL_ZERO_BITS: u64 = 0x0u64;
///
/// 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)]
#[derive(Debug, Default, Clone, Copy)]
pub struct OrderedFloat<T: Float>(pub T);
impl<T: Float> OrderedFloat<T> {
@ -55,13 +66,21 @@ impl<T: Float> AsMut<T> for OrderedFloat<T> {
}
}
impl<T: Float + PartialOrd> Ord for OrderedFloat<T> {
fn cmp(&self, other: &OrderedFloat<T>) -> Ordering {
match self.partial_cmp(&other) {
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 self.as_ref().is_nan() {
if other.as_ref().is_nan() {
if lhs.is_nan() {
if rhs.is_nan() {
Ordering::Equal
} else {
Ordering::Greater
@ -77,7 +96,7 @@ impl<T: Float + PartialOrd> Ord for OrderedFloat<T> {
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 }
other.as_ref().is_nan()
} else if other.as_ref().is_nan() {
false
} else {
@ -141,43 +160,43 @@ impl<T: Float + PartialEq> Eq for OrderedFloat<T> {}
///
/// A NaN value cannot be stored in this type.
#[derive(PartialOrd, PartialEq, Debug, Default, Clone, Copy)]
pub struct NotNaN<T: Float>(T);
pub struct NotNan<T: Float>(T);
impl<T: Float> NotNaN<T> {
/// Create a NotNaN value.
impl<T: Float> NotNan<T> {
/// Create a NotNan value.
///
/// Returns Err if val is NaN
pub fn new(val: T) -> Result<Self, FloatIsNaN> {
pub fn new(val: T) -> Result<Self, FloatIsNan> {
match val {
ref val if val.is_nan() => Err(FloatIsNaN),
val => Ok(NotNaN(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
/// 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)
NotNan(val)
}
/// Get the value out.
pub fn into_inner(self) -> T {
let NotNaN(val) = self;
let NotNan(val) = self;
val
}
}
impl<T: Float> AsRef<T> for NotNaN<T> {
impl<T: Float> AsRef<T> for NotNan<T> {
fn as_ref(&self) -> &T {
let NotNaN(ref val) = *self;
let NotNan(ref val) = *self;
val
}
}
impl<T: Float + PartialOrd> Ord for NotNaN<T> {
fn cmp(&self, other: &NotNaN<T>) -> Ordering {
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() },
@ -185,41 +204,41 @@ impl<T: Float + PartialOrd> Ord for NotNaN<T> {
}
}
impl<T: Float> Hash for NotNaN<T> {
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> {
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> {
impl Into<f32> for NotNan<f32> {
fn into(self) -> f32 {
self.into_inner()
}
}
impl Into<f64> for NotNaN<f64> {
impl Into<f64> for NotNan<f64> {
fn into(self) -> f64 {
self.into_inner()
}
}
/// Creates a NotNaN value from a Float.
/// 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> {
impl<T: Float> From<T> for NotNan<T> {
fn from(v: T) -> Self {
assert!(!v.is_nan());
NotNaN(v)
NotNan(v)
}
}
impl<T: Float> Deref for NotNaN<T> {
impl<T: Float> Deref for NotNan<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
@ -227,36 +246,36 @@ impl<T: Float> Deref for NotNaN<T> {
}
}
impl<T: Float + PartialEq> Eq for NotNaN<T> {}
impl<T: Float + PartialEq> Eq for NotNan<T> {}
impl<T: Float> Add for NotNaN<T> {
impl<T: Float> Add for NotNan<T> {
type Output = Self;
fn add(self, other: Self) -> Self {
NotNaN(self.0 + other.0)
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> {
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")
NotNan::new(self.0 + other).expect("Addition resulted in NaN")
}
}
impl AddAssign for NotNaN<f64> {
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> {
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")
@ -266,7 +285,7 @@ impl AddAssign for NotNaN<f32> {
/// Adds a float directly.
///
/// Panics if the provided value is NaN or the computation results in NaN
impl AddAssign<f64> for NotNaN<f64> {
impl AddAssign<f64> for NotNan<f64> {
fn add_assign(&mut self, other: f64) {
assert!(!other.is_nan());
self.0 += other;
@ -277,7 +296,7 @@ impl AddAssign<f64> for NotNaN<f64> {
/// Adds a float directly.
///
/// Panics if the provided value is NaN.
impl AddAssign<f32> for NotNaN<f32> {
impl AddAssign<f32> for NotNan<f32> {
fn add_assign(&mut self, other: f32) {
assert!(!other.is_nan());
self.0 += other;
@ -285,34 +304,34 @@ impl AddAssign<f32> for NotNaN<f32> {
}
}
impl<T: Float> Sub for NotNaN<T> {
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")
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> {
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")
NotNan::new(self.0 - other).expect("Subtraction resulted in NaN")
}
}
impl SubAssign for NotNaN<f64> {
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> {
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")
@ -322,7 +341,7 @@ impl SubAssign for NotNaN<f32> {
/// Subtracts a float directly.
///
/// Panics if the provided value is NaN or the computation results in NaN
impl SubAssign<f64> for NotNaN<f64> {
impl SubAssign<f64> for NotNan<f64> {
fn sub_assign(&mut self, other: f64) {
assert!(!other.is_nan());
self.0 -= other;
@ -333,7 +352,7 @@ impl SubAssign<f64> for NotNaN<f64> {
/// Subtracts a float directly.
///
/// Panics if the provided value is NaN or the computation results in NaN
impl SubAssign<f32> for NotNaN<f32> {
impl SubAssign<f32> for NotNan<f32> {
fn sub_assign(&mut self, other: f32) {
assert!(!other.is_nan());
self.0 -= other;
@ -341,34 +360,34 @@ impl SubAssign<f32> for NotNaN<f32> {
}
}
impl<T: Float> Mul for NotNaN<T> {
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")
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> {
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")
NotNan::new(self.0 * other).expect("Multiplication resulted in NaN")
}
}
impl MulAssign for NotNaN<f64> {
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> {
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")
@ -378,7 +397,7 @@ impl MulAssign for NotNaN<f32> {
/// Multiplies a float directly.
///
/// Panics if the provided value is NaN.
impl MulAssign<f64> for NotNaN<f64> {
impl MulAssign<f64> for NotNan<f64> {
fn mul_assign(&mut self, other: f64) {
assert!(!other.is_nan());
self.0 *= other;
@ -388,7 +407,7 @@ impl MulAssign<f64> for NotNaN<f64> {
/// Multiplies a float directly.
///
/// Panics if the provided value is NaN or the computation results in NaN
impl MulAssign<f32> for NotNaN<f32> {
impl MulAssign<f32> for NotNan<f32> {
fn mul_assign(&mut self, other: f32) {
assert!(!other.is_nan());
self.0 *= other;
@ -396,34 +415,34 @@ impl MulAssign<f32> for NotNaN<f32> {
}
}
impl<T: Float> Div for NotNaN<T> {
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")
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> {
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")
NotNan::new(self.0 / other).expect("Division resulted in NaN")
}
}
impl DivAssign for NotNaN<f64> {
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> {
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")
@ -433,7 +452,7 @@ impl DivAssign for NotNaN<f32> {
/// Divides a float directly.
///
/// Panics if the provided value is NaN or the computation results in NaN
impl DivAssign<f64> for NotNaN<f64> {
impl DivAssign<f64> for NotNan<f64> {
fn div_assign(&mut self, other: f64) {
assert!(!other.is_nan());
self.0 /= other;
@ -444,7 +463,7 @@ impl DivAssign<f64> for NotNaN<f64> {
/// Divides a float directly.
///
/// Panics if the provided value is NaN or the computation results in NaN
impl DivAssign<f32> for NotNaN<f32> {
impl DivAssign<f32> for NotNan<f32> {
fn div_assign(&mut self, other: f32) {
assert!(!other.is_nan());
self.0 /= other;
@ -452,34 +471,34 @@ impl DivAssign<f32> for NotNaN<f32> {
}
}
impl<T: Float> Rem for NotNaN<T> {
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")
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> {
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")
NotNan::new(self.0 % other).expect("Rem resulted in NaN")
}
}
impl RemAssign for NotNaN<f64> {
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> {
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")
@ -489,7 +508,7 @@ impl RemAssign for NotNaN<f32> {
/// Calculates `%=` with a float directly.
///
/// Panics if the provided value is NaN or the computation results in NaN
impl RemAssign<f64> for NotNaN<f64> {
impl RemAssign<f64> for NotNan<f64> {
fn rem_assign(&mut self, other: f64) {
assert!(!other.is_nan());
self.0 %= other;
@ -500,7 +519,7 @@ impl RemAssign<f64> for NotNaN<f64> {
/// Calculates `%=` with a float directly.
///
/// Panics if the provided value is NaN or the computation results in NaN
impl RemAssign<f32> for NotNaN<f32> {
impl RemAssign<f32> for NotNan<f32> {
fn rem_assign(&mut self, other: f32) {
assert!(!other.is_nan());
self.0 %= other;
@ -508,31 +527,31 @@ impl RemAssign<f32> for NotNaN<f32> {
}
}
impl<T: Float> Neg for NotNaN<T> {
impl<T: Float> Neg for NotNan<T> {
type Output = Self;
fn neg(self) -> Self {
NotNaN::new(-self.0).expect("Negation resulted in NaN")
NotNan::new(-self.0).expect("Negation resulted in NaN")
}
}
/// An error indicating an attempt to construct NotNaN from a NaN
/// An error indicating an attempt to construct NotNan from a NaN
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct FloatIsNaN;
pub struct FloatIsNan;
impl Error for FloatIsNaN {
impl Error for FloatIsNan {
fn description(&self) -> &str {
return "NotNaN constructed with NaN";
"NotNan constructed with NaN"
}
}
impl fmt::Display for FloatIsNaN {
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 {
impl Into<io::Error> for FloatIsNan {
fn into(self) -> io::Error {
io::Error::new(io::ErrorKind::InvalidInput, self)
}
@ -559,36 +578,104 @@ fn raw_double_bits<F: Float>(f: &F) -> u64 {
(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 + Zero> Zero for NotNan<T> {
fn zero() -> Self { NotNan(T::zero()) }
impl<T: Float + Encodable> Encodable for OrderedFloat<T> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
self.0.encode(s)
}
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())
}
impl<T: Float + Decodable> Decodable for OrderedFloat<T> {
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
T::decode(d).map(OrderedFloat)
}
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")
}
impl<T: Float + Encodable> Encodable for NotNaN<T> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
self.0.encode(s)
}
}
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 + 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())))
}
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())
}
}
@ -596,34 +683,59 @@ mod impl_rustc {
mod impl_serde {
extern crate serde;
use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
use self::serde::de::Error;
use super::{OrderedFloat, NotNaN};
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: &mut S) -> Result<(), S::Error> {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, 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> {
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: &mut S) -> Result<(), S::Error> {
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<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"))
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)");
}
}

524
third_party/rust/new-ordered-float/tests/test.rs поставляемый Normal file
Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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);
}

1
third_party/rust/new_debug_unreachable/.cargo-checksum.json поставляемый Normal file
Просмотреть файл

@ -0,0 +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"}

Просмотреть файл

27
third_party/rust/new_debug_unreachable/Cargo.toml поставляемый Normal file
Просмотреть файл

@ -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"

25
third_party/rust/new_debug_unreachable/LICENSE-MIT поставляемый Normal file
Просмотреть файл

@ -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.

27
third_party/rust/new_debug_unreachable/README.md поставляемый Normal file
Просмотреть файл

@ -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

Просмотреть файл

@ -1,5 +1,7 @@
#![deny(missing_docs, warnings)]
#![no_std]
//! `panic!()` in debug builds, optimization hint in release.
extern crate unreachable;
@ -12,10 +14,10 @@ pub use unreachable::unreachable as __unreachable;
macro_rules! debug_unreachable {
() => { debug_unreachable!("entered unreachable code") };
($e:expr) => {
if cfg!(ndebug) {
$crate::__unreachable()
} else {
if cfg!(debug_assertions) {
panic!($e);
} else {
$crate::__unreachable()
}
}
}

Просмотреть файл

Просмотреть файл

@ -1 +0,0 @@
{"files":{".travis.yml":"836b2a8c7fc40a6b7fafc7ae6d4cc0cfc5e8cd1ce9023843ed471f1d5f41af8b","Cargo.toml":"fa8d70d0447555cbda365af477d0bb43fefa964562d76b262ec67f0f2e658bd4","README.md":"10c54822e3ec242a69f9abcbf15cec555f666280336b0e650d6f008c982adc7c","src/lib.rs":"d0dbfdac8aa6d7be0bf0d4e443a197b88f73262f88670df531c84993aa4bc45c","tests/test.rs":"f339d8b594fb450903349fba93d04d91322a2c947b5d5ebb475ca10ae04a0eb2"},"package":"da12c96037889ae0be29dd2bdd260e5a62a7df24e6466d5a15bb8131c1c200a8"}

17
third_party/rust/ordered-float/Cargo.toml поставляемый
Просмотреть файл

@ -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"

15
third_party/rust/ordered-float/README.md поставляемый
Просмотреть файл

@ -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

226
third_party/rust/ordered-float/tests/test.rs поставляемый
Просмотреть файл

@ -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);
}
}

Просмотреть файл

@ -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"}
{"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"}

10
third_party/rust/string_cache/Cargo.toml поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
[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."
@ -22,12 +22,12 @@ 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"
@ -40,7 +40,7 @@ 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"

1
third_party/rust/string_cache/src/atom.rs поставляемый
Просмотреть файл

@ -12,7 +12,6 @@
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;

Просмотреть файл

@ -1 +0,0 @@
{"files":{".travis.yml":"180cc837b1ea2ce0ed737c2e15208e83abf6f92291a77ed1ebcc564c628c2077","Cargo.toml":"cc09349f0610a327f3562a4c44b9c3889e5a9bf43c290ce436bfb98a4e66b0ed","README.md":"447088161e4b8c6060ae830d41ba2adf3cac2dbd8b1195c618b062878832be82","src/lib.rs":"2cb4bbb6a0c7058e49f5bbc0c1e2f208b5374cf70c495813401a357f9dfad188"},"package":"1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"}

Просмотреть файл

@ -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=

13
third_party/rust/unreachable-0.1.1/Cargo.toml поставляемый
Просмотреть файл

@ -1,13 +0,0 @@
[package]
name = "unreachable"
version = "0.1.1"
authors = ["Jonathan Reem <jonathan.reem@gmail.com>"]
repository = "https://github.com/reem/rust-unreachable.git"
description = "An unreachable code optimization hint in stable rust."
readme = "README.md"
license = "MIT"
[dependencies.void]
version = "1"
default-features = false

24
third_party/rust/unreachable-0.1.1/README.md поставляемый
Просмотреть файл

@ -1,24 +0,0 @@
# unreachable
> An unreachable code optimization hint in stable rust.
## [Documentation](https://crates.fyi/crates/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]
unreachable = "0.1"
```
## Author
[Jonathan Reem](https://medium.com/@jreem) is the primary author and maintainer of unreachable.
## License
MIT

77
third_party/rust/unreachable-0.1.1/src/lib.rs поставляемый
Просмотреть файл

@ -1,77 +0,0 @@
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
//! # unreachable
//!
//! An unreachable code optimization hint in stable rust, and some useful
//! extension traits for `Option` and `Result`.
//!
#![no_std]
extern crate void;
use core::mem;
/// Hint to the optimizer that any code path which calls this function is
/// statically unreachable and can be removed.
///
/// Calling this function in reachable code invokes undefined behavior. Be
/// very, very sure this is what you want; often, a simple `panic!` is more
/// suitable.
#[inline]
pub unsafe fn unreachable() -> ! {
let x: &void::Void = mem::transmute(1usize);
void::unreachable(*x)
}
/// An extension trait for `Option<T>` providing unchecked unwrapping methods.
pub trait UncheckedOptionExt<T> {
/// Get the value out of this Option without checking for None.
unsafe fn unchecked_unwrap(self) -> T;
/// Assert that this Option is a None to the optimizer.
unsafe fn unchecked_unwrap_none(self);
}
/// An extension trait for `Result<T, E>` providing unchecked unwrapping methods.
pub trait UncheckedResultExt<T, E> {
/// Get the value out of this Result without checking for Err.
unsafe fn unchecked_unwrap_ok(self) -> T;
/// Get the error out of this Result without checking for Ok.
unsafe fn unchecked_unwrap_err(self) -> E;
}
impl<T> UncheckedOptionExt<T> for Option<T> {
unsafe fn unchecked_unwrap(self) -> T {
match self {
Some(x) => x,
None => unreachable()
}
}
unsafe fn unchecked_unwrap_none(self) {
match self {
Some(_) => unreachable(),
None => ()
}
}
}
impl<T, E> UncheckedResultExt<T, E> for Result<T, E> {
unsafe fn unchecked_unwrap_ok(self) -> T {
match self {
Ok(x) => x,
Err(_) => unreachable()
}
}
unsafe fn unchecked_unwrap_err(self) -> E {
match self {
Ok(_) => unreachable(),
Err(e) => e
}
}
}