Rust是否会对产出常量值的Lazy提前求值致字符串混淆失效
Rust 字符串混淆属性宏高优化等级下失效问题
问题现象
正在编写可实现源码字符串混淆功能的属性宏,该宏在调试模式下运行效果符合预期,但在发布模式下完全无法起到混淆作用。
初步判断原因是编译器识别到SyncLazy始终会产出相同的固定值,因此在优化阶段直接对其做了编译期求值,该行为不符合设计预期。已尝试两种修复方案均未生效:
- 使用
black_box包裹求值逻辑,编译器未遵循该优化提示 - 启用
optimize_attribute特性,目前该特性尚未提供optimize(none)选项可供使用
最小复现代码
以下是基于cargo expand输出结果编写的复现示例:
#![feature(once_cell)] #![feature(bench_black_box)] use std::hint; use std::lazy::SyncLazy; // 闭包内逻辑均由宏生成,用于运行时还原得到原始字符串 static VAL: SyncLazy<String> = SyncLazy::new(|| { hint::black_box(String::from_utf8( [ 140, 155, 158, 142, 158, 142, 166, 156, 150, 130, 148, 171, 128, 134, 132, 150, 137, ] .iter() .enumerate() .map(|(i, e)| i as u8 ^ !e as u8) .collect::<Vec<u8>>(), )) .unwrap() }); fn main() { println!("{}", *VAL); }
测试结果
不同优化等级下的测试表现如下:
# opt-level=1 下符合预期 $ rustc -C opt-level=1 main.rs && if grep 'secret' main; then echo '"secret" is still readable'; else echo "obfuscation worked"; fi obfuscation worked # opt-level=2 下混淆失效,明文字符串直接出现在二进制中 $ rustc -C opt-level=2 main.rs && if grep 'secret' main; then echo '"secret" is still readable'; else echo "obfuscation worked"; fi grep: main: binary file matches "secret" is still readable
待解决问题
目前采用的临时解决方案是在Cargo.toml中降低发布模式的优化等级,但仍需要明确两个核心问题:
- 该优化行为的底层原理是什么?对Lazy类型做提前贪婪求值似乎违背了该类型的设计初衷,明确实际触发机制才能找到更合理的解决方案
- 是否存在可靠方案可以将求值逻辑强制推迟到运行时,无需依赖降低全局优化等级的临时方案
内容的提问来源于stack exchange,提问作者Jeremy Meadows
相关产品推荐
相关产品推荐

