Skip to content

Commit

Permalink
add validate function to FrameRepr
Browse files Browse the repository at this point in the history
  • Loading branch information
thvdveld committed Dec 17, 2024
1 parent e739f98 commit 066649a
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 3 deletions.
21 changes: 20 additions & 1 deletion dot15d4-frame/src/repr/addressing.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::super::{Address, AddressingFields, AddressingMode};
use super::FrameControlRepr;

use crate::{Address, AddressingFields, AddressingMode, Error, FrameType, Result};

/// A high-level representation of the IEEE 802.15.4 Addressing Fields.
#[derive(Debug, Default)]
#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
Expand All @@ -26,6 +27,24 @@ impl AddressingFieldsRepr {
}
}

/// Validate the Addressing Fields.
pub fn validate(&self, fc: &FrameControlRepr) -> Result<()> {
if fc.frame_type == FrameType::Data
&& matches!(
(
self.dst_pan_id,
self.dst_address,
self.src_pan_id,
self.src_address
),
(None, None, None, None)
)
{
return Err(Error);
}
Ok(())
}

/// Return the length of the Addressing Fields in octets.
pub fn buffer_len(&self, fc: &FrameControlRepr) -> usize {
(match self.dst_pan_id {
Expand Down
33 changes: 31 additions & 2 deletions dot15d4-frame/src/repr/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::Frame;
use super::Result;
use crate::FrameType;

use super::{Error, Frame, Result};

mod addressing;
pub use addressing::AddressingFieldsRepr;
Expand Down Expand Up @@ -50,6 +51,34 @@ impl<'f> FrameRepr<'f> {
})
}

/// Validate the frame.
pub fn validate(&self) -> Result<()> {
// If the frame type is data, then the addressing fields must be present.
if self.frame_control.frame_type == FrameType::Data {
if self.addressing_fields.is_none() {
return Err(Error);
}

if self.payload.is_none() {
return Err(Error);
}
}

// If the addressing fields are present, they must be valid.
if let Some(af) = &self.addressing_fields {
af.validate(&self.frame_control)?;
}

// If the payload is present, it must not be empty.
if let Some(payload) = self.payload {
if payload.is_empty() {
return Err(Error);
}
}

Ok(())
}

/// Return the length of the frame when emitted into a buffer.
pub fn buffer_len(&self) -> usize {
let mut len = 2; // Frame control
Expand Down
2 changes: 2 additions & 0 deletions dot15d4-frame/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ impl Instant {
pub struct Duration(i64);

impl Duration {
pub const ZERO: Self = Self(0);

/// Create a new `Duration` from microseconds.
pub const fn from_us(us: i64) -> Self {
Self(us)
Expand Down
4 changes: 4 additions & 0 deletions fuzz/fuzz_targets/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ use dot15d4_frame::{Frame, FrameRepr};
use libfuzzer_sys::fuzz_target;

fuzz_target!(|repr: FrameRepr| {
if repr.validate().is_err() {
return;
}

let len = repr.buffer_len();
let mut buffer = vec![0; len];
repr.emit(&mut Frame::new_unchecked(&mut buffer[..]));
Expand Down

0 comments on commit 066649a

Please sign in to comment.