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

推荐订阅源

F
Fortinet All Blogs
S
Secure Thoughts
月光博客
月光博客
美团技术团队
雷峰网
雷峰网
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
N
News and Events Feed by Topic
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Forbes - Security
Forbes - Security
W
WeLiveSecurity
P
Proofpoint News Feed
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿
G
GRAHAM CLULEY
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AI
AI
Last Week in AI
Last Week in AI
Google Online Security Blog
Google Online Security Blog
Schneier on Security
Schneier on Security
云风的 BLOG
云风的 BLOG
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Recent Announcements
Recent Announcements
Webroot Blog
Webroot Blog
T
Tor Project blog
Cisco Talos Blog
Cisco Talos Blog
N
News and Events Feed by Topic
罗磊的独立博客
The Register - Security
The Register - Security
Blog — PlanetScale
Blog — PlanetScale
T
Threat Research - Cisco Blogs
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
T
The Exploit Database - CXSecurity.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
B
Blog
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Engineering at Meta
Engineering at Meta
Latest news
Latest news
IT之家
IT之家
D
DataBreaches.Net
博客园 - 司徒正美
N
Netflix TechBlog - Medium
V
V2EX
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

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.