1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//! The bounds arithmetic every in-memory double in `tests/` shares.
//!
//! # Why this exists next to `src/test_device.rs` rather than inside it
//!
//! `src/test_device.rs` is `#[cfg(test)]`, and an integration test is a
//! separate crate that cannot see a `#[cfg(test)]` item. So the eleven
//! suites here each hand-rolled the arithmetic the shared device was
//! consolidated to own, and each of them re-introduced the divergence
//! that consolidation had removed:
//!
//! ```text
//! let s = offset as usize;
//! buf.copy_from_slice(&b[s..s + buf.len()]);
//! ```
//!
//! No bounds check at all, so a past-end read panicked inside the
//! double — which turns a caller's arithmetic bug into a crash in the
//! harness rather than an error the caller can be asserted against, and
//! means a test that wants to prove a wrapper REFUSES a wild offset
//! cannot be written with these devices at all. `tests/caching_wild_
//! offset.rs` had to declare a twelfth, "deliberately checked" double
//! for exactly that reason.
//!
//! The alternative was to publish the real one behind a
//! `#[cfg(feature = "test-support")]` module. That adds a feature and a
//! self dev-dependency to the manifest of a crate twelve siblings pin,
//! to ship test support nothing outside this repository consumes. One
//! file the suites share is the smaller change; the cost is that the
//! rule is stated twice, so both copies carry a test that pins it —
//! `tests/shared_double_bounds.rs` here, `src/test_device.rs::tests`
//! there.
use BlockRead;
use ;
/// Where `offset` lands in a buffer of `len` bytes — or the
/// [`Error::ShortRead`] that says the range does not fit, which always
/// reports `got: 0` because nothing is copied on that path.
///
/// The arithmetic is `u64` throughout, and the narrowing to `usize`
/// happens only *after* the bounds check has proved the range fits
/// inside `len` — rather than before it, where `offset as usize` would
/// turn a wild offset into a plausible one instead of refusing it, and
/// where `start + want` panicked with "attempt to add with overflow"
/// in a debug build, which is every `cargo test` run.
/// The read every double here shares: a past-end read is
/// [`Error::ShortRead`], never a panic, and a refused read leaves the
/// caller's buffer untouched.
/// The write, which carried the identical pair of lines. A device is
/// not a `Vec`: a write past the end grows nothing and is refused.
/// A read-only byte buffer — the plainest double there is, and the one
/// several suites need only in order to have *something* under the
/// device being tested.
;