新闻详情

新闻详情

首页 / 资讯中心 / 详情

Foundry Cast 深度解析:`cast from-rlp` 如何修复深度嵌套 RLP 列表的栈溢出

发布时间:2026/9/16 0:21:35来源:尧图网络
Foundry Cast 深度解析:`cast from-rlp` 如何修复深度嵌套 RLP 列表的栈溢出
Foundry Cast 深度解析cast from-rlp如何修复深度嵌套 RLP 列表的栈溢出【免费下载链接】foundryFoundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.项目地址: https://gitcode.com/GitHub_Trending/fo/foundry导读本篇文章围绕 Foundry 项目 changelog 条目 cast-deeply-nested-rlp.md 展开深入剖析cast from-rlp命令针对“深度嵌套 RLP 列表导致栈溢出”这一缺陷的修复方案。文章以该变更记录为核心结合 rlp_converter.rs 的实现细节与 conversions.rs 中的回归测试讲解 RLP 编解码的递归风险、迭代式显式栈解码、非递归析构与格式化等工程实践。读完本文你将理解cast from-rlp/cast to-rlp的完整使用方式掌握如何在 Rust 中安全处理任意深度嵌套的递归数据结构并能看懂 Foundry 针对此类问题的测试设计思路。RLP 与 cast 的 RLP 编解码命令RLPRecursive Length Prefix递归长度前缀是以太坊底层使用的序列化格式用于编码区块、交易、收据等核心数据结构。它的“递归”特性在于一个列表中可以嵌套任意层级的字符串与子列表因此一条 RLP 数据的结构天然是一棵深度可变的树。Foundry 的 cast 工具提供了两条配套命令位于 opts.rscast to-rlp可见别名--to-rlp把 JSON 数组/十六进制字符串编码为 RLP 十六进制。cast from-rlp可见别名--from-rlp把 RLP 十六进制解码为嵌套的 JSON 数组。可选--as-int别名--int将 RLP 数据整体当作大整数解码。两者的命令行帮助注释给出了最基本的往返示例见 opts.rscast to-rlp []→0xc0cast to-rlp 0x22→0x22cast to-rlp [\0x61\]→0xc161cast to-rlp [\0xf1\, \f2\]→0xc481f181f2其中0xc0是空列表的 RLP 编码0xc0为短列表头0xc161表示“包含一个字节0x61的列表”与 conversions.rs 中的 CLI 测试断言完全一致。从命令分发代码 args.rs 可以看到from-rlp的实现路径先将输入做十六进制解码失败时报Could not decode hex随后在--as-int模式下调用U256::decode否则调用crate::rlp_converter::Item::decode得到一棵Item树再to_string()输出为 JSON 风格文本。可见核心的递归结构定义与解码逻辑全部收敛在rlp_converter.rs中这正是本次补丁的修改对象。问题背景深度嵌套列表为何会撑爆调用栈在修复之前cast from-rlp对 RLP 列表的解析采用的是“一个函数对应一层递归”的朴素实现遇到列表就递归调用自身进入子列表返回时再逐层组装父列表。这种写法在正常情况下没有问题但 RLP 格式允许攻击者或恶意数据构造出极深的嵌套层级——例如一万层“列表套列表”。此时每次递归都要压入新的栈帧调用栈会被迅速耗尽程序以stack overflow崩溃退出。这个风险并不只存在于解码阶段。即便解码成功得到的Item树本身依然是深层嵌套的后续两处看似“自然”的递归同样会触发栈溢出析构DropRust 中递归结构体的默认析构会递归释放子节点。changelog 原文cast-deeply-nested-rlp.md点明“防止cast from-rlp在深度嵌套 RLP 列表上撑爆栈”而源码注释进一步说明The default recursive drop can overflow after successfully decoding deeply nested RLP——即即使解码成功默认递归析构也可能在解码完成后溢出。格式化Display把Item树输出为嵌套 JSON 文本时若按树形递归遍历同样面临相同的栈深度问题。因此这是一处需要同时在“解码、释放、格式化”三个环节消除递归的典型修复。修复核心一用显式栈做迭代式解码Item的数据结构定义在 rlp_converter.rs只有两种形态pub enum Item { Data(Vecu8), // 字符串/字节数据 Array(VecSelf), // 子列表可任意嵌套 }其Decodable实现rlp_converter.rs展示了本次修复的编码技巧——把递归调用替换为显式维护的帧栈framesimpl Decodable for Item { fn decode(buf: mut [u8]) - alloy_rlp::ResultSelf { struct ListFramea { remaining: std::vec::IntoItera [u8], // 本层剩余子项 items: VecItem, // 本层已收集的子项 } let items match Header::decode_raw(buf)? { PayloadView::String(data) return Ok(Self::Data(data.to_vec())), PayloadView::List(items) items, }; let mut frames vec![ListFrame { remaining: items.into_iter(), items: Vec::new() }]; loop { // 从栈顶帧取下一个子项取尽则弹栈组装 Array 交给父帧 let Some(encoded) frames.last_mut().unwrap().remaining.next() else { let frame frames.pop().unwrap(); let item Self::Array(frame.items); if let Some(parent) frames.last_mut() { parent.items.push(item); continue; } return Ok(item); // 栈中只剩一层时即为最终结果 }; // 子项仍是列表则压入新帧字符串则直接收进当前帧 match Header::decode_raw(mut encoded[..])? { PayloadView::String(data) { frames.last_mut().unwrap().items.push(Self::Data(data.to_vec())); } PayloadView::List(items) { frames.push(ListFrame { remaining: items.into_iter(), items: Vec::new() }); } } } } }这段代码的要点在于借助alloy_rlp的Header::decode_raw与PayloadView先解析 RLP 头部若是字符串PayloadView::String直接构造Item::Data返回若是列表PayloadView::List则拿到这一层的子项切片迭代器。程序维护frames: VecListFrame作为堆上的显式调用栈遇到嵌套列表就push一个新帧当前层处理完毕就pop并组装成Item::Array交给父帧直到栈中只剩根帧并返回。整个解码过程没有函数递归无论嵌套多少层每次循环都只操作栈顶帧栈空间消耗与层级深度无关。这种“用Vec模拟调用栈、把递归改写为循环”的模式是处理深度不受控的递归数据的通用解法也是本次补丁对 rlp_converter.rs 的核心改造。修复核心二非递归 Drop 与任务栈式格式化解码只是第一道关口。修复同时覆盖了解码之后的两处隐患。析构阶段的非递归展开。Item实现了自定义Droprlp_converter.rs用pending向量显式收集待释放的节点迭代地把每个Array的子节点展开到pending尾部从而避免递归式析构impl Drop for Item { fn drop(mut self) { let Self::Array(items) self else { return }; let mut pending std::mem::take(items); while let Some(mut item) pending.pop() { if let Self::Array(children) mut item { pending.append(children); } } } }这样即使是解码成功的万层嵌套Item树其内存释放过程也始终运行在常量级栈空间内不会在解码“成功”之后又因析构崩溃。格式化阶段的非递归输出。Item的Display实现rlp_converter.rs同样弃用了递归写法改用Task枚举任务栈输出一个数组时把Close收右括号压栈再逆序压入各子项的Item任务与Comma任务循环弹栈逐个写出。Data以0x...十六进制字符串形式输出Array以[...]嵌套形式输出最终得到可直接阅读的 JSON 风格文本。至此解码、析构、格式化三处递归全部被消除cast from-rlp在任意深度的 RLP 输入下都能稳定运行。回归测试如何验证一万层嵌套不再崩溃本次补丁在 CLI 集成测试中加入了专门的回归用例位于 conversions.rs。值得注意的不仅是“测了什么”更是“怎么构造测试数据”由于测试进程自身也有调用栈上限若用递归方式去编码一万层嵌套列表测试代码本身就会先栈溢出。因此测试采用迭代方式逐层构造 RLP 头// Build the RLP encoding of 10,000 nested single-item lists without recursively encoding it. const NESTING_DEPTH: usize 10_000; let mut encoded_len 1; let mut headers Vec::with_capacity(NESTING_DEPTH); for _ in 0..NESTING_DEPTH { let mut header Vec::new(); Header { list: true, payload_length: encoded_len }.encode(mut header); encoded_len header.len(); headers.push(header); } // 逆序拼接各层头部最后补一个空字符串项 0x80 let mut deeply_nested Vec::with_capacity(encoded_len); for header in headers.iter().rev() { deeply_nested.extend_from_slice(header); } deeply_nested.push(0x80); cmd.cast_fuse().arg(--from-rlp).stdin(hex::encode_prefixed(deeply_nested)).assert_success();该用例通过 stdin 把深度为 10,000 的嵌套 RLP 喂给--from-rlp断言命令成功退出且无栈溢出。这一万层数据正是对“解码、析构、格式化”全链路非递归化的端到端验证。同一测试还覆盖了常规的往返与边界行为conversions.rs命令输入期望输出cast from-rlp0xc0[]cast from-rlp0x0f0x0fcast from-rlp0x330x33cast from-rlp0xc161[0x61]cast from-rlp8200020x0002cast from-rlp000x00cast to-rlp[]0xc0cast to-rlp0x220x22cast to-rlp[0x61]0xc161cast to-rlp[0xf1, f2]0xc481f181f2其中820002是一段 2 字节字符串0002的 RLP 编码82为长度头普通模式下原样保留前导零输出0x0002而在--as-int模式下则会被拒绝。这与rlp_converter.rs单元测试rlp_datarlp_converter.rs中针对 foundry-rs/foundry issue #9197 的回归保持一致。边界行为--as-int与非规范整数from-rlp的--as-int模式走的是另一条路径args.rs直接对整段字节做U256::decode并输出十进制字符串而不是构造Item树。该模式对非规范整数编码即带有前导零的大整数持严格态度。CLI 测试from_rlp_rejects_noncanonical_integersconversions.rs验证了820002与00在--as-int下均以Error: leading zero失败退出——这正是 issue #9197 所描述的歧义场景同一段 RLP 既可以解释为“字节串”也可以解释为“大整数”cast 选择在整数模式下拒绝含前导零的非规范形式避免语义混淆。对于普通非--as-int模式value_to_itemrlp_converter.rs则定义了 JSON 侧到Item的转换规则与to-rlp命令共用null映射为空数据、数字按U256取规范字节、字符串按十六进制解码、数组递归转换布尔值与对象{}不被 RLP 支持直接报错。这与to-rlp的“输入是十六进制编码字符串或十六进制编码字符串数组可任意递归”opts.rs的文档说明互为印证。总结从一条补丁记录看递归安全的工程范式.changelog/cast-deeply-nested-rlp.md虽然只是一行简短的补丁说明但其背后是三类典型的递归安全隐患及其系统性解法解码阶段用显式帧栈VecListFrame改写递归下降栈开销与嵌套深度解耦析构阶段自定义Drop以迭代方式展开子节点防止“解码成功但释放崩溃”格式化阶段以任务栈Task枚举替代树形递归输出。与之配套的测试则演示了如何构造深度 10,000 的 RLP 输入而不让测试自身溢出并同步覆盖普通往返、长数据from_rlp_long、非规范整数拒绝等边界。这一整套模式对任何需要解析“深度不可控的递归格式”如 JSON、XML、表达式树的 Rust 项目都具有直接参考价值。若要进一步研读实现与测试可依次查看 rlp_converter.rs、args.rs、opts.rs 与 conversions.rs。【免费下载链接】foundryFoundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.项目地址: https://gitcode.com/GitHub_Trending/fo/foundry创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

基于STC89C52RC的数字IC测试仪设计与实现 2026/9/16 1:09:43

基于STC89C52RC的数字IC测试仪设计与实现

简介:这是一套面向电子类专业学生与单片机初学者的51单片机集成芯片测试仪完整开发资料,解决74系列中小规模数字芯片(14引脚以内)快速功能验证与教学实操需求,适用于课程设计、电子实训及嵌入式入门项目。资源共36个文…

阅读更多 →
STM32指纹密码锁开发实战:AS608模块对接、GSM报警与矩阵键盘设计 2026/9/16 1:09:43

STM32指纹密码锁开发实战:AS608模块对接、GSM报警与矩阵键盘设计

简介:这套STM32指纹密码锁程序是一套完整的嵌入式安全系统方案,主要面向智能锁开发者、电子设计竞赛学生以及物联网爱好者,将AS608指纹识别、GSM远程报警、密码管理与蜂鸣器本地告警集于一体,适用于家庭门禁、办公安防等场景。资源…

阅读更多 →
做课件用这15大网站避坑指南 2026/9/16 1:09:43

做课件用这15大网站避坑指南

做课件用这15大网站避坑指南 模板网站太丑,改起来还费劲,做出来的课件毫无专业感,这是很多培训讲师和HR的噩梦。别急着骂设计师,很多时候是选错了工具。这份避坑指南,直接给你拆解15个主流平台的底层逻辑。 五大类课件平台定位与核心差异…

阅读更多 →
VS配置RTKLIB卫星定位开源代码环境:从源码编译到工程集成 2026/9/16 1:09:43

VS配置RTKLIB卫星定位开源代码环境:从源码编译到工程集成

搞卫星定位的人,几乎没有不知道 RTKLIB 的。这套由日本学者开发维护了近二十年的开源程序库,从 GPS 时代的双频 RTK,到现在支持 GPS/BDS/Galileo/GLONASS/QZSS 多系统的 PPP/RTK 解算,说是 GNSS 领域的一部活字典也不过分。但真正…

阅读更多 →
RealtimeSTT FastAPI 浏览器流式服务器深度实战:多用户 WebSocket 实时语音转写架构与引擎配置指南 2026/9/16 1:09:43

RealtimeSTT FastAPI 浏览器流式服务器深度实战:多用户 WebSocket 实时语音转写架构与引擎配置指南

RealtimeSTT FastAPI 浏览器流式服务器深度实战:多用户 WebSocket 实时语音转写架构与引擎配置指南 【免费下载链接】RealtimeSTT A robust, efficient, low-latency speech-to-text library with advanced voice activity detection, wake word activation and ins…

阅读更多 →
BiSheng 租户用户管理模型收敛:从 UserTenant 到主部门派生的 UI/API 对齐实战(F024) 2026/9/16 1:06:43

BiSheng 租户用户管理模型收敛:从 UserTenant 到主部门派生的 UI/API 对齐实战(F024)

BiSheng 租户用户管理模型收敛:从 UserTenant 到主部门派生的 UI/API 对齐实战(F024) 【免费下载链接】bisheng BISHENG is an open LLM devops platform for next generation Enterprise AI applications. Powerful and comprehensive featu…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞