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
//! Shared traversal-validation logic for the `zenops-safe-relative-path`
//! family.
//!
//! Both the runtime [`SafeRelativePath`] type and the compile-time
//! [`srpath!`] proc macro need to agree on what counts as a "safe"
//! relative path. The rule lives here so neither side can drift from the
//! other. Application code should depend on [`zenops-safe-relative-path`]
//! instead of pulling this crate in directly — this exists as the seam
//! between the runtime crate and the proc-macro crate.
//!
//! [`SafeRelativePath`]: https://docs.rs/zenops-safe-relative-path/latest/zenops_safe_relative_path/struct.SafeRelativePath.html
//! [`srpath!`]: https://docs.rs/zenops-safe-relative-path/latest/zenops_safe_relative_path/macro.srpath.html
//! [`zenops-safe-relative-path`]: https://docs.rs/zenops-safe-relative-path
use ;
/// Returns `true` if `path` contains no `..` components.
///
/// The single source of truth for what counts as a safe relative path in
/// this family of crates. A path is safe when every component is either
/// `.` or a normal name segment — anything that would walk out via `..`
/// is rejected, including segments that would notionally cancel
/// (`a/../b` is unsafe even though it normalises to `b`).
///
/// # Why no `..` at all?
///
/// The check is purely lexical so the same rule can run inside the
/// `srpath!` proc macro at compile time, where no filesystem is available.
/// Once you're committed to a lexical check, "normalise first, then
/// reject `..`" becomes unsound: `foo/../bar` normalises to `bar`, but at
/// run time `foo` might be a symlink, and walking through `..` then
/// resolves against the symlink target's parent rather than the original
/// base. Rejecting every `..` outright sidesteps that footgun.
///
/// # Examples
///
/// ```
/// use zenops_safe_relative_path_validator::is_safe_relative_path;
///
/// assert!(is_safe_relative_path("config/app.toml"));
/// assert!(is_safe_relative_path("."));
/// assert!(is_safe_relative_path(""));
///
/// assert!(!is_safe_relative_path("../etc"));
/// assert!(!is_safe_relative_path("a/../b"));
/// ```