ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Pysa 端到端集成测试完全指南:基于 pyre-check 的污点分析测试体系详解

Pysa 端到端集成测试完全指南:基于 pyre-check 的污点分析测试体系详解 静态分析开发工具代码质量【免费下载链接】pyre-checkPerformant type-checking for python.项目地址https://gitcode.com/gh_mirrors/py/pyre-check点击查看免费下载导读PysaPython Static Analyzer是 pyre-check 仓库内置的污点分析引擎用于检测数据从 source 流向 sink 的安全漏洞。本文围绕.llms/skills/pysa-integration-tests/SKILL.md这份操作手册系统讲解 Pysa 端到端集成测试的完整工作流从运行命令、测试文件结构、失败调试到更新期望输出与新建测试用例并结合仓库源码integrationTest.ml 与 testHelper.ml深入剖析底层机制。读完本文你将能够在 pyre-check 仓库中独立运行、调试、更新与创建 Pysa 集成测试。Pysa 集成测试概览Pysa 的端到端集成测试用于验证污点分析引擎的完整工作链路每个测试是一个位于source/interprocedural_analyses/taint/test/integration/目录下的.py文件测试运行完整污点分析流水线类型检查 → 调用图构建 → 高阶调用图 → 覆盖图 → 污点不动点求解并将输出与期望文件.models、.cg、.hofcg、.overrides逐字比较。从源码结构看测试入口位于 integrationTest.ml当设置了PYSA_INTEGRATION_TEST环境变量时仅运行指定的单个测试否则通过TestHelper.end_to_end_test_paths扫描目录下所有*.py文件批量执行。核心的比对逻辑集中在 testHelper.ml 的end_to_end_integration_test函数中它负责读取被测源码、解析模型与配置、初始化环境、执行分析并生成/比对期望文件。运行测试所有命令必须在source/目录下执行dune exec依赖当前目录定位测试根路径cd source # 运行全部测试16 个分片并行 OUNIT_SHARDS16 dune exec interprocedural_analyses/taint/test/integrationTest.exe # 仅运行单个测试以 format.py 为例 PYSA_INTEGRATION_TESTformat.py dune exec interprocedural_analyses/taint/test/integrationTest.exe环境变量说明OUNIT_SHARDS16OUnit 测试框架的分片数用于并行加速。原文档强调不设置该变量时全量测试会明显变慢。PYSA_INTEGRATION_TEST精确指定要运行的测试文件。从 integrationTest.ml 的源码可以看到该变量被读取后与测试目录source/interprocedural_analyses/taint/test/integration/拼接成完整路径再交给TestHelper.end_to_end_integration_test执行。PYREFLY_BINARY指定自定义 Pyrefly 前端二进制见下文。使用 Pyrefly 前端运行pyre-check 的污点分析流水线支持两种前端传统的 Pyre1 前端与新一代 Pyrefly 前端。执行./facebook/scripts/setup.sh --local后Pyrefly 成为默认后端集成测试会自动使用source/pyrefly.exe。如需覆盖为自定义二进制PYREFLY_BINARYpath-to-binary PYSA_INTEGRATION_TESTformat.py dune exec interprocedural_analyses/taint/test/integrationTest.exe从 testHelper.ml 可以看到测试初始化默认以~force_pyrefly:true运行。Pyrefly 前端的一个显著差异是它不会类型检查未被源码文件传递包含的模块见filter_unused_test_modules_errors的注释与实现testHelper.ml因此测试框架会过滤掉pysa、django等初始模型模块的 BaseModuleNotInEnvironment 类验证错误。测试文件结构每个测试name.py可以有如下伴随文件文件是否必需用途name.py是待分析的 Python 源码name.py.pysa否Pysa 模型文件声明 sources、sinks、TITO 等name.py.config否污点配置规则rules、sources、sinks、optionsname.py.models是期望输出污点模型与问题报告JSONname.py.cg是期望输出调用图call graphname.py.hofcg是期望输出高阶调用图higher-order call graphname.py.overrides是期望输出覆盖图override graphname.py.pyrefly.models否Pyrefly 前端下的期望模型输出name.py.pyrefly.cg否Pyrefly 前端下的期望调用图输出name.py.pyrefly.hofcg否Pyrefly 前端下的期望高阶调用图输出name.py.pyrefly.overrides否Pyrefly 前端下的期望覆盖图输出默认测试模型机制当测试文件同时没有.pysa模型文件和.config配置文件时测试运行器会自动注入默认测试模型如_test_sink、_test_source等。这一逻辑在 testHelper.ml 中体现为let add_initial_models Option.is_none models_source Option.is_none taint_configuration in即只有两者都不存在时才启用默认模型。这些默认模型定义在initial_models_source字符串中testHelper.ml包括def pysa._test_sink(arg: TaintSink[Test, Via[special_sink]]): ... def pysa._test_source() - TaintSource[Test, Via[special_source]]: ... def pysa._tito( *x: TaintInTaintOut, **kw: TaintInTaintOut): ... def pysa._user_controlled() - TaintSource[UserControlled]: ... def pysa._cookies() - TaintSource[Cookies]: ... def pysa._rce(argument: TaintSink[RemoteCodeExecution]): ... def pysa._sql(argument: TaintSink[SQL]): ... def eval(source: TaintSink[RemoteCodeExecution], /): ... pysa._global_sink: TaintSink[Test] ... pysa.ClassWithSinkAttribute.attribute: TaintSink[Test] ...一旦提供了.pysa或.config中的任意一个测试就必须自包含即自行声明所需的全部模型与配置不再依赖默认模型。这正是原文档强调的 the test must be self-contained 的源码依据。配置与模型文件实例一个典型的.config文件以 add_breadcrumb_to_state.py.config 为例包含 sources、sinks、features 与 rules 四个区块{ sources: [ { name: Test } ], sinks: [ { name: Test } ], features: [ { name: special_sink, comment: From _test_sink() }, { name: special_source, comment: From _test_source() }, { name: add_breadcrumb_to_state, comment: From add_breadcrumb_to_state() } ], rules: [ { name: Test, sources: [Test], sinks: [Test], code: 5002, message_format: Data from [{$sources}] source(s) may reach [{$sinks}] sink(s) } ] }配套的.pysa模型文件则声明具体函数与类的污点语义add_breadcrumb_to_state.py.pysadef pysa._test_sink(arg: TaintSink[Test]): ... def pysa._test_source() - TaintSource[Test]: ... AddBreadcrumbToState(Via[add_breadcrumb_to_state]) def add_breadcrumb_to_state.add_breadcrumb_to_state(): ... AddBreadcrumbToState(Via[add_breadcrumb_to_state]) def add_breadcrumb_to_state.BreadcrumbOnEnter.__enter__(): ...期望输出文件示例以 format.py.models 为例期望输出是generated开头的换行分隔 JSONNDJSON每条记录描述一个 callable 的模型信息包括端口port、污点种类kinds与模式modesgenerated { kind: model, data: { callable: builtins.eval, filename: builtins.pyi, callable_line: 4540, sinks: [ { port: formal(source, position0, positional_only), taint: [ { kinds: [ { kind: RemoteCodeExecution } ], declaration: null } ] } ], modes: [ Obscure ] } }调用图文件format.py.cg则以 JSON 映射形式列出每个 callable 的调用依赖generated Call dependencies { format.issue_in_format (fun): [ builtins.object.__repr__ (method), pysa._test_sink (fun), pysa._test_source (fun) ], ... }这些文件的生成逻辑位于 testHelper.ml.cg由CallGraph.WholeProgramCallGraph.to_target_graph序列化而来.hofcg由 fixpoint 状态中非空的高阶调用图聚合而成.models则由TaintReporting.fetch_and_externalize产出并通过NewlineDelimitedJson逐行序列化。调试测试失败当测试因期望输出不匹配而失败时测试运行器会打印差异diff对于大型 diff 可能被截断它会为每个不匹配的输出创建.actual文件例如format.py.models.actual使用diff命令对比期望与实际输出diff source/interprocedural_analyses/taint/test/integration/format.py.models \ source/interprocedural_analyses/taint/test/integration/format.py.models.actual底层实现印证了这一流程在 testHelper.ml 中get_expected读取期望文件——若期望文件不存在则直接写入当前输出首次运行自动生成若两者相等则清理旧的.actual文件若不等则写入.actual文件并记入divergent_files列表最终所有差异文件统一通过error_on_actual_files打印 diff 并以断言失败收尾。如果测试失败伴随的是类型错误或分析错误而非输出不匹配则问题出在 Python 源码或模型定义本身。此时应检查被测文件是否存在类型标注问题、.pysa中的模型写法是否与目标 callable 匹配、.config中的规则引用是否一致。注意initialize阶段会调用initialize_pyre_and_fail_on_errorstestHelper.ml一旦被测源码存在类型错误测试会直接以failwithf抛错列出错误位置与描述。更新期望文件当分析逻辑被有意修改、输出变化符合预期时需要更新期望文件facebook/scripts/in_path/pysa-update-expected该脚本会自动把所有.actual文件移动到对应的期望文件位置即用name.py.ext.actual替换name.py.ext。务必先 review diff 再更新——运行sl diff核对变更是否符合预期避免把意外的行为变化固化进期望文件。此外原文档特别提醒期望文件带有generated标记严禁手工编辑应一律通过pysa-update-expected更新。创建新测试在source/interprocedural_analyses/taint/test/integration/下新建一个测试的完整步骤创建name.py被测 Python 源码可选地创建name.py.pysa模型文件与/或name.py.config污点配置运行测试——首次运行时运行器会自动创建缺失的期望输出文件PYSA_INTEGRATION_TESTname.py dune exec interprocedural_analyses/taint/test/integrationTest.exe这一步的自动生成机制已在前文说明期望文件缺失时create_expected_and_actual_files会以~initial:true直接把实际输出写入期望路径testHelper.ml仔细审查生成的.models、.cg、.hofcg、.overrides四个文件确认污点模型、调用图、高阶调用图与覆盖图符合预期将源码与全部伴随文件一起提交。一个良好的参考范例是 format.py它覆盖了 f-string 格式化场景下的污点传播source 进入格式串、sink 出现在格式串、格式说明符中的 source/sink、以及 source→sink 的完整 issue并且该测试不带.pysa与.config文件完全依赖默认测试模型运行。常见错误清单原文档总结的常见失误如下务必规避环境变量名写错正确的变量是PYSA_INTEGRATION_TEST不是PYSA_TEST或类似名称。从 integrationTest.ml 可以看出运行时只读取PYSA_INTEGRATION_TEST这一确切键名。忘记.py扩展名应使用PYSA_INTEGRATION_TESTformat.py而不是format。环境变量值会与测试目录路径直接拼接缺少扩展名会导致文件查找失败。在错误的目录下运行dune exec必须在source/下执行因为测试目录常量是相对路径source/interprocedural_analyses/taint/test/integration/integrationTest.ml并在Test.find_pyre_source_code_root ()解析出的仓库根下拼接。猜测 OUnit 过滤参数不要用-- format这类 OUnit 参数来过滤测试应使用PYSA_INTEGRATION_TEST环境变量——这是唯一受支持的过滤方式。手工编辑期望文件期望文件都是generated生成物应使用pysa-update-expected更新不要直接改文件内容。忘记OUNIT_SHARDS全量运行时不加OUNIT_SHARDS16会慢得多并行分片是官方推荐的运行方式。小结Pysa 集成测试是 pyre-check 污点分析质量保障的核心手段其源码 模型 配置 四类期望输出的文件约定清晰、自动化程度高首次运行自动生成期望文件、失败自动产出.actual供 diff 对比。本文所述的运行、调试、更新与创建流程与 integrationTest.ml 和 testHelper.ml 中的实现一一对应读者可直接在仓库的source/interprocedural_analyses/taint/test/integration/目录中动手实践修改一个测试的源码或模型运行单测观察.actual的产生再通过pysa-update-expected完成期望文件更新即可完整走通 Pysa 集成测试的迭代闭环。赞分享静态分析开发工具代码质量【免费下载链接】pyre-checkPerformant type-checking for python.项目地址https://gitcode.com/gh_mirrors/py/pyre-check点击查看免费下载相关推荐Windows 激活怎么做3 分钟用 MAS 免费激活 Windows 和 OfficeWindows 激活怎么做3 分钟用 MAS 免费激活 Windows 和 Office 系统右下角挂着未激活的水印打开 Office 还弹提醒条Mi操作系统Electric 集成测试指南基于 lux 的多组件端到端测试体系解析Electric 集成测试指南基于 lux 的多组件端到端测试体系解析 导读本文以 integration tests/README.md https://后端数据同步数据库人工智能AI AgentMCP 服务PredictionIO 集成测试框架解析基于 pio_tests 的端到端测试体系与实战指南PredictionIO 集成测试框架解析基于 pio_tests 的端到端测试体系与实战指南 导读 PredictionIO 是一个面向开发者和机器学习工程机器学习后端推荐系统上一篇终极指南Shairport Sync音频延迟测量与同步优化方法下一篇Realtek RTL8125 2.5G网卡驱动终极配置指南3步实现高效网络加速创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表