From f10f6e44b10eab2667812e54df68799348449723 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 5 Nov 2026 14:36:25 +0000 Subject: [PATCH 1/2] Return nullptr from any_cast on a null pointer and bounds-check vector::at --- rules/any/tgt_refcount.rs | 12 ++++++++---- rules/any/tgt_unsafe.rs | 2 +- rules/vector/tgt_refcount.rs | 6 +++++- tests/ub/vector_at_out_of_range.cpp | 9 +++++++++ tests/unit/any.cpp | 2 ++ 5 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 tests/ub/vector_at_out_of_range.cpp diff --git a/rules/any/tgt_refcount.rs b/rules/any/tgt_refcount.rs index 8bad9f113c..ce69df1430 100644 --- a/rules/any/tgt_refcount.rs +++ b/rules/any/tgt_refcount.rs @@ -29,10 +29,14 @@ fn f14(a0: &mut Option>, init: cpp_type!("std } fn f19(a0: Ptr>>) -> Ptr { - a0.with(|__a: &Option>| match __a.clone().map(|__r| __r.downcast::>()) { - Some(Ok(__v)) => __v.as_pointer(), - _ => Ptr::null(), - }) + if a0.is_null() { + Ptr::null() + } else { + a0.with(|__a: &Option>| match __a.clone().map(|__r| __r.downcast::>()) { + Some(Ok(__v)) => __v.as_pointer(), + _ => Ptr::null(), + }) + } } fn f27(init: cpp_type!("std::decay_t", T1)) -> Option> { diff --git a/rules/any/tgt_unsafe.rs b/rules/any/tgt_unsafe.rs index dfdd9f82b1..a171f3c0fa 100644 --- a/rules/any/tgt_unsafe.rs +++ b/rules/any/tgt_unsafe.rs @@ -25,7 +25,7 @@ unsafe fn f14(a0: &mut Option>, init: cpp_ty } unsafe fn f19(a0: *mut Option>) -> *mut T1 { - match (*a0).as_mut().and_then(|__b| __b.downcast_mut::()) { + match a0.as_mut().and_then(|__a| __a.as_mut()).and_then(|__b| __b.downcast_mut::()) { Some(__v) => __v as *mut T1, None => std::ptr::null_mut(), } diff --git a/rules/vector/tgt_refcount.rs b/rules/vector/tgt_refcount.rs index 5f48646b0d..558a6b6b10 100644 --- a/rules/vector/tgt_refcount.rs +++ b/rules/vector/tgt_refcount.rs @@ -40,7 +40,11 @@ fn f65(a0: Ptr) -> Ptr { } fn f66(a0: Ptr, a1: usize) -> Ptr { - a0.offset(a1 as isize) + if a1 as usize >= a0.len() { + panic!("out of bounds access") + } else { + a0.offset(a1 as isize) + } } fn f68(a0: Ptr) -> Ptr { diff --git a/tests/ub/vector_at_out_of_range.cpp b/tests/ub/vector_at_out_of_range.cpp new file mode 100644 index 0000000000..6524c38650 --- /dev/null +++ b/tests/ub/vector_at_out_of_range.cpp @@ -0,0 +1,9 @@ +// panic-ub +#include + +int main() { + std::vector v = {1, 2, 3}; + auto idx = v.size(); + int *p = &v.at(idx); + return p == nullptr; +} diff --git a/tests/unit/any.cpp b/tests/unit/any.cpp index 856fdfe7e8..35821d7ad9 100644 --- a/tests/unit/any.cpp +++ b/tests/unit/any.cpp @@ -24,5 +24,7 @@ int main() { b.reset(); assert(!b.has_value()); assert(std::any_cast(&b) == nullptr); + std::any *n = nullptr; + assert(std::any_cast(n) == nullptr); return 0; } From d0913730cd3f82ccd62a9600b8d7612bc827c43e Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 5 Nov 2026 15:11:27 +0000 Subject: [PATCH 2/2] Update tests --- .../ub/out/refcount/vector_at_out_of_range.rs | 23 ++++ tests/ub/out/unsafe/vector_at_out_of_range.rs | 21 ++++ tests/unit/out/refcount/any.rs | 113 +++++++++++++----- tests/unit/out/refcount/implicit_autoref.rs | 10 +- tests/unit/out/refcount/nested_vector.rs | 14 ++- tests/unit/out/refcount/vector.rs | 88 +++++++++++--- .../out/refcount/vector_with_allocator.rs | 108 ++++++++++++----- tests/unit/out/unsafe/any.rs | 27 ++++- 8 files changed, 320 insertions(+), 84 deletions(-) create mode 100644 tests/ub/out/refcount/vector_at_out_of_range.rs create mode 100644 tests/ub/out/unsafe/vector_at_out_of_range.rs diff --git a/tests/ub/out/refcount/vector_at_out_of_range.rs b/tests/ub/out/refcount/vector_at_out_of_range.rs new file mode 100644 index 0000000000..b6fb6e8dd3 --- /dev/null +++ b/tests/ub/out/refcount/vector_at_out_of_range.rs @@ -0,0 +1,23 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let v: Value> = Rc::new(RefCell::new(Vec::from([1, 2, 3]))); + let mut idx: usize = (*v.borrow()).len(); + let mut p: Ptr = (if idx as usize >= v.decay().len() { + panic!("out of bounds access") + } else { + v.decay().offset(idx as isize) + }); + return (((p).is_null()) as i32); +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/ub/out/unsafe/vector_at_out_of_range.rs b/tests/ub/out/unsafe/vector_at_out_of_range.rs new file mode 100644 index 0000000000..0d1d04d641 --- /dev/null +++ b/tests/ub/out/unsafe/vector_at_out_of_range.rs @@ -0,0 +1,21 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut v: Vec = Vec::from([1, 2, 3]); + let mut idx: usize = v.len(); + let mut p: *mut i32 = (&mut (v)[idx as usize] as *mut i32); + return (((p).is_null()) as i32); +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/any.rs b/tests/unit/out/refcount/any.rs index ef9bf551c0..f3b972340f 100644 --- a/tests/unit/out/refcount/any.rs +++ b/tests/unit/out/refcount/any.rs @@ -28,23 +28,38 @@ fn main_0() -> i32 { RefCell::new(Point::new({ 3 }, { 4 })), )))); assert!(({ (*a.borrow()).is_some() })); - let mut p: Ptr = (a.as_pointer()).with(|__a: &Option>| match __a - .clone() - .map(|__r| __r.downcast::>()) - { - Some(Ok(__v)) => __v.as_pointer(), - _ => Ptr::null(), - }); + let mut p: Ptr = match ({ (a.as_pointer()) },) { + (mut __tmp_0,) => { + if __tmp_0.is_null() { + Ptr::null() + } else { + __tmp_0.with(|__a: &Option>| { + match __a.clone().map(|__r| __r.downcast::>()) { + Some(Ok(__v)) => __v.as_pointer(), + _ => Ptr::null(), + } + }) + } + } + }; assert!(!((p).is_null())); assert!((p.with(|__s| __s.x) == 3)); assert!((p.with(|__s| __s.y) == 4)); assert!( - ((a.as_pointer()).with(|__a: &Option>| { - match __a.clone().map(|__r| __r.downcast::>()) { - Some(Ok(__v)) => __v.as_pointer(), - _ => Ptr::null(), + (match ({ (a.as_pointer()) },) { + (mut __tmp_1,) => { + if __tmp_1.is_null() { + Ptr::null() + } else { + __tmp_1.with(|__a: &Option>| { + match __a.clone().map(|__r| __r.downcast::>()) { + Some(Ok(__v)) => __v.as_pointer(), + _ => Ptr::null(), + } + }) + } } - })) + }) .is_null() ); let q: Ptr = { @@ -55,38 +70,74 @@ fn main_0() -> i32 { }; assert!((q.with(|__s| __s.x) == 5)); assert!( - ((a.as_pointer()) - .with(|__a: &Option>| { - match __a.clone().map(|__r| __r.downcast::>()) { - Some(Ok(__v)) => __v.as_pointer(), - _ => Ptr::null(), + (match ({ (a.as_pointer()) },) { + (mut __tmp_2,) => { + if __tmp_2.is_null() { + Ptr::null() + } else { + __tmp_2.with(|__a: &Option>| { + match __a.clone().map(|__r| __r.downcast::>()) { + Some(Ok(__v)) => __v.as_pointer(), + _ => Ptr::null(), + } + }) } - }) - .with(|__s| __s.y) + } + } + .with(|__s| __s.y) == 6) ); let b: Value>> = Rc::new(RefCell::new(Some(Rc::new(RefCell::new(7))))); assert!( - (((b.as_pointer()) - .with(|__a: &Option>| { - match __a.clone().map(|__r| __r.downcast::>()) { - Some(Ok(__v)) => __v.as_pointer(), - _ => Ptr::null(), + ((match ({ (b.as_pointer()) },) { + (mut __tmp_3,) => { + if __tmp_3.is_null() { + Ptr::null() + } else { + __tmp_3.with(|__a: &Option>| { + match __a.clone().map(|__r| __r.downcast::>()) { + Some(Ok(__v)) => __v.as_pointer(), + _ => Ptr::null(), + } + }) } - }) - .read()) + } + } + .read()) == 7) ); (*b.borrow_mut()) = None; assert!(({ !((*b.borrow()).is_some()) })); assert!( - ((b.as_pointer()).with(|__a: &Option>| { - match __a.clone().map(|__r| __r.downcast::>()) { - Some(Ok(__v)) => __v.as_pointer(), - _ => Ptr::null(), + (match ({ (b.as_pointer()) },) { + (mut __tmp_4,) => { + if __tmp_4.is_null() { + Ptr::null() + } else { + __tmp_4.with(|__a: &Option>| { + match __a.clone().map(|__r| __r.downcast::>()) { + Some(Ok(__v)) => __v.as_pointer(), + _ => Ptr::null(), + } + }) + } } - })) + }) + .is_null() + ); + let mut n: Ptr>> = Ptr::>>::null(); + assert!( + (if n.is_null() { + Ptr::null() + } else { + n.with(|__a: &Option>| { + match __a.clone().map(|__r| __r.downcast::>()) { + Some(Ok(__v)) => __v.as_pointer(), + _ => Ptr::null(), + } + }) + }) .is_null() ); return 0; diff --git a/tests/unit/out/refcount/implicit_autoref.rs b/tests/unit/out/refcount/implicit_autoref.rs index 4546818fe4..34b58f55d2 100644 --- a/tests/unit/out/refcount/implicit_autoref.rs +++ b/tests/unit/out/refcount/implicit_autoref.rs @@ -56,7 +56,15 @@ fn main_0() -> i32 { assert!(((index!(p, 1_usize).read()) == 30)); assert!((b == 40)); assert!(((vec_elem!((hp), v, 1_usize).read()) == 60)); - ({ write_through_0((p.decay().offset(0_usize as isize))) }); + ({ + write_through_0( + (if 0_usize as usize >= p.decay().len() { + panic!("out of bounds access") + } else { + p.decay().offset(0_usize as isize) + }), + ) + }); assert!(((index!(p, 0_usize).read()) == 42)); return 0; } diff --git a/tests/unit/out/refcount/nested_vector.rs b/tests/unit/out/refcount/nested_vector.rs index ec172c638a..10fcfeaf36 100644 --- a/tests/unit/out/refcount/nested_vector.rs +++ b/tests/unit/out/refcount/nested_vector.rs @@ -17,7 +17,19 @@ fn main_0() -> i32 { let a0_clone = v2.clone(); (*v1.borrow_mut()).push(a0_clone) }; - assert!(((v1.decay().to_last().decay().offset(0_usize as isize).read()) == 1)); + assert!( + ((match (v1.decay().to_last(),) { + (__tmp_0,) => { + if 0_usize as usize >= __tmp_0.decay().len() { + panic!("out of bounds access") + } else { + __tmp_0.decay().offset(0_usize as isize) + } + } + } + .read()) + == 1) + ); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/vector.rs b/tests/unit/out/refcount/vector.rs index 3b52b3b4f1..16efd29293 100644 --- a/tests/unit/out/refcount/vector.rs +++ b/tests/unit/out/refcount/vector.rs @@ -282,39 +282,91 @@ fn main_0() -> i32 { x0 = 6_f64; assert!(((v6.decay().to_last().read()) == 5_f64)); let mut idx: i32 = 0; - assert!(((v6.decay().offset((idx as usize) as isize).read()) == 2_f64)); assert!( - ((v6.decay() - .offset((s2).wrapping_sub(1_usize) as isize) - .read()) + ((match ({ (idx as usize) },) { + (mut __tmp_11,) => { + if __tmp_11 as usize >= v6.decay().len() { + panic!("out of bounds access") + } else { + v6.decay().offset(__tmp_11 as isize) + } + } + } + .read()) + == 2_f64) + ); + assert!( + ((match ({ (s2).wrapping_sub(1_usize) },) { + (mut __tmp_12,) => { + if __tmp_12 as usize >= v6.decay().len() { + panic!("out of bounds access") + } else { + v6.decay().offset(__tmp_12 as isize) + } + } + } + .read()) == 5_f64) ); - let ref1: Ptr = v6.decay().offset((s2).wrapping_sub(1_usize) as isize); + let ref1: Ptr = match ({ (s2).wrapping_sub(1_usize) },) { + (mut __tmp_13,) => { + if __tmp_13 as usize >= v6.decay().len() { + panic!("out of bounds access") + } else { + v6.decay().offset(__tmp_13 as isize) + } + } + }; { ref1.with_mut(|__v| *__v = *__v + 1.5_f64) }; assert!( - ((v6.decay() - .offset((s2).wrapping_sub(1_usize) as isize) - .read()) + ((match ({ (s2).wrapping_sub(1_usize) },) { + (mut __tmp_14,) => { + if __tmp_14 as usize >= v6.decay().len() { + panic!("out of bounds access") + } else { + v6.decay().offset(__tmp_14 as isize) + } + } + } + .read()) == 6.5_f64) ); - let mut x1: f64 = (v6 - .decay() - .offset((s2).wrapping_sub(1_usize) as isize) - .read()); + let mut x1: f64 = (match ({ (s2).wrapping_sub(1_usize) },) { + (mut __tmp_15,) => { + if __tmp_15 as usize >= v6.decay().len() { + panic!("out of bounds access") + } else { + v6.decay().offset(__tmp_15 as isize) + } + } + } + .read()); assert!((x1 == 6.5_f64)); x1 -= 1.5_f64; assert!( - ((v6.decay() - .offset((s2).wrapping_sub(1_usize) as isize) - .read()) + ((match ({ (s2).wrapping_sub(1_usize) },) { + (mut __tmp_16,) => { + if __tmp_16 as usize >= v6.decay().len() { + panic!("out of bounds access") + } else { + v6.decay().offset(__tmp_16 as isize) + } + } + } + .read()) == 6.5_f64) ); assert!( - (((s1).wrapping_add(s2)) - .wrapping_add(((v2.decay().offset(0_usize as isize).read()) as usize)) - == 103_usize) + (((s1).wrapping_add(s2)).wrapping_add( + ((if 0_usize as usize >= v2.decay().len() { + panic!("out of bounds access") + } else { + v2.decay().offset(0_usize as isize) + } + .read()) as usize) + ) == 103_usize) ); let a: Value = Rc::new(RefCell::new(S { x: 1 })); let pa: Value> = Rc::new(RefCell::new((a.as_pointer()))); diff --git a/tests/unit/out/refcount/vector_with_allocator.rs b/tests/unit/out/refcount/vector_with_allocator.rs index 9f3f91356d..c903934771 100644 --- a/tests/unit/out/refcount/vector_with_allocator.rs +++ b/tests/unit/out/refcount/vector_with_allocator.rs @@ -184,33 +184,80 @@ fn main_0() -> i32 { x0 = 6_f64; assert!(((v6.decay().to_last().read()) == 5_f64)); let mut idx: i32 = 0; - assert!(((v6.decay().offset((idx as usize) as isize).read()) == 2_f64)); assert!( - ((v6.decay() - .offset((s2).wrapping_sub(1_usize) as isize) - .read()) + ((match ({ (idx as usize) },) { + (mut __tmp_2,) => { + if __tmp_2 as usize >= v6.decay().len() { + panic!("out of bounds access") + } else { + v6.decay().offset(__tmp_2 as isize) + } + } + } + .read()) + == 2_f64) + ); + assert!( + ((match ({ (s2).wrapping_sub(1_usize) },) { + (mut __tmp_3,) => { + if __tmp_3 as usize >= v6.decay().len() { + panic!("out of bounds access") + } else { + v6.decay().offset(__tmp_3 as isize) + } + } + } + .read()) == 5_f64) ); - let ref1: Ptr = v6.decay().offset((s2).wrapping_sub(1_usize) as isize); + let ref1: Ptr = match ({ (s2).wrapping_sub(1_usize) },) { + (mut __tmp_4,) => { + if __tmp_4 as usize >= v6.decay().len() { + panic!("out of bounds access") + } else { + v6.decay().offset(__tmp_4 as isize) + } + } + }; { ref1.with_mut(|__v| *__v = *__v + 1.5_f64) }; assert!( - ((v6.decay() - .offset((s2).wrapping_sub(1_usize) as isize) - .read()) + ((match ({ (s2).wrapping_sub(1_usize) },) { + (mut __tmp_5,) => { + if __tmp_5 as usize >= v6.decay().len() { + panic!("out of bounds access") + } else { + v6.decay().offset(__tmp_5 as isize) + } + } + } + .read()) == 6.5_f64) ); - let mut x1: f64 = (v6 - .decay() - .offset((s2).wrapping_sub(1_usize) as isize) - .read()); + let mut x1: f64 = (match ({ (s2).wrapping_sub(1_usize) },) { + (mut __tmp_6,) => { + if __tmp_6 as usize >= v6.decay().len() { + panic!("out of bounds access") + } else { + v6.decay().offset(__tmp_6 as isize) + } + } + } + .read()); assert!((x1 == 6.5_f64)); x1 -= 1.5_f64; assert!( - ((v6.decay() - .offset((s2).wrapping_sub(1_usize) as isize) - .read()) + ((match ({ (s2).wrapping_sub(1_usize) },) { + (mut __tmp_7,) => { + if __tmp_7 as usize >= v6.decay().len() { + panic!("out of bounds access") + } else { + v6.decay().offset(__tmp_7 as isize) + } + } + } + .read()) == 6.5_f64) ); let v7: Value> = Rc::new(RefCell::new(Vec::new())); @@ -238,10 +285,10 @@ fn main_0() -> i32 { ({ fn_1(v7.as_pointer(), v8.clone()) }); let src: Value> = Rc::new(RefCell::new(Box::new([1_u32, 2_u32, 3_u32]))); let mut v9: Vec = match ({ (src.as_pointer() as Ptr).offset((3) as isize) },) { - (mut __tmp_2,) => { + (mut __tmp_8,) => { let mut __v = Vec::new(); let mut __it = (src.as_pointer() as Ptr); - while __it != __tmp_2 { + while __it != __tmp_8 { __v.push((__it.iter_deref().read())); __it.iter_inc(); } @@ -251,10 +298,10 @@ fn main_0() -> i32 { assert!((v9.len() == 3_usize)); assert!(((v9[0_usize] == 1_u32) && (v9[1_usize] == 2_u32)) && (v9[2_usize] == 3_u32)); let mut v10: Vec = match ({ (src.as_pointer() as Ptr).offset((3) as isize) },) { - (mut __tmp_3,) => { + (mut __tmp_9,) => { let mut __v = Vec::new(); let mut __it = (src.as_pointer() as Ptr); - while __it != __tmp_3 { + while __it != __tmp_9 { __v.push(((__it.iter_deref().read()) as u64)); __it.iter_inc(); } @@ -264,10 +311,10 @@ fn main_0() -> i32 { assert!((v10.len() == 3_usize)); assert!(((v10[0_usize] == 1_u64) && (v10[1_usize] == 2_u64)) && (v10[2_usize] == 3_u64)); let mut v11: Vec = match ({ (src.as_pointer() as Ptr).offset((3) as isize) },) { - (mut __tmp_4,) => { + (mut __tmp_10,) => { let mut __v = Vec::new(); let mut __it = (src.as_pointer() as Ptr); - while __it != __tmp_4 { + while __it != __tmp_10 { __v.push(((__it.iter_deref().read()) as i32)); __it.iter_inc(); } @@ -278,10 +325,10 @@ fn main_0() -> i32 { assert!(((v11[0_usize] == 1) && (v11[1_usize] == 2)) && (v11[2_usize] == 3)); let src1: Value> = Rc::new(RefCell::new(Box::new([1_u32, 2_u32, 3_u32]))); let mut v12: Vec = match ({ (src1.as_pointer() as Ptr).to_end() },) { - (mut __tmp_5,) => { + (mut __tmp_11,) => { let mut __v = Vec::new(); let mut __it = (src1.as_pointer() as Ptr); - while __it != __tmp_5 { + while __it != __tmp_11 { __v.push((__it.iter_deref().read())); __it.iter_inc(); } @@ -295,10 +342,10 @@ fn main_0() -> i32 { let mut start: Ptr = (buf.as_pointer() as Ptr); let mut len: usize = 5_usize; let mut v13: Vec = match ({ start.offset((len) as isize) },) { - (mut __tmp_6,) => { + (mut __tmp_12,) => { let mut __v = Vec::new(); let mut __it = (start).clone(); - while __it != __tmp_6 { + while __it != __tmp_12 { __v.push((__it.iter_deref().read())); __it.iter_inc(); } @@ -308,9 +355,14 @@ fn main_0() -> i32 { assert!((v13.len() == 5_usize)); assert!(((v13[0_usize] as i32) == 10) && ((v13[4_usize] as i32) == 50)); assert!( - (((s1).wrapping_add(s2)) - .wrapping_add(((v2.decay().offset(0_usize as isize).read()) as usize)) - == 103_usize) + (((s1).wrapping_add(s2)).wrapping_add( + ((if 0_usize as usize >= v2.decay().len() { + panic!("out of bounds access") + } else { + v2.decay().offset(0_usize as isize) + } + .read()) as usize) + ) == 103_usize) ); return 0; } diff --git a/tests/unit/out/unsafe/any.rs b/tests/unit/out/unsafe/any.rs index abdb000c81..5cdcce9156 100644 --- a/tests/unit/out/unsafe/any.rs +++ b/tests/unit/out/unsafe/any.rs @@ -27,8 +27,9 @@ pub fn main() { unsafe fn main_0() -> i32 { let mut a: Option> = Some(Box::new(Point::new({ 3 }, { 4 }))); assert!(a.is_some()); - let mut p: *mut Point = match (*(&mut a as *mut Option>)) + let mut p: *mut Point = match (&mut a as *mut Option>) .as_mut() + .and_then(|__a| __a.as_mut()) .and_then(|__b| __b.downcast_mut::()) { Some(__v) => __v as *mut Point, @@ -38,8 +39,9 @@ unsafe fn main_0() -> i32 { assert!((((*p).x) == (3))); assert!((((*p).y) == (4))); assert!( - (match (*(&mut a as *mut Option>)) + (match (&mut a as *mut Option>) .as_mut() + .and_then(|__a| __a.as_mut()) .and_then(|__b| __b.downcast_mut::()) { Some(__v) => __v as *mut i32, @@ -53,8 +55,9 @@ unsafe fn main_0() -> i32 { }; assert!((((*q).x) == (5))); assert!( - (((*match (*(&mut a as *mut Option>)) + (((*match (&mut a as *mut Option>) .as_mut() + .and_then(|__a| __a.as_mut()) .and_then(|__b| __b.downcast_mut::()) { Some(__v) => __v as *mut Point, @@ -64,8 +67,9 @@ unsafe fn main_0() -> i32 { ); let mut b: Option> = Some(Box::new(7)); assert!( - ((*match (*(&mut b as *mut Option>)) + ((*match (&mut b as *mut Option>) .as_mut() + .and_then(|__a| __a.as_mut()) .and_then(|__b| __b.downcast_mut::()) { Some(__v) => __v as *mut i32, @@ -75,8 +79,21 @@ unsafe fn main_0() -> i32 { b = None; assert!(!(b.is_some())); assert!( - (match (*(&mut b as *mut Option>)) + (match (&mut b as *mut Option>) .as_mut() + .and_then(|__a| __a.as_mut()) + .and_then(|__b| __b.downcast_mut::()) + { + Some(__v) => __v as *mut i32, + None => std::ptr::null_mut(), + }) + .is_null() + ); + let mut n: *mut Option> = std::ptr::null_mut(); + assert!( + (match n + .as_mut() + .and_then(|__a| __a.as_mut()) .and_then(|__b| __b.downcast_mut::()) { Some(__v) => __v as *mut i32,