redirect_uri.rs 1.3 KB

123456789101112131415161718192021222324252627282930313233343536
  1. //! Fuzz `redirect_uri` matching (`protocol::redirect_repo`, RFC 3986 §6.2.1
  2. //! plus the RFC 8252 §7.3 loopback exception).
  3. //!
  4. //! Both the requested URI (first input line) and the registered catalog set
  5. //! (following lines, capped) are hostile input: the matcher must never panic,
  6. //! never fall back to prefix/wildcard comparison, and only report `Exact`
  7. //! for a character-for-character member of the registered set.
  8. #![no_main]
  9. use d_oauth::protocol::redirect_repo::{RedirectDecision, match_redirect_uri};
  10. use libfuzzer_sys::fuzz_target;
  11. /// Maximum registered URIs taken from one input; matching is linear, so the
  12. /// cap keeps a single execution bounded.
  13. const MAX_REGISTERED: usize = 8;
  14. fuzz_target!(|data: &[u8]| {
  15. let Ok(text) = core::str::from_utf8(data) else {
  16. return;
  17. };
  18. let mut lines = text.split('\n');
  19. let Some(requested) = lines.next() else {
  20. return;
  21. };
  22. let registered: Vec<&str> = lines.take(MAX_REGISTERED).collect();
  23. let decision = match_redirect_uri(&registered, requested);
  24. // An empty catalog can never match.
  25. if registered.is_empty() {
  26. debug_assert_eq!(decision, RedirectDecision::Reject);
  27. }
  28. // `Exact` fires only for a character-for-character registered member.
  29. if decision == RedirectDecision::Exact {
  30. debug_assert!(registered.contains(&requested));
  31. }
  32. });