Skip to content

Commit 27a68f4

Browse files
authored
Add missing safety documentation and assertions for testing and fuzzing (#128)
1 parent 06b0d89 commit 27a68f4

File tree

5 files changed

+38
-25
lines changed

5 files changed

+38
-25
lines changed

lib/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66

77
- Add `BASE32_NOPAD_NOCASE` and `BASE32_NOPAD_VISUAL`
88

9+
### Patch
10+
11+
- Add missing safety documentation and assertions for testing and fuzzing
12+
- Move lints from `src/lib.rs` to `Cargo.toml` to ignore MSRV restrictions
13+
914
## 2.7.0
1015

1116
### Minor

lib/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,13 @@ rustdoc-args = ["--cfg=docsrs"]
2121
default = ["std"]
2222
alloc = []
2323
std = ["alloc"]
24+
25+
[lints]
26+
clippy.undocumented-unsafe-blocks = "warn"
27+
rust.elided-lifetimes-in-paths = "warn"
28+
rust.let-underscore-drop = "warn"
29+
rust.missing-debug-implementations = "warn"
30+
rust.missing-docs = "warn"
31+
rust.unreachable-pub = "warn"
32+
rust.unsafe-op-in-unsafe-fn = "warn"
33+
rust.unused-results = "warn"

lib/benches/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Library benchmarks
2+
13
#![feature(test)]
24

35
extern crate test;

lib/src/lib.rs

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -145,21 +145,6 @@
145145
146146
#![no_std]
147147
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
148-
// TODO: This list up to warn(clippy::pedantic) should ideally use a lint group.
149-
#![warn(elided_lifetimes_in_paths)]
150-
// TODO(msrv): #![warn(let_underscore_drop)]
151-
#![warn(missing_debug_implementations)]
152-
#![warn(missing_docs)]
153-
#![warn(unreachable_pub)]
154-
// TODO(msrv): #![warn(unsafe_op_in_unsafe_fn)]
155-
#![warn(unused_results)]
156-
#![allow(unused_unsafe)] // TODO(msrv)
157-
#![warn(clippy::pedantic)]
158-
#![allow(clippy::assigning_clones)] // TODO(msrv)
159-
#![allow(clippy::doc_markdown)]
160-
#![allow(clippy::enum_glob_use)]
161-
#![allow(clippy::similar_names)]
162-
#![allow(clippy::uninlined_format_args)] // TODO(msrv)
163148

164149
#[cfg(feature = "alloc")]
165150
extern crate alloc;
@@ -175,6 +160,7 @@ use alloc::vec;
175160
#[cfg(feature = "alloc")]
176161
use alloc::vec::Vec;
177162
use core::convert::TryInto;
163+
use core::debug_assert as safety_assert;
178164

179165
macro_rules! check {
180166
($e: expr, $c: expr) => {
@@ -255,13 +241,15 @@ macro_rules! dispatch {
255241
($body: expr) => { $body };
256242
}
257243

258-
unsafe fn chunk_unchecked<T>(x: &[T], n: usize, i: usize) -> &[T] {
259-
debug_assert!((i + 1) * n <= x.len());
244+
fn chunk_unchecked<T>(x: &[T], n: usize, i: usize) -> &[T] {
245+
safety_assert!((i + 1) * n <= x.len());
246+
// SAFETY: Ensured by correctness requirements (and asserted above).
260247
unsafe { core::slice::from_raw_parts(x.as_ptr().add(n * i), n) }
261248
}
262249

263-
unsafe fn chunk_mut_unchecked<T>(x: &mut [T], n: usize, i: usize) -> &mut [T] {
264-
debug_assert!((i + 1) * n <= x.len());
250+
fn chunk_mut_unchecked<T>(x: &mut [T], n: usize, i: usize) -> &mut [T] {
251+
safety_assert!((i + 1) * n <= x.len());
252+
// SAFETY: Ensured by correctness requirements (and asserted above).
265253
unsafe { core::slice::from_raw_parts_mut(x.as_mut_ptr().add(n * i), n) }
266254
}
267255

@@ -412,8 +400,8 @@ fn encode_mut<B: Static<usize>, M: Static<bool>>(
412400
_ => 1,
413401
};
414402
vectorize(n, bs, |i| {
415-
let input = unsafe { chunk_unchecked(input, enc, i) };
416-
let output = unsafe { chunk_mut_unchecked(output, dec, i) };
403+
let input = chunk_unchecked(input, enc, i);
404+
let output = chunk_mut_unchecked(output, dec, i);
417405
encode_block(bit, msb, symbols, input, output);
418406
});
419407
encode_block(bit, msb, symbols, &input[enc * n ..], &mut output[dec * n ..]);
@@ -451,8 +439,8 @@ fn decode_mut<B: Static<usize>, M: Static<bool>>(
451439
let dec = dec(bit.val());
452440
let n = input.len() / dec;
453441
for i in 0 .. n {
454-
let input = unsafe { chunk_unchecked(input, dec, i) };
455-
let output = unsafe { chunk_mut_unchecked(output, enc, i) };
442+
let input = chunk_unchecked(input, dec, i);
443+
let output = chunk_mut_unchecked(output, enc, i);
456444
decode_block(bit, msb, values, input, output).map_err(|e| dec * i + e)?;
457445
}
458446
decode_block(bit, msb, values, &input[dec * n ..], &mut output[enc * n ..])
@@ -559,8 +547,8 @@ fn encode_wrap_mut<
559547
let olen = dec - end.len();
560548
let n = input.len() / enc;
561549
for i in 0 .. n {
562-
let input = unsafe { chunk_unchecked(input, enc, i) };
563-
let output = unsafe { chunk_mut_unchecked(output, dec, i) };
550+
let input = chunk_unchecked(input, enc, i);
551+
let output = chunk_mut_unchecked(output, dec, i);
564552
encode_base(bit, msb, symbols, input, &mut output[.. olen]);
565553
output[olen ..].copy_from_slice(end);
566554
}
@@ -1324,10 +1312,12 @@ impl Encoding {
13241312
/// ```
13251313
#[cfg(feature = "alloc")]
13261314
pub fn encode_append(&self, input: &[u8], output: &mut String) {
1315+
// SAFETY: Ensured by correctness guarantees of encode_mut (and asserted below).
13271316
let output = unsafe { output.as_mut_vec() };
13281317
let output_len = output.len();
13291318
output.resize(output_len + self.encode_len(input.len()), 0u8);
13301319
self.encode_mut(input, &mut output[output_len ..]);
1320+
safety_assert!(output[output_len ..].is_ascii());
13311321
}
13321322

13331323
/// Returns an object to encode a fragmented input and append it to `output`
@@ -1369,6 +1359,8 @@ impl Encoding {
13691359
for input in input.chunks(buffer.len() / dec * enc) {
13701360
let buffer = &mut buffer[.. self.encode_len(input.len())];
13711361
self.encode_mut(input, buffer);
1362+
safety_assert!(buffer.is_ascii());
1363+
// SAFETY: Ensured by correctness guarantees of encode_mut (and asserted above).
13721364
output.write_str(unsafe { core::str::from_utf8_unchecked(buffer) })?;
13731365
}
13741366
Ok(())
@@ -1403,6 +1395,8 @@ impl Encoding {
14031395
pub fn encode(&self, input: &[u8]) -> String {
14041396
let mut output = vec![0u8; self.encode_len(input.len())];
14051397
self.encode_mut(input, &mut output);
1398+
safety_assert!(output.is_ascii());
1399+
// SAFETY: Ensured by correctness guarantees of encode_mut (and asserted above).
14061400
unsafe { String::from_utf8_unchecked(output) }
14071401
}
14081402

lib/tests/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Library tests
2+
13
use data_encoding::DecodeKind::*;
24
use data_encoding::{DecodeError, Encoding, Specification};
35

0 commit comments

Comments
 (0)