diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 98e68e682abb1..d8db7db2b288a 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -772,45 +772,64 @@ impl<'a> Parser<'a> {
                 && let [segment] = &attr_kind.item.path.segments[..]
                 && segment.ident.name == sym::cfg
                 && let Some(args_span) = attr_kind.item.args.span()
-                && let Ok(next_attr) = snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None))
-                && let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind
-                && let Some(next_attr_args_span) = next_attr_kind.item.args.span()
-                && let [next_segment] = &next_attr_kind.item.path.segments[..]
-                && segment.ident.name == sym::cfg
-                && let Ok(next_expr) = snapshot.parse_expr()
             {
-                // We have for sure
-                // #[cfg(..)]
-                // expr
-                // #[cfg(..)]
-                // other_expr
-                // So we suggest using `if cfg!(..) { expr } else if cfg!(..) { other_expr }`.
-                let margin = self.sess.source_map().span_to_margin(next_expr.span).unwrap_or(0);
-                let sugg = vec![
-                    (attr.span.with_hi(segment.span().hi()), "if cfg!".to_string()),
-                    (args_span.shrink_to_hi().with_hi(attr.span.hi()), " {".to_string()),
-                    (expr.span.shrink_to_lo(), "    ".to_string()),
-                    (
-                        next_attr.span.with_hi(next_segment.span().hi()),
-                        "} else if cfg!".to_string(),
-                    ),
-                    (
-                        next_attr_args_span.shrink_to_hi().with_hi(next_attr.span.hi()),
-                        " {".to_string(),
-                    ),
-                    (next_expr.span.shrink_to_lo(), "    ".to_string()),
-                    (next_expr.span.shrink_to_hi(), format!("\n{}}}", " ".repeat(margin))),
-                ];
-                err.multipart_suggestion(
-                    "it seems like you are trying to provide different expressions depending on \
-                     `cfg`, consider using `if cfg!(..)`",
-                    sugg,
-                    Applicability::MachineApplicable,
-                );
+                let next_attr = match snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None)) {
+                    Ok(next_attr) => next_attr,
+                    Err(mut perr) => {
+                        // Handle cases like #118575, where the attribute is malformed
+                        err.cancel();
+                        perr.emit();
+                        return;
+                    }
+                };
+                if let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind
+                    && let Some(next_attr_args_span) = next_attr_kind.item.args.span()
+                    && let [next_segment] = &next_attr_kind.item.path.segments[..]
+                    && segment.ident.name == sym::cfg
+                {
+                    let next_expr = match snapshot.parse_expr() {
+                        Ok(next_expr) => next_expr,
+                        Err(mut perr) => {
+                            // Handle cases like #118575, where the expression is malformed
+                            err.cancel();
+                            perr.emit();
+                            return;
+                        }
+                    };
+                    // We have for sure
+                    // #[cfg(..)]
+                    // expr
+                    // #[cfg(..)]
+                    // other_expr
+                    // So we suggest using `if cfg!(..) { expr } else if cfg!(..) { other_expr }`.
+                    let margin = self.sess.source_map().span_to_margin(next_expr.span).unwrap_or(0);
+                    let sugg = vec![
+                        (attr.span.with_hi(segment.span().hi()), "if cfg!".to_string()),
+                        (args_span.shrink_to_hi().with_hi(attr.span.hi()), " {".to_string()),
+                        (expr.span.shrink_to_lo(), "    ".to_string()),
+                        (
+                            next_attr.span.with_hi(next_segment.span().hi()),
+                            "} else if cfg!".to_string(),
+                        ),
+                        (
+                            next_attr_args_span.shrink_to_hi().with_hi(next_attr.span.hi()),
+                            " {".to_string(),
+                        ),
+                        (next_expr.span.shrink_to_lo(), "    ".to_string()),
+                        (next_expr.span.shrink_to_hi(), format!("\n{}}}", " ".repeat(margin))),
+                    ];
+                    err.multipart_suggestion(
+                        "it seems like you are trying to provide different expressions depending on \
+                        `cfg`, consider using `if cfg!(..)`",
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                }
             }
         }
         err.emit();
     }
+
     fn check_too_many_raw_str_terminators(&mut self, err: &mut Diagnostic) -> bool {
         let sm = self.sess.source_map();
         match (&self.prev_token.kind, &self.token.kind) {
diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs
index d97f24a3d2949..6e4fb1eea4d06 100644
--- a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs
+++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs
@@ -14,6 +14,23 @@ fn bar() -> String {
     String::new()
 }
 
+fn baz() -> String {
+    // Issue #118575: Don't ICE when encountering malformed attributes
+    #[cfg(feature = "validation")]
+    "foo".into()
+    #[]
+    //~^ ERROR expected identifier, found `]`
+    //~| ERROR expected identifier, found `]`
+    "bar".into()
+}
+
+fn qux() -> String {
+    // Issue #118575: Don't ICE when encountering malformed tail expressions
+    #[cfg(feature = "validation")]
+    "foo".into()
+    #[cfg(not(feature = "validation"))] //~ ERROR expected statement after outer attribute
+} //~ ERROR expected expression, found `}`
+
 fn main() {
     println!("{}", foo());
 }
diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr
index a71253a5e428c..ce34ee32a5509 100644
--- a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr
+++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr
@@ -44,11 +44,37 @@ help: alternatively, consider surrounding the expression with a block
 LL |     { [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() }
    |     +                                                             +
 
+error: expected identifier, found `]`
+  --> $DIR/multiple-tail-expr-behind-cfg.rs:21:7
+   |
+LL |     #[]
+   |       ^ expected identifier
+
+error: expected identifier, found `]`
+  --> $DIR/multiple-tail-expr-behind-cfg.rs:21:7
+   |
+LL |     #[]
+   |       ^ expected identifier
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: expected expression, found `}`
+  --> $DIR/multiple-tail-expr-behind-cfg.rs:32:1
+   |
+LL | }
+   | ^ expected expression
+
+error: expected statement after outer attribute
+  --> $DIR/multiple-tail-expr-behind-cfg.rs:31:5
+   |
+LL |     #[cfg(not(feature = "validation"))]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: cannot find attribute `attr` in this scope
   --> $DIR/multiple-tail-expr-behind-cfg.rs:13:7
    |
 LL |     #[attr]
    |       ^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 7 previous errors