1use std::collections::{BTreeMap, BTreeSet};
2use std::str::FromStr;
3
4use rustc_macros::{BlobDecodable, Encodable};
5use rustc_span::edition::Edition;
6use rustc_target::spec::StackProtector;
7
8use crate::Session;
9use crate::config::Options;
10use crate::options::CFGuard;
11
12#[derive(#[automatically_derived]
impl ::core::marker::Copy for DeniedPartialMitigationLevel { }Copy, #[automatically_derived]
impl ::core::clone::Clone for DeniedPartialMitigationLevel {
#[inline]
fn clone(&self) -> DeniedPartialMitigationLevel {
let _: ::core::clone::AssertParamIsClone<bool>;
let _: ::core::clone::AssertParamIsClone<StackProtector>;
*self
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for DeniedPartialMitigationLevel {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
DeniedPartialMitigationLevel::Enabled(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Enabled", &__self_0),
DeniedPartialMitigationLevel::StackProtector(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"StackProtector", &__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for DeniedPartialMitigationLevel {
#[inline]
fn eq(&self, other: &DeniedPartialMitigationLevel) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(DeniedPartialMitigationLevel::Enabled(__self_0),
DeniedPartialMitigationLevel::Enabled(__arg1_0)) =>
__self_0 == __arg1_0,
(DeniedPartialMitigationLevel::StackProtector(__self_0),
DeniedPartialMitigationLevel::StackProtector(__arg1_0)) =>
__self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DeniedPartialMitigationLevel {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<bool>;
let _: ::core::cmp::AssertParamIsEq<StackProtector>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for DeniedPartialMitigationLevel {
#[inline]
fn partial_cmp(&self, other: &DeniedPartialMitigationLevel)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match (self, other) {
(DeniedPartialMitigationLevel::Enabled(__self_0),
DeniedPartialMitigationLevel::Enabled(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(DeniedPartialMitigationLevel::StackProtector(__self_0),
DeniedPartialMitigationLevel::StackProtector(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
_ =>
::core::cmp::PartialOrd::partial_cmp(&__self_discr,
&__arg1_discr),
}
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for DeniedPartialMitigationLevel {
#[inline]
fn cmp(&self, other: &DeniedPartialMitigationLevel)
-> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
::core::cmp::Ordering::Equal =>
match (self, other) {
(DeniedPartialMitigationLevel::Enabled(__self_0),
DeniedPartialMitigationLevel::Enabled(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(DeniedPartialMitigationLevel::StackProtector(__self_0),
DeniedPartialMitigationLevel::StackProtector(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ => unsafe { ::core::intrinsics::unreachable() }
},
cmp => cmp,
}
}
}Ord, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for DeniedPartialMitigationLevel {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
DeniedPartialMitigationLevel::Enabled(ref __binding_0) => {
0usize
}
DeniedPartialMitigationLevel::StackProtector(ref __binding_0)
=> {
1usize
}
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
DeniedPartialMitigationLevel::Enabled(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
DeniedPartialMitigationLevel::StackProtector(ref __binding_0)
=> {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::BlobDecoder> ::rustc_serialize::Decodable<__D>
for DeniedPartialMitigationLevel {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => {
DeniedPartialMitigationLevel::Enabled(::rustc_serialize::Decodable::decode(__decoder))
}
1usize => {
DeniedPartialMitigationLevel::StackProtector(::rustc_serialize::Decodable::decode(__decoder))
}
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `DeniedPartialMitigationLevel`, expected 0..2, actual {0}",
n));
}
}
}
}
};BlobDecodable)]
13pub enum DeniedPartialMitigationLevel {
14 Enabled(bool),
16 StackProtector(StackProtector),
17}
18
19impl DeniedPartialMitigationLevel {
20 pub fn level_str(&self) -> &'static str {
21 match self {
22 DeniedPartialMitigationLevel::StackProtector(StackProtector::All) => "=all",
23 DeniedPartialMitigationLevel::StackProtector(StackProtector::Basic) => "=basic",
24 DeniedPartialMitigationLevel::StackProtector(StackProtector::Strong) => "=strong",
25 DeniedPartialMitigationLevel::Enabled(false) => "=disabled",
27 DeniedPartialMitigationLevel::StackProtector(StackProtector::None)
28 | DeniedPartialMitigationLevel::Enabled(true) => "",
29 }
30 }
31}
32
33impl std::fmt::Display for DeniedPartialMitigationLevel {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 match self {
36 DeniedPartialMitigationLevel::StackProtector(StackProtector::All) => {
37 f.write_fmt(format_args!("all"))write!(f, "all")
38 }
39 DeniedPartialMitigationLevel::StackProtector(StackProtector::Basic) => {
40 f.write_fmt(format_args!("basic"))write!(f, "basic")
41 }
42 DeniedPartialMitigationLevel::StackProtector(StackProtector::Strong) => {
43 f.write_fmt(format_args!("strong"))write!(f, "strong")
44 }
45 DeniedPartialMitigationLevel::Enabled(true) => {
46 f.write_fmt(format_args!("enabled"))write!(f, "enabled")
47 }
48 DeniedPartialMitigationLevel::StackProtector(StackProtector::None)
49 | DeniedPartialMitigationLevel::Enabled(false) => {
50 f.write_fmt(format_args!("disabled"))write!(f, "disabled")
51 }
52 }
53 }
54}
55
56impl From<bool> for DeniedPartialMitigationLevel {
57 fn from(value: bool) -> Self {
58 DeniedPartialMitigationLevel::Enabled(value)
59 }
60}
61
62impl From<StackProtector> for DeniedPartialMitigationLevel {
63 fn from(value: StackProtector) -> Self {
64 DeniedPartialMitigationLevel::StackProtector(value)
65 }
66}
67
68#[derive(#[automatically_derived]
impl ::core::marker::Copy for MitigationStatus { }Copy, #[automatically_derived]
impl ::core::clone::Clone for MitigationStatus {
#[inline]
fn clone(&self) -> MitigationStatus {
let _: ::core::clone::AssertParamIsClone<usize>;
let _: ::core::clone::AssertParamIsClone<Option<bool>>;
*self
}
}Clone)]
69struct MitigationStatus {
70 index: usize,
76 allowed: Option<bool>,
77}
78
79#[derive(#[automatically_derived]
impl ::core::clone::Clone for MitigationCoverageMap {
#[inline]
fn clone(&self) -> MitigationCoverageMap {
MitigationCoverageMap { map: ::core::clone::Clone::clone(&self.map) }
}
}Clone, #[automatically_derived]
impl ::core::default::Default for MitigationCoverageMap {
#[inline]
fn default() -> MitigationCoverageMap {
MitigationCoverageMap { map: ::core::default::Default::default() }
}
}Default)]
80pub struct MitigationCoverageMap {
81 map: BTreeMap<DeniedPartialMitigationKind, MitigationStatus>,
82}
83
84impl MitigationCoverageMap {
85 fn apply_mitigation(
86 &mut self,
87 kind: DeniedPartialMitigationKind,
88 index: usize,
89 allowed: Option<bool>,
90 ) {
91 self.map
92 .entry(kind)
93 .and_modify(|e| {
94 if index >= e.index {
95 *e = MitigationStatus { index, allowed }
96 }
97 })
98 .or_insert(MitigationStatus { index, allowed });
99 }
100
101 pub(crate) fn handle_allowdeny_mitigation_option(
102 &mut self,
103 v: Option<&str>,
104 index: usize,
105 allowed: bool,
106 ) -> bool {
107 match v {
108 Some(s) => {
109 for sub in s.split(',') {
110 match sub.parse() {
111 Ok(kind) => self.apply_mitigation(kind, index, Some(allowed)),
112 Err(_) => return false,
113 }
114 }
115 true
116 }
117 None => false,
118 }
119 }
120
121 pub(crate) fn reset_mitigation(&mut self, kind: DeniedPartialMitigationKind, index: usize) {
122 self.apply_mitigation(kind, index, None);
123 }
124}
125
126pub struct DeniedPartialMitigationKindParseError;
127
128macro_rules! intersperse {
129 ($sep:expr, ($first:expr $(, $rest:expr)* $(,)?)) => {
130 concat!($first $(, $sep, $rest)*)
131 };
132}
133
134macro_rules! denied_partial_mitigations {
135 ([$self:ident] enum $kind:ident {$(($name:ident, $text:expr, $since:ident, $code:expr)),*}) => {
136 #[allow(non_camel_case_types)]
137 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Encodable, BlobDecodable)]
138 pub enum DeniedPartialMitigationKind {
139 $($name),*
140 }
141
142 impl std::fmt::Display for DeniedPartialMitigationKind {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 match self {
145 $(DeniedPartialMitigationKind::$name => write!(f, $text)),*
146 }
147 }
148 }
149
150 impl DeniedPartialMitigationKind {
151 pub(crate) const KINDS: &'static str = concat!("comma-separated list of mitigation kinds (available: ",
152 intersperse!(", ", ($(concat!("`", $text, "`")),*)), ")");
153 }
154
155 impl FromStr for DeniedPartialMitigationKind {
156 type Err = DeniedPartialMitigationKindParseError;
157
158 fn from_str(v: &str) -> Result<DeniedPartialMitigationKind, DeniedPartialMitigationKindParseError> {
159 match v {
160 $($text => Ok(DeniedPartialMitigationKind::$name)),*
161 ,
162 _ => Err(DeniedPartialMitigationKindParseError),
163 }
164 }
165 }
166
167 #[allow(unused)]
168 impl DeniedPartialMitigationKind {
169 pub fn allowed_by_default_at(&self, edition: Edition) -> bool {
170 let denied_since = match self {
171 $(DeniedPartialMitigationKind::$name => Edition::$since),*
174 };
175 edition < denied_since
176 }
177 }
178
179 impl Options {
180 pub fn all_denied_partial_mitigations(&self) -> impl Iterator<Item = DeniedPartialMitigationKind> {
181 [$(DeniedPartialMitigationKind::$name),*].into_iter()
182 }
183 }
184
185 impl Session {
186 pub fn gather_enabled_denied_partial_mitigations(&$self) -> Vec<DeniedPartialMitigation> {
187 let mut mitigations = [
188 $(
189 DeniedPartialMitigation {
190 kind: DeniedPartialMitigationKind::$name,
191 level: From::from($code),
192 }
193 ),*
194 ];
195 mitigations.sort();
196 mitigations.into_iter().collect()
197 }
198 }
199 }
200}
201
202#[allow(non_camel_case_types)]
pub enum DeniedPartialMitigationKind { stack_protector, control_flow_guard, }
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::marker::Copy for DeniedPartialMitigationKind { }
#[automatically_derived]
#[doc(hidden)]
#[allow(non_camel_case_types)]
unsafe impl ::core::clone::TrivialClone for DeniedPartialMitigationKind { }
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::clone::Clone for DeniedPartialMitigationKind {
#[inline]
fn clone(&self) -> DeniedPartialMitigationKind { *self }
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::fmt::Debug for DeniedPartialMitigationKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
DeniedPartialMitigationKind::stack_protector =>
"stack_protector",
DeniedPartialMitigationKind::control_flow_guard =>
"control_flow_guard",
})
}
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::marker::StructuralPartialEq for DeniedPartialMitigationKind { }
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialEq for DeniedPartialMitigationKind {
#[inline]
fn eq(&self, other: &DeniedPartialMitigationKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::Eq for DeniedPartialMitigationKind {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::hash::Hash for DeniedPartialMitigationKind {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialOrd for DeniedPartialMitigationKind {
#[inline]
fn partial_cmp(&self, other: &DeniedPartialMitigationKind)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
}
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::Ord for DeniedPartialMitigationKind {
#[inline]
fn cmp(&self, other: &DeniedPartialMitigationKind)
-> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
}
}
const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for DeniedPartialMitigationKind {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
DeniedPartialMitigationKind::stack_protector => { 0usize }
DeniedPartialMitigationKind::control_flow_guard => {
1usize
}
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
DeniedPartialMitigationKind::stack_protector => {}
DeniedPartialMitigationKind::control_flow_guard => {}
}
}
}
};
const _: () =
{
impl<__D: ::rustc_span::BlobDecoder> ::rustc_serialize::Decodable<__D>
for DeniedPartialMitigationKind {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { DeniedPartialMitigationKind::stack_protector }
1usize => {
DeniedPartialMitigationKind::control_flow_guard
}
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `DeniedPartialMitigationKind`, expected 0..2, actual {0}",
n));
}
}
}
}
};
impl std::fmt::Display for DeniedPartialMitigationKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DeniedPartialMitigationKind::stack_protector =>
f.write_fmt(format_args!("stack-protector")),
DeniedPartialMitigationKind::control_flow_guard =>
f.write_fmt(format_args!("control-flow-guard")),
}
}
}
impl DeniedPartialMitigationKind {
pub(crate) const KINDS: &'static str =
"comma-separated list of mitigation kinds (available: `stack-protector`, `control-flow-guard`)";
}
impl FromStr for DeniedPartialMitigationKind {
type Err = DeniedPartialMitigationKindParseError;
fn from_str(v: &str)
->
Result<DeniedPartialMitigationKind,
DeniedPartialMitigationKindParseError> {
match v {
"stack-protector" =>
Ok(DeniedPartialMitigationKind::stack_protector),
"control-flow-guard" =>
Ok(DeniedPartialMitigationKind::control_flow_guard),
_ => Err(DeniedPartialMitigationKindParseError),
}
}
}
#[allow(unused)]
impl DeniedPartialMitigationKind {
pub fn allowed_by_default_at(&self, edition: Edition) -> bool {
let denied_since =
match self {
DeniedPartialMitigationKind::stack_protector =>
Edition::EditionFuture,
DeniedPartialMitigationKind::control_flow_guard =>
Edition::EditionFuture,
};
edition < denied_since
}
}
impl Options {
pub fn all_denied_partial_mitigations(&self)
-> impl Iterator<Item = DeniedPartialMitigationKind> {
[DeniedPartialMitigationKind::stack_protector,
DeniedPartialMitigationKind::control_flow_guard].into_iter()
}
}
impl Session {
pub fn gather_enabled_denied_partial_mitigations(&self)
-> Vec<DeniedPartialMitigation> {
let mut mitigations =
[DeniedPartialMitigation {
kind: DeniedPartialMitigationKind::stack_protector,
level: From::from(self.stack_protector()),
},
DeniedPartialMitigation {
kind: DeniedPartialMitigationKind::control_flow_guard,
level: From::from(self.opts.cg.control_flow_guard ==
CFGuard::Checks),
}];
mitigations.sort();
mitigations.into_iter().collect()
}
}denied_partial_mitigations! {
203 [self]
204 enum DeniedPartialMitigationKind {
205 (stack_protector, "stack-protector", EditionFuture, self.stack_protector()),
208 (control_flow_guard, "control-flow-guard", EditionFuture, self.opts.cg.control_flow_guard == CFGuard::Checks)
209 }
210}
211
212#[derive(#[automatically_derived]
impl ::core::marker::Copy for DeniedPartialMitigation { }Copy, #[automatically_derived]
impl ::core::clone::Clone for DeniedPartialMitigation {
#[inline]
fn clone(&self) -> DeniedPartialMitigation {
let _: ::core::clone::AssertParamIsClone<DeniedPartialMitigationKind>;
let _:
::core::clone::AssertParamIsClone<DeniedPartialMitigationLevel>;
*self
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for DeniedPartialMitigation {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"DeniedPartialMitigation", "kind", &self.kind, "level",
&&self.level)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for DeniedPartialMitigation {
#[inline]
fn eq(&self, other: &DeniedPartialMitigation) -> bool {
self.kind == other.kind && self.level == other.level
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DeniedPartialMitigation {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<DeniedPartialMitigationKind>;
let _: ::core::cmp::AssertParamIsEq<DeniedPartialMitigationLevel>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for DeniedPartialMitigation {
#[inline]
fn partial_cmp(&self, other: &DeniedPartialMitigation)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.kind, &other.kind) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
::core::cmp::PartialOrd::partial_cmp(&self.level,
&other.level),
cmp => cmp,
}
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for DeniedPartialMitigation {
#[inline]
fn cmp(&self, other: &DeniedPartialMitigation) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.kind, &other.kind) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.level, &other.level),
cmp => cmp,
}
}
}Ord, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for DeniedPartialMitigation {
fn encode(&self, __encoder: &mut __E) {
match *self {
DeniedPartialMitigation {
kind: ref __binding_0, level: ref __binding_1 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::BlobDecoder> ::rustc_serialize::Decodable<__D>
for DeniedPartialMitigation {
fn decode(__decoder: &mut __D) -> Self {
DeniedPartialMitigation {
kind: ::rustc_serialize::Decodable::decode(__decoder),
level: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};BlobDecodable)]
216pub struct DeniedPartialMitigation {
217 pub kind: DeniedPartialMitigationKind,
218 pub level: DeniedPartialMitigationLevel,
219}
220
221impl Options {
222 pub fn allowed_partial_mitigations(
224 &self,
225 edition: Edition,
226 ) -> impl Iterator<Item = DeniedPartialMitigationKind> {
227 let mut result: BTreeSet<_> = self
228 .all_denied_partial_mitigations()
229 .filter(|mitigation| mitigation.allowed_by_default_at(edition))
230 .collect();
231 for (kind, MitigationStatus { index: _, allowed }) in &self.mitigation_coverage_map.map {
232 match allowed {
233 Some(true) => {
234 result.insert(*kind);
235 }
236 Some(false) => {
237 result.remove(kind);
238 }
239 None => {}
240 }
241 }
242 result.into_iter()
243 }
244}