Skip to content

Commit

Permalink
Merge pull request #2 from nyris/feature/fuzzing
Browse files Browse the repository at this point in the history
Add fuzzing support
  • Loading branch information
sunsided authored Apr 7, 2023
2 parents 7281f16 + 15df438 commit c871fe3
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 4 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
This project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

### Changed

- `from_bytes_ref`, `as_uuid` and `is_empty` are now `const`.

### Internal

- Added fuzzing targets.

## 0.1.0 - 2023-04-07

### Added
Expand Down
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "shortguid"
version = "0.1.0"
version = "0.2.0-unstable"
edition = "2021"
license = "EUPL-1.2"
description = "Short URL-safe Base64 encoded UUIDs"
Expand All @@ -10,5 +10,9 @@ readme = "README.md"
rust-version = "1.67.1"

[dependencies]
arbitrary = { version = "1.3.0", optional = true }
base64 = "0.21.0"
uuid = "1.3.0"

[features]
arbitrary = ["uuid/arbitrary", "arbitrary/derive"]
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,13 @@ fn it_works() {
assert_eq!(short_guid_3, uuid);
}
```

## Fuzzing

This uses `cargo-fuzz`. See `fuzz/fuzzers` for the available fuzzing scripts. To run, use an invocation like these:

```
cargo +nightly fuzz run roundtrip
cargo +nightly fuzz run decode_random
cargo +nightly fuzz run encode_random
```
4 changes: 4 additions & 0 deletions fuzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
target
corpus
artifacts
coverage
131 changes: 131 additions & 0 deletions fuzz/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[package]
name = "shortguid-fuzz"
version = "0.0.0"
publish = false
edition = "2021"

[package.metadata]
cargo-fuzz = true

[dependencies]
libfuzzer-sys = "0.4.6"

[dependencies.shortguid]
path = ".."
features = ["arbitrary"]

# Prevent this from interfering with workspaces
[workspace]
members = ["."]

[profile.release]
debug = 1

[[bin]]
name = "decode_random"
path = "fuzz_targets/decode_random.rs"
test = false
doc = false

[[bin]]
name = "encode_random"
path = "fuzz_targets/encode_random.rs"
test = false
doc = false

[[bin]]
name = "roundtrip"
path = "fuzz_targets/roundtrip.rs"
test = false
doc = false
10 changes: 10 additions & 0 deletions fuzz/fuzz_targets/decode_random.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![no_main]

use libfuzzer_sys::fuzz_target;
use shortguid::ShortGuid;

fuzz_target!(|id: ShortGuid| {
let str = id.to_string();
let id2 = ShortGuid::try_parse(str).expect("decoding should work");
assert_eq!(id, id2);
});
11 changes: 11 additions & 0 deletions fuzz/fuzz_targets/encode_random.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![no_main]

use libfuzzer_sys::fuzz_target;
use shortguid::ShortGuid;

fuzz_target!(|str: String| {
// Since the input data is random, this likely won't
// parse correctly. As long as it returns an Err()
// instead of panicking, it's considered correct behavior.
let _ = ShortGuid::try_parse(&str);
});
9 changes: 9 additions & 0 deletions fuzz/fuzz_targets/roundtrip.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#![no_main]

use libfuzzer_sys::fuzz_target;
use shortguid::ShortGuid;

fuzz_target!(|bytes: [u8; 16]| {
let id = ShortGuid::from_bytes_ref(&bytes);
assert_eq!(&bytes, id.as_bytes());
});
13 changes: 10 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use uuid::Uuid;
/// assert_eq!(short_guid_a, short_guid_b);
/// ```
#[derive(Default, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[repr(transparent)]
pub struct ShortGuid(Uuid);

Expand All @@ -47,6 +48,7 @@ impl ShortGuid {
Ok(Self(uuid))
}

#[inline]
pub fn from_bytes(bytes: &[u8; 16]) -> Self {
Self(Uuid::from_bytes_ref(bytes).clone())
}
Expand Down Expand Up @@ -77,18 +79,21 @@ impl ShortGuid {
/// &bytes1 as *const [u8; 16] as *const u8,
/// ));
/// ```
pub fn from_bytes_ref(bytes: &[u8; 16]) -> &Self {
#[inline]
pub const fn from_bytes_ref(bytes: &[u8; 16]) -> &Self {
// SAFETY: `Bytes`, `Uuid` and `ShortGuid have the same ABI
unsafe { &*(bytes as *const [u8; 16] as *const Uuid as *const ShortGuid) }
}

/// Tests if this [`ShortGuid`] is all zeros.
pub fn is_empty(&self) -> bool {
#[inline]
pub const fn is_empty(&self) -> bool {
self.0.is_nil()
}

/// Returns the underlying [`Uuid`] instance.
pub fn as_uuid(&self) -> &Uuid {
#[inline]
pub const fn as_uuid(&self) -> &Uuid {
&self.0
}

Expand Down Expand Up @@ -118,6 +123,7 @@ impl ShortGuid {
/// &bytes1 as *const [u8; 16] as *const u8,
/// ));
/// ```
#[inline]
pub fn as_bytes(&self) -> &[u8; 16] {
self.0.as_bytes()
}
Expand Down Expand Up @@ -146,6 +152,7 @@ impl ShortGuid {
/// # Ok(())
/// # }
/// ```
#[inline]
pub fn to_bytes_le(&self) -> [u8; 16] {
self.0.to_bytes_le()
}
Expand Down

0 comments on commit c871fe3

Please sign in to comment.