惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
量子位
M
MIT News - Artificial intelligence
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Google DeepMind News
Google DeepMind News
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
雷峰网
雷峰网
I
InfoQ
罗磊的独立博客
博客园 - 聂微东
酷 壳 – CoolShell
酷 壳 – CoolShell
大猫的无限游戏
大猫的无限游戏
D
Docker
H
Hackread – Cybersecurity News, Data Breaches, AI and More
腾讯CDC
博客园 - 三生石上(FineUI控件)
The GitHub Blog
The GitHub Blog
K
Kaspersky official blog
P
Privacy & Cybersecurity Law Blog
S
SegmentFault 最新的问题
T
Threat Research - Cisco Blogs
H
Help Net Security
小众软件
小众软件
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
C
CERT Recently Published Vulnerability Notes
WordPress大学
WordPress大学
T
Tenable Blog
T
The Blog of Author Tim Ferriss
C
Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
博客园 - Franky
A
Arctic Wolf
T
Threatpost
Scott Helme
Scott Helme
C
Cybersecurity and Infrastructure Security Agency CISA
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
The Exploit Database - CXSecurity.com
G
GRAHAM CLULEY
Security Latest
Security Latest
Spread Privacy
Spread Privacy
L
LINUX DO - 热门话题
V
Vulnerabilities – Threatpost
P
Privacy International News Feed
S
Schneier on Security
Latest news
Latest news
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com

hsfzxjy 的博客

解决 VSCode + CMake + MSVC 编译器信息乱码的问题 使用 3090 部署 1.58bit 动态量化版 DeepSeek R1 671b 如何在 VS Code DevContainer 中配置 HTTP 代理 如何在跳板机背后的服务器上使用 VS Code Remote - Containers Cohesive Digests for Ints and Floats Rust 中的隐匿概念 —— Place(位置) 美术馆 一尺之槌,日取其半,1075日而竭 老生常谈:使用 Cloudflare 自选 IP 加速站点访问 辩义 State、Nation 与 Country 将 Base64 编码的数据快速转换为 Uint8Array 折腾 NPU·第1章 —— 搭建 Level Zero 开发环境 折腾 NPU·第0章 —— Intel NPU 概述与 Level-Zero 新增域名 monad.run CSS 中为特定字符设置不同字体 Dijkstra 算法的延伸 Manacher 回文计数算法 硬卧 Go Fact: Zero-sized Field at the Rear of a Struct Has Non-zero Size Display *big.Rat Losslessly and Smartly in Golang 代码的仪式 Building Electron From Scratch 中式亲属称谓研究之一:构建半群 Some Notes on Kotlin Coroutines Git sparse-checkout and partial clones for Mega-Repos 辩义“封建” Diving from the CUDA Error 804 into a bug of libnvidia-container Modern Cryptography, GPG and Integration with Git(hub) Move the Root Partition of Ubuntu A New Programmer Kicks a Roadblock Git-based Dependencies in Dart and Go Reversy Naming 人类一败涂地 Invalid Golang Pointers Can Bite You Even If You Don't Dereference Side Project(副业) A Flaw of Promoting Complex Trait Bounds in Rust Initialize Process Pool Worker with Individual Value Rust - Python FFI From Scratch [Extending Hexo For My Site] Part 1 [Extending Hexo For My Site] Part 0 Debug a 'torch.tensor(1).cuda()' hanging 不自由的互联网 Retrieve Contents over HTTP without curl or wget [Unravelling mocona] Part 1 - Verbosity or Anti-Pattern [Unravelling mocona] Part 0 - Preface Understanding pickle in Python Rough Notes on Deploying Vaultwarden & NextCloud Bookmarks 语言狂热者与实用主义者 Demystify the randomness in CUDA kernels Performant Bulk Mutations in IndexedDB Auto Rebuild .pyx Files with pyximport Cython and Threads Obtain a Random Available TCP Port with Bash Information Theory: KL Divergence Information Theory: Entropy and Mutual Information 铁板烧 西郊线 Proof of the Gumbel Max Trick Option::as_ref Rc, RefCell and Interior Mutability Visualizing Correlation 三月十日杂感 三月一日杂感 二月十一日杂感 一月二十六日杂感 SS Configuration 一月七日杂感 四月·病 Haskell 笔记:State Monad Haskell 笔记:Monad 引论 Haskell 笔记:Applicative Haskell 笔记:Category Theory and Functor Haskell 笔记:data, type, newtype Haskell 笔记:folds 使用 Aria2 在 Ubuntu 中下载百度云资源 从伪并行的 Python 多线程说起 一个 Reentrant Error 引发的对 Python 信号机制的探索和思考 Linux 文件权限 HSFZMUN 4.0 部署小记 午后雨·科大 最后的雨夜·广州 揭秘·变态的平方根倒数算法 神坑·Python 装饰类无限递归 Python“黑魔法”之 Encoding & Decoding Ubuntu 重新映射键盘布局 为什么我要翻墙 Python“黑魔法”之 Generator Coroutines 数学美 之 判断线段相交的最简方法 除夕杂感 17 行代码实现的简易 Javascript 字符串模板 Python“黑魔法”之 Meta Classes 诗集 生活,需要被“发现” 家书·十八岁成人礼 炫技?还是需求? 【译】响应式图片的现状 【译】“为什么有这么多的编程语言?” Wisecity 商赛总结——也谈前端自动化测试 记一次 DoS 诈骗网站的经历 那一年,我们望向星空
Arbitary Lifetime Transmutation via Rust Unsoundness
2024-02-11 · via hsfzxjy 的博客

Do you believe that one can write a function in safe Rust which can arbitrarily change the lifetime of a reference? For clarity, try to implement the following function without using unsafe:

fn transmute_lifetime<'a, 'b>(x: &'a u64) -> &'b u64 { todo!() }

Such intention seems to violate the fundamental principle of Rust’s lifetime system, which is to prevent dangling references and data. However, it is possible to write such a function in safe Rust, and it is not even that hard:

trait Trait {
type Output;
}

impl<T: ?Sized> Trait for T {
type Output = &'static u64;
}

fn foo<'a, T: ?Sized>(x: <T as Trait>::Output) -> &'a u64 { x }

fn transmute_lifetime<'a, 'b>(x: &'a u64) -> &'b u64 {
foo::<dyn Trait<Output=&'a u64>>(x)
}

WOAH! There’s a lot of magic going on here. This is from my recent discovery of a Github issue Coherence can be bypassed by an indirect impl for a trait object, which is a quite enjoyable reading down the rabbit hole.

Let’s break down the code step by step.

The Trait trait

trait Trait {
type Output;
}

impl<T: ?Sized> Trait for T {
type Output = &'static u64;
}

The first part defines a trait Trait with an associated type Output. As a reminder, let’s recap on the concept of associated types:

  1. An associated type is a type that is associated with a trait, and must be specified by the trait implementor.
  2. The associated type of a trait is unique for each implementor, i.e., a type T cannot implement Trait<Output=O1> and Trait<Output=O2> at the same time, which is different from the generic type parameters.
  3. Given the uniqueness mentioned above, one can access the associated type of a trait by using the syntax <T as Trait>::Output, which resolves to a concrete type.

What’s interesting is that we have Trait implemented for all types T: ?Sized, in which the associated type Output is set to &'static u64. This implies for any type T, including those dynamically sized, is now a subtype of Trait, and <T as Trait>::Output should resolve to &'static u64.

Hence, we have the validity of the foo function.

fn foo<'a, T: ?Sized>(x: <T as Trait>::Output) -> &'a u64 { x }

Since <T as Trait>::Output should always be &'static u64, variable x of that type can be safely cast to &'a u64 without any lifetime issues.

So far so good, until we enter the territory of dyn ... types, aka the trait objects.

The Trait Objects

Trait objects is a way to abstract over types that implement a trait, denoted as dyn Trait which is a special type in Rust and enables dynamic dispatch at runtime. We may consider an implicit implementation is generated for every trait object type as:

impl Trait for dyn Trait { ... }

Specially, if a trait Trait contains associated types, a bare dyn Trait is not allowed. Instead we need to specify the associated types explicitly, e.g., dyn Trait<Output=...>. Similar to above, an imaginary implementation is generated for this case as:

impl<O> Trait for dyn Trait<Output=O> { type Output = O; }

Now let’s think about a question: Does trait object type belong to “any type”?

This matters since if it does, our aforementioned impl<T: ?Sized> Trait for T should also apply to dyn Trait types, which means the following implementation also exists:

impl<O> Trait for dyn Trait<Output=O> { type Output = &'static u64; }

which contradicts the previous one! Unfortunately, Rust does not prevent this from happening, and the compiler will not complain about it. By exploiting this, we can write the legendary transmute_lifetime function.

fn transmute_lifetime<'a, 'b>(x: &'a u64) -> &'b u64 {
foo::<dyn Trait<Output=&'a u64>>(x)
}

The snippet is legitimized as explained by @nikomatsakis in the Github issue:

Now the problem is that different parts of the compiler could select different impls, resulting in distinct values for Output. In @Centril’s example (#57893 (comment)), there is a helper function foo which only knows that it has some T: ?Sized, so it uses the user’s impl to resolve Output. […]

On the other hand, the transmute_lifetime function invokes foo with the type dyn Object<Output=&'a u64>. […] This winds up resolving using the “auto-generated” impl, and hence Output is normalized to &'a u64.

This problem remains unsolved since 2019 and is considered a soundness hole in Rust’s type system. The Rust team has been aware of this issue for a long time, but it is not easy to fix.


Author: hsfzxjy.
Link: .
License: CC BY-NC-ND 4.0.
All rights reserved by the author.
Commercial use of this post in any form is NOT permitted.
Non-commercial use of this post should be attributed with this block of text.