diff options
| author | Eduard Zingerman <eddyz87@gmail.com> | 2026-09-04 17:05:56 -0700 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-09-04 18:17:30 -0700 |
| commit | 506ada89629ec7059b96ecfb0dc7d33ece0103ca (patch) | |
| tree | 0b07297409b68d2333fb4f0eae7f3b072eb68d4c /rust/quote/ident_fragment.rs | |
| download | linux-stable-506ada89629ec7059b96ecfb0dc7d33ece0103ca.tar.gz linux-stable-506ada89629ec7059b96ecfb0dc7d33ece0103ca.zip | |
bpf: mark a NULL kfunc argument precisegrafted
check_kfunc_arg() allows bpf_register_is_null() for nullable arguments
w/o marking the underlying scalar register precise. Hence a checkpoint
created on such a path would prune against arbitrary scalar value.
Fixes: 3bda08b63670 ("bpf: Allow NULL buffers in bpf_dynptr_slice(_rw)")
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260904-register-is-null-precise-fixes-v1-5-0f5a360ff15d@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'rust/quote/ident_fragment.rs')
| -rw-r--r-- | rust/quote/ident_fragment.rs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/rust/quote/ident_fragment.rs b/rust/quote/ident_fragment.rs new file mode 100644 index 000000000..d98106f17 --- /dev/null +++ b/rust/quote/ident_fragment.rs @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +use alloc::borrow::Cow; +use core::fmt; +use proc_macro2::{Ident, Span}; + +/// Specialized formatting trait used by `format_ident!`. +/// +/// [`Ident`] arguments formatted using this trait will have their `r#` prefix +/// stripped, if present. +/// +/// See [`format_ident!`] for more information. +/// +/// [`format_ident!`]: crate::format_ident +pub trait IdentFragment { + /// Format this value as an identifier fragment. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result; + + /// Span associated with this `IdentFragment`. + /// + /// If non-`None`, may be inherited by formatted identifiers. + fn span(&self) -> Option<Span> { + None + } +} + +impl<T: IdentFragment + ?Sized> IdentFragment for &T { + fn span(&self) -> Option<Span> { + <T as IdentFragment>::span(*self) + } + + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + IdentFragment::fmt(*self, f) + } +} + +impl<T: IdentFragment + ?Sized> IdentFragment for &mut T { + fn span(&self) -> Option<Span> { + <T as IdentFragment>::span(*self) + } + + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + IdentFragment::fmt(*self, f) + } +} + +impl IdentFragment for Ident { + fn span(&self) -> Option<Span> { + Some(self.span()) + } + + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let id = self.to_string(); + if let Some(id) = id.strip_prefix("r#") { + fmt::Display::fmt(id, f) + } else { + fmt::Display::fmt(&id[..], f) + } + } +} + +impl<T> IdentFragment for Cow<'_, T> +where + T: IdentFragment + ToOwned + ?Sized, +{ + fn span(&self) -> Option<Span> { + T::span(self) + } + + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + T::fmt(self, f) + } +} + +// Limited set of types which this is implemented for, as we want to avoid types +// which will often include non-identifier characters in their `Display` impl. +macro_rules! ident_fragment_display { + ($($T:ty),*) => { + $( + impl IdentFragment for $T { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self, f) + } + } + )* + }; +} + +ident_fragment_display!(bool, str, String, char); +ident_fragment_display!(u8, u16, u32, u64, u128, usize); |
