ARTICLE DETAIL

资讯详情

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

CodeQL C 提取器对函数指针的支持:`FunctionPointerType` 与 `FunctionPointerCall` 的实现与查询实战

CodeQL C 提取器对函数指针的支持:`FunctionPointerType` 与 `FunctionPointerCall` 的实现与查询实战 静态分析SAST应用安全漏洞扫描代码质量【免费下载链接】codeqlCodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security项目地址https://gitcode.com/gh_mirrors/co/codeql点击查看免费下载导读C# 9.0 引入的delegate*函数指针语法让托管代码可以直接获得非托管函数地址是高性能与互操作场景的重要能力。本文以 csharp/old-change-notes/2021-01-19-Function-pointer.md 为主线剖析 CodeQL 仓库中 C# 提取器如何抽取函数指针类型FunctionPointerType与函数指针调用FunctionPointerCall并结合源码实体、TRAP 事实表、QL 库类与测试用例给出可复制、可运行的查询实践帮助你理解并复用这套语义模型。变更背景与能力概览在 C# 9 / .NET 5 中delegate*T函数指针是全新的语言特性。它不经过委托delegate的分配开销而是直接保存指向方法的地址并支持managed、unmanaged及unmanaged[Cdecl|Stdcall|...]等多种调用约定calling convention。该变更记录仅两条要点却是整个提取链路的起点新增类型实体FunctionPointerType对应符号接口IFunctionPointerTypeSymbol新增调用表达式实体FunctionPointerCall用于描述对函数指针的调用。在仓库中这条链路横跨四个层面层面位置作用Roslyn 符号IFunctionPointerTypeSymbol提供签名、调用约定等信息源提取器实体FunctionPointerType.cs将符号落成 TRAP 事实QL 库类Type.qll、Call.qll向查询作者暴露类型化 API测试用例FunctionPointer.ql 与 FunctionPointer.cs校验提取与查询结果提取器实现从符号到 TRAP 事实类型实体FunctionPointerType提取器在 Entities/Types/FunctionPointerType.cs 中定义该实体其关键职责有三ID 生成WriteId借助 Roslyn 的Symbol.BuildTypeId构造类型 ID再追加;functionpointertype后缀从而与其他类型实体区分。这意味着在数据库中用function_pointer_type表关联的实体拥有可辨识的稳定标识。调用约定抽取Populate写入function_pointer_calling_conventions(this, (int)Symbol.Signature.CallingConvention)记录主调用约定随后遍历Symbol.Signature.UnmanagedCallingConventionTypes通过has_unmanaged_calling_conventions(this, i, conv.TypeRef)逐个写入非托管调用约定及其下标保留其顺序语义。类型成员抽取继续调用PopulateType(trapFile)将函数指针的返回类型、参数类型等以function_pointer_return_type等关系写入 TRAP详见下文 Type.cs。该实体还采用CachedEntityFactory工厂模式FunctionPointerTypeFactory保证同一符号在数据库构建过程中只产生唯一实体。返回类型与参数抽取在 Entities/Types/Type.cs 的PopulateType中TypeKind.FunctionPointer被映射为Kinds.TypeKind.FUNCTION_POINTER见同文件第 106 行即 QL 中TypeKind.FunctionPointer()对应的枚举值当符号是IFunctionPointerTypeSymbol时调用ExtractParametersForDelegateLikeType(trapFile, functionPointer.Signature, t trapFile.function_pointer_return_type(this, t))把函数指针签名当作类委托处理抽取其返回类型及形参列表。从源码结构看这一复用设计意味着函数指针与委托在提取器内部共享同一套参数抽取逻辑QL 端也相应地都归属Parameterizable家族。调用表达式实体FunctionPointerCall对函数指针的调用形如f(ref i, out object? o)其目标是函数指针类型的符号而非普通方法符号。提取器在 Entities/Expressions/Invocation.cs 中通过IsDelegateLikeCall统一判定当调用目标候选符号满足是函数指针symbol.Kind SymbolKind.FunctionPointerType或是委托的 Invoke 方法MethodKind.DelegateInvoke时就将其归类为类委托调用从而生成FunctionPointerCall实体而非普通方法调用。该处理同时覆盖了OverloadResolutionFailure候选符号全部为函数指针与LateBound动态调用等边缘场景避免把合法的函数指针调用误报为编译错误或模型错误ModelError。QL 库查询函数指针的公开 API类型侧 API在 csharp/ql/lib/semmle/code/csharp/Type.qll 中class FunctionPointerType extends Type, Parameterizable, function_pointer_type { ... }它同时继承Type与Parameterizable因此查询作者可以直接使用以下常用成员getAnnotatedReturnType()获取带注解如可空性的返回类型getParameter(int i)/getAnnotatedType()访问第 i 个参数及其注解类型getCallingConvention()获取主调用约定managed / unmanaged / unmanaged 变体getUnmanagedCallingConvention(int i)逐个获取非托管调用约定类型对应delegate* unmanaged[Cdecl, Stdcall, ...]列表。在 Member.qll 与 AnnotatedType.qll 中亦有对函数指针类型的相应引用使其完整融入类型系统。调用侧 API函数指针调用在 csharp/ql/lib/semmle/code/csharp/exprs/Call.qll 中被建模为FunctionPointerCallCall的子类。这使得既有的调用图分析、数据流分析如csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.ql可以直接覆盖函数指针调用而不需要查询作者为这一新语法单独编写调用边。查询实践直接可运行的 QL 示例以下查询直接取自仓库测试 FunctionPointer.ql并补充了便于观察的order by与输出列可在csharp/ql目录下对测试数据库运行1. 枚举函数指针类型、返回类型与调用约定import csharp from FunctionPointerType fpt, string returnType, string callingConvention where fpt.getAnnotatedReturnType().toString() returnType and fpt.getCallingConvention().toString() callingConvention select fpt, returnType, callingConvention order by fpt.toString()对应测试输入 FunctionPointer.cs 中的delegate*int返回intmanaged约定等声明可以验证提取结果。2. 枚举非托管调用约定import csharp from FunctionPointerType fpt, int i, string callingConvention where fpt.getUnmanagedCallingConvention(i).toString() callingConvention select fpt, i, callingConvention对应测试用例中的delegate* unmanaged[Stdcall]ref int, out object?, T, void下标 0 处应能查询到Stdcall调用约定源码第 20 行还注释展示了StdcallSuppressGCTransition等候选约定。3. 枚举函数指针的参数类型import csharp from FunctionPointerType fpt, int i, Parameter p, string t where fpt.getParameter(i) p and p.getAnnotatedType().toString() t select fpt, i, p, t order by fpt.toString(), i可覆盖ref int、out object?、in int、ref readonly int等参数修饰符组合见测试文件 M1/M3。4. 找出所有函数指针调用点import csharp from FunctionPointerCall fpc select fpc, fpc.getTarget()对应测试文件中f(ref i, out object? o)、f(ref i, out object? o, new T())等调用表达式。5. 追踪函数指针的隐式转换import csharp from ImplicitCast cast, FunctionPointerType fromType, FunctionPointerType toType where cast.getSourceType() fromType and cast.getTargetType() toType select cast, fromType, toType测试文件 M5/M6 验证了函数指针间的两种隐式转换由隐式引用转换delegate*B,A到delegate*A,B与隐式指针转换delegate*int*,void*到delegate*void*,int*触发的转换节点。测试验证与关联变更仓库中与该能力配套的测试包括库测试csharp9/FunctionPointer.ql 与 csharp9/FunctionPointer.cs 覆盖类型、调用约定、参数、调用点与隐式转换五类谓词期望输出记录在 PrintAst.expected 中数据流测试csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.ql 验证函数指针调用可以作为数据流经过的调用边委托测试delegates/PrintAst.expected 中同样出现FunctionPointerCall印证函数指针与委托共享类委托调用建模的设计。另一条关联变更 2021-01-25-Function-pointer-cil.md 则记录了 ILCIL侧对FunctionPointerType的抽取并修复了pinned、by-reference类型注解cil_type_annotation的抽取问题说明同一能力在源码级与 IL 级两条路径上均已落地。使用前提与限制语言版本函数指针是 C# 9.0.NET 5特性需要编译器与运行库支持查询函数指针相关库 API 时建议在包含 C# 9 语法测试的数据库如csharp/ql/test/library-tests/csharp9上运行unsafe上下文delegate*声明与调用通常需要unsafe上下文测试类即声明为unsafe static class Program提取与查询并不依赖运行时是否真正启用非托管代码但代码语义受此约束非托管调用约定getUnmanagedCallingConvention(i)只对unmanaged[...]形式有意义managed与无括号unmanaged形式没有该项查询时需注意下标越界为空的结果本仓库只读以上查询与测试均为查看、运行与验证用途不涉及对仓库的修改。借助本文的实体映射、QL API 与可直接运行的查询片段你可以基于 CodeQL C# 数据库进一步编写针对函数指针的调用图、类型安全或数据流分析例如检测不安全的调用约定混用、追踪函数指针指向的敏感方法等。赞分享静态分析SAST应用安全漏洞扫描代码质量【免费下载链接】codeqlCodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security项目地址https://gitcode.com/gh_mirrors/co/codeql点击查看免费下载相关推荐CodeQL C 提取器对预处理器指令的支持从 if 到 line 的完整建模CodeQL C 提取器对预处理器指令的支持从 if 到 line 的完整建模 导读 本篇文章围绕 CodeQL 仓库中 C 语言库对预处理器指令Prepr静态分析SAST应用安全漏洞扫描代码质量CANN opbase 错误码 EZ1005 深度解析算子 JSON 文件解析失败File_Operation_Error_ParseCANN opbase 错误码 EZ1005 深度解析算子 JSON 文件解析失败File_Operation_Error_Parse 本篇技术指南以 C静态分析SAST应用安全漏洞扫描代码质量从零开始扩展YKLineChartView自定义图表类型与插件开发指南从零开始扩展YKLineChartView自定义图表类型与插件开发指南 YKLineChartView是一款专为iOS开发者打造的股票K线图与分时图绘制框架上一篇macOS 免费歌词同步神器 LyricsX 完整使用指南下一篇产线停机两小时换来的教训光伏缺陷检测AI质检系统的完整搭建实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表