把写代码想成养身体:程序员的每一段源代码,都是一个日夜运转的“小生命”。它有没有隐疾?是不是吃进了不干净的东西?传统做法是把它拉到操场上跑几圈——也就是把程序运行起来,用测试用例观察它在运动中的表现。可有些毛病,比如血管里的脂肪、骨架的歪斜,不剧烈运动根本看不出来,等发作时往往已经晚了。 静态分析(Static Analysis)提供了一条更聪明的路径:像全面体检一样,不跑、不动,只抽一管血、拍几张片——把源代码从头到尾读一遍,就能在发病前把问题揪出来。这套“体检”有固定的流程:先量血压查血常规(词法分析),再拍 X 光看骨架(语法分析),把结构画成骨架图(抽象语法树),顺着血管追踪血液流向(数据流分析),检查有没有食物中毒的入口(污点分析),最后把每个指标跟一本临床手册逐条对照(规则引擎)。当这一切成为每日例行,你便拥有了一个永不疲倦的“私人保健医生”。
在 AI 工程化时代,代码产量爆炸式增长,人工评审难以为继。掌握静态分析,等于拥有火眼金睛的自动巡检员,能把安全漏洞和坏味道拦在合并之前,是 AI 工程师守护生产代码质量的必修课。
可视化演示
展示词法分析Token化、语法分析AST构建及语义分析污点传播三阶段静态分析流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
词法分析Token化 正则表达式将源代码拆分为Token序列 标识符/运算符/数字分类标注 source → regex → [Token] 词法分析是静态分析流水线第一阶段
概念与意义
体检的中心思想是:很多健康问题,在你还活蹦乱跳时就已经写在了化验单上。静态分析也一样——它坚持“不运行代码”这条铁律,只把源代码当作一份体检样本,逐行逐句地读。你不需要为它准备测试数据、不需要启动服务,把代码文件丢给它,它就能告诉你哪些地方可能藏雷。
所谓“静态”,是与“动态”相对。动态分析要跑程序、喂输入、看运行结果;静态分析则通通不做,只做“读”和“想”两件事。读的是源码文本,想的是根据语言规则推导出的种种可能性。这种差异决定了它的独特价值:早、全、稳。早,是代码尚未运行就能发现缺陷,修复成本最低;全,是可以把整个代码库从头到尾扫一遍,不会像人工评审那样疲劳遗漏;稳,是规则确定,同样的问题每次都会被抓住。
当然,静态分析也面临两大指标考验:精确率(别误报)与召回率(别漏报)。评估一个工具是否值得信赖,就看这两项指标:
回到体检的比喻:精确率低的体检中心,天天吓唬你“疑似肿瘤”,跑几次复查全是虚惊;召回率低的体检中心,漏掉了早期病灶,第二年再来已是晚期。好的静态分析工具,追求的是既不瞎报警、也不漏真雷——这正是它在工程中能否被信任的关键。
- 真阳性 TP工具报告了问题,且确认是真实缺陷。这是工具“说得对”的时刻。
- 误报 FP工具报告了问题,但代码其实是健康的。误报太多会让人对工具失去信任。
- 漏报 FN代码里存在真实缺陷,工具却没报出来。这是最危险的,因为你会误以为代码安全。
- 精确率公式精确率 = 真阳性 ÷(真阳性 + 误报),衡量报告的可信度。
- 召回率公式召回率 = 真阳性 ÷(真阳性 + 漏报),衡量捕获缺陷的完整度。
词法语法分析
体检的第一步,永远是“数据采集”:护士量身高、测体重、抽血,机器把血样分离成红细胞、白细胞、血小板。词法分析所做的,就是把源代码这管“血”分离成一个个最小单元——Token(词法记号)。
比如 y = speed + 1 这行代码,在词法分析器眼里并不是一长串字符,而是五个 Token:y(标识符)、=(运算符)、speed(标识符)、+(运算符)、1(数字字面量)。每个 Token 还带着自己的“身份证”:类型、文本内容、所在行列。无论是关键字、变量名、数字还是括号,都会被精准分类,就像化验单上每一项指标都有明确的名称和单位。
Token 切好之后,语法分析器登场。它像一位结构科医生,把 Token 序列与语言的语法规则做比对,判断“这组词的排列合不合语法”。如果程序员忘了分号、括号不配对,语法分析会立刻给出报错位置。这一步的产出,是一个描述语句结构的骨架——为下一步的抽象语法树做准备。语法规则本身可以用一种类似“配方”的方式描述:
回到体检:血常规报告上的每一项都有参考范围,化验单才具有诊断价值。Token 就是代码的“血常规指标”,语法规则就是指标的正常范围。没有这两步“标准化采样”,后面的任何分析都无从谈起。
- 赋值语句等号左边一个名字、右边一个值,“把右边的值装进左边的名字”,是最常见的语句形态。
- 标识符变量、函数的名字,是代码世界的“身份证号”。
- 表达式一个能算出值的片段,可以是变量名,也可以是数字常量。
- 推导符号 →读作“由……组成”,把复杂语句拆解为基本零件,是描述语法规则的标准写法。
抽象语法树
拿到血常规、X 光片之后,医生不会只看一堆散乱数据,而是会画出一张人体结构图。抽象语法树(AST)就是代码的“人体结构图”:把一行行语句组织成一棵倒挂的树,树的根是句子的主干动作,枝杈是参与动作的主角,叶子是最基本的名字和数字。
以 x = a + b 为例,它的 AST 根节点是“赋值 =”,左孩子是变量 x,右孩子是加法 +,而 + 又有两个叶子孩子 a 和 b。整棵树的形状,精确描述了“谁被谁怎么算出来”。相比纯文本,树形结构让从属关系一目了然:谁嵌套在谁里面、谁先计算谁后计算,全都写在形状里。
有了这棵树,许多检查就变得机械而可靠:遍历整棵树,看变量有没有声明过、类型是不是匹配、代码分支有没有闭合……几乎所有静态分析都构建在 AST 之上,它是后续数据流分析、污点分析的“地基”。树有多深,决定了分析器要沿着结构走多远:
医生的骨架图比一叠散乱报告更有说服力,因为结构本身就在说话。AST 也一样:让机器“看见”代码的骨架,它才能像一位经验丰富的老医生那样,顺着骨架指出“这里关节错位、那里骨骼有裂缝”。
- 树 T 的深度从根到最深叶子的路径步数,决定分析器要沿着结构走多远。
- 递归定义整棵树的深度 = 1 加上子树中最大的深度——先算孩子,再算自己,层层递进。
- 叶子节点最底层的数字、字符串字面量,没有孩子,深度为 0。
数据流分析
体检报告里的“血脂”指标,背后是血液在血管中一刻不停的流动。代码里也有类似的东西——数据。变量被赋值、被读取、被传给函数,就像血液把养分送到各个器官。数据流分析就是给代码画一张“血液循环图”,追踪每个变量的值从哪来、到哪去。
第一步先建控制流图(CFG):把代码切成一个个“基本块”(像一段段血管),块与块之间有向箭头连接,表示执行顺序。然后,在图上玩一个传递游戏:把“某个变量在这里被定义了”这条消息,沿着箭头向后传递,直到被新的赋值覆盖。
传递的规则很经典,叫到达定值分析。对每个基本块 B,记录它内部新产生的定义 gen[B],以及会覆盖掉的定义 kill[B],然后反复迭代,直到信息收敛。若某处读变量时没有任何定义到达,就说明变量可能未经初始化——这是最常见的运行时崩溃源头之一。类似的还有活跃变量分析:一个变量的值在可能被读之前有没有机会用到,用不到就有“死代码”的味道。核心方程只有一个:
就像医生通过血液循环图判断哪个器官缺血,数据流分析通过“数据流动图”判断哪个变量“缺血”或“淤积”。程序运行中那些莫名其妙的崩溃,往往早在静态的血流图上就已露出端倪。
- gen[B]在基本块 B 内部新出现的赋值定义,相当于这段血管里新注入的“新鲜血液”。
- kill[B]B 内对某个变量再次赋值后,会覆盖掉从上游传来的旧定义——旧血液被代谢掉了。
- in[B]进入 B 时仍然“存活”的定义集合,即上游送来的还有效的信息。
- 迭代方程离开 B 时有效的信息 = 新生定义 ∪(入口带入的 − 被覆盖的),这个方程在每个基本块上反复执行,直到全网收敛。
污点分析
体检中有一类特殊关注:食物中毒。毒素从嘴进入,随血液扩散,最后可能伤及肝脏。代码世界也有“嘴”:用户的输入、网络请求、文件内容——它们从不可信的外部世界进来,如果一路不加清洗地流入 SQL 查询、命令执行等“要害器官”,就会引发注入攻击。污点分析专治这种病。
污点分析把代码里的数据分成两类:被污染的(tainted)和干净的。分析开始前,先标出“污点源”:所有外部输入 API。然后沿着数据流图的箭头追踪:污点数据传给谁,谁就被污染;传播路径上如果经过清洗函数(如参数化查询),那才算“消毒”。最终要盯住的是“汇聚点”(sink)——那些一旦接收到脏数据就会酿成大祸的危险函数。
技术实现上,污点分析在数据流方程上做文章:给每个变量增加一个“是否带毒”的标记,并用一个传递规则在图上扩散。当发现“污点源 → 传播链 → 危险汇聚点”完整连通时,就报告一条真实可复现的攻击路径。这是检测 SQL 注入、XSS、命令注入的利器。传递规则可以写成:
医生看到“患者昨天吃了没洗的蘑菇、今天肝功能异常”,会立刻建立毒素-症状因果链。污点分析干的正是这件事:它不满足于“这里有个危险函数”,而是连成一条“污染进来 → 一路流传 → 抵达要害”的完整证据链,让安全修复有据可依。
- 污染状态 T(v)变量 v 的污染标记,true 表示带毒,false 表示干净。
- 污点源 source(v)v 本身是不是外部输入,例如
input()的返回值直接标记为带毒。 - 上游节点 pred(v)在数据流图上,所有能流入 v 的前驱节点。
- 污染扩散对全部上游做并集,只要任何一个上游带毒,v 就带毒;污染沿路径一路扩散。
规则引擎匹配
体检的最后一步,是拿所有化验数据与一本厚厚的《临床诊疗手册》逐条对照:哪个指标超标了?超了多少?该不该干预?规则引擎就是静态分析的“诊疗手册”,把专家经验固化成一条条机器可执行的检查规则。
一条规则通常由三要素构成:匹配模式(在 AST 或数据流结果上找什么形状)、触发条件(什么样的上下文才算命中)、处置级别(阻断、高、中、低)。比如“禁止使用 eval”这条规则:模式就是 AST 里出现名叫 eval 的调用节点,触发条件是不在白名单中,级别是阻断。
规则引擎运行的核心是模式匹配:把 AST 的每个节点依次与规则库中的模式比对,命中即产出告警。为控制效率,匹配算法会先建立索引、按节点类型粗筛,再逐步精细比对。告警产出后还要去重、聚合、分级,最后按严重程度排序,让开发者优先处理最危险的发现。一个告警的综合评分,通常由危害等级和置信度加权得出:
手册再厚,也需要好医生来对照执行;规则再多,也需要合理的优先级。把“专家会诊的经验”沉淀成规则库,就像把一位老医生几十年的临床心得写成手册本,让每一位初级开发者在提交代码时,背后都有一位永不疲倦的“老专家”把关。
- 危害等级规则预先标注的固有危险程度,例如“代码注入”明显高于“代码风格”。
- 置信度本次匹配结果的可信度,越高越可能是真问题,用于抑制误报影响。
- 权重系数 w两个口径的权重,团队可按自身风险偏好调整比例。
- 综合评分加权求和得到 SCORE,映射为最终的告警级别和处置优先级。
工程化落地
体检的终极意义不在体检本身,而在于“每年都做、异常就治、指标入档”。静态分析唯有接入工程流程,才能真正守护代码健康。这一步的主题,是把分析工具从“偶尔用一下”变成“每次提交必过”的自动化门禁。
具体做法是接入 CI/CD 流水线:开发者提交代码或发起合并请求(MR/PR)时,流水线自动拉取最新代码、运行静态分析,并把结果反馈给提交者。质量门禁(Quality Gate)按照预设策略判定:存在阻断级告警就红灯,新引入的高危缺陷超过阈值就拦住合并。这就像机场安检:行李不过 X 光机,就不允许登机。
落地过程中有三个常见工程难点:存量告警太多,需要先建立基线、再按目录逐步清零;规则误报率高,需要建立“告警申诉 — 规则优化”闭环,让规则库持续进化;门禁过于严格则拖慢迭代,要设计“增量门禁”——只拦截新增问题,历史欠账单独跟踪。最终形成“分析 → 门禁 → 度量 → 改进”的闭环。门禁判定可以用一个分段函数描述:
一位优秀的保健医生,最终的目标是让你忘掉医院——因为健康已成为习惯。工程化的静态分析也是这样:当每一次代码提交都自动过一遍“体检”、坏味道在合并前就被拦住,团队的生产力与代码健康就不再是二选一的矛盾,而是彼此的保障。
- 阻断级告警 blocker本次提交引入的阻断级告警数,只要大于 0,门禁立即红灯。
- 新增高危数本次提交新引入的高危告警数,与历史存量无关,保证只对“新欠的债”负责。
- 容忍阈值 θ团队设定的参数,例如 θ=0 表示一个高危都不允许进主干。
- 门禁决策两条判定规则合成最终的放行/拦截决策,把质量策略变成自动化执行的代码。
AI 应用场景
场景 1:CI 质量门禁守护发布安全
阶段:工程化落地与持续集成
解决的问题:传统人工 Code Review 速度慢、覆盖不均,深夜提交的代码常常没人细看。接入静态分析门禁后,每次 PR 自动扫描,阻断级告警直接红灯,低级别告警提醒修复,把质量检查从“人肉”变成“自动化”,相当于给每次代码提交安排了一次免费的“晨间体检”。
具体案例:某互联网公司的支付团队,在 CI 中接入 SonarQube + ESLint + 自研污点分析插件,两周内将线上注入类漏洞的发现时间从“上线后数周”提前到“合并前”,发布回滚率下降 60%。
场景 2:为 AI 生成的代码把关
阶段:AI 辅助开发与模型应用
解决的问题:大模型生成代码速度快、风格各异,也时常带着训练数据里的坏味道甚至安全漏洞。若未经检查直接合入,会把隐患悄悄带进生产环境。用静态分析对 AI 生成代码做“出厂质检”,从源头拦截问题——让 AI 这位“高产医生”开出的每一张药方,都经过老专家的复核。
具体案例:一家 SaaS 公司让工程师用 Copilot 写业务代码,同时在 IDE 插件里跑实时静态检查,AI 补全的代码一旦触发高危规则立刻标红提示,开发者当场修正,合入代码的漏洞密度下降 45%。
场景 3:开源与供应链安全扫描
阶段:数据与代码安全治理
解决的问题:开源依赖里的漏洞是供应链攻击的高发地,人工审计海量第三方代码不现实。静态分析(结合 SCA 工具)自动扫描依赖树,污点分析追踪“用户可控输入是否直达危险函数”,持续监控开源组件新披露的 CVE——相当于对每一种进入身体的“外来营养品”都做成分检测。
具体案例:安全团队用 Semgrep 编写自定义规则库,对上游引入的每个开源库自动执行漏洞模式匹配,曾在一周内捕获某依赖库新版本中疑似 Log4Shell 变体的风险路径,及时阻断升级。
Python 演示
#!/usr/bin/env python3"""迷你静态分析器:演示词法分析、规则引擎与污点追踪的原理。"""import reimport sys # token 模式:标识符 / 字符串 / 数字 / 运算符 / 括号逗号分号TOKEN_RE = r'[A-Za-z_]\w*|"[^"]*"|\'[^\']*\'|\d+|[+\-*/=<>!]+|[(){}[\],;:]' def tokenize(code): """词法分析:把源码逐行切成 (类型, 文本, 行号) 的 token 列表。""" tokens = [] for lineno, line in enumerate(code.splitlines(), 1): for m in re.finditer(TOKEN_RE, line): text = m.group() if text.isdigit(): ttype = 'num' elif text[0] in "\"'": ttype = 'str' elif text.isidentifier(): ttype = 'name' else: ttype = 'op' tokens.append((ttype, text, lineno)) return tokens def rule_banned_call(tokens): """规则一:禁止调用 eval / exec 这类高危函数。""" for ttype, text, lineno in tokens: if text in ('eval', 'exec'): yield (lineno, 'blocker', '禁止调用 %s(),存在代码注入风险' % text) def rule_taint_chain(tokens): """规则二:污点分析——用户输入若流入危险函数,形成攻击路径。""" tainted = False for ttype, text, lineno in tokens: if text == 'input': tainted = True if tainted and text in ('eval', 'exec'): yield (lineno, 'blocker', '用户输入(input)流入危险函数 %s(),构成污点路径' % text) tainted = False def rule_todo_note(tokens): """规则三:提示遗留的 TODO 待办事项。""" for ttype, text, lineno in tokens: if text == 'TODO': yield (lineno, 'info', '存在未处理的 TODO 待办') RULES = [rule_banned_call, rule_taint_chain, rule_todo_note] def main(): code = sys.stdin.read() tokens = tokenize(code) findings = [] for rule in RULES: findings.extend(rule(tokens)) for lineno, level, msg in sorted(findings): print('%s [%s] %s' % (lineno, level, msg)) if not findings: print('静态检查通过,未发现问题') if __name__ == '__main__': main()
TOKEN_RE = r'[A-Za-z_]\w*|"[^"]*"|\'[^\']*\'|\d+|[+\-*/=<>!]+|[(){}[\],;:]'用一条正则定义了“词法规则”,相当于给字符流准备了一把切分词典,把标识符、字符串、数字、运算符区分开。for m in re.finditer(TOKEN_RE, line):逐行扫描源码,把字符流切成一个个带行号的 token,就像把一句中文切成一个个词语。elif text.isidentifier():判断一个词是不是合法的名字(标识符),是变量名还是函数名,为后续规则判断提供依据。def rule_taint_chain(tokens):模拟污点分析:看到input就标记“带毒”,带毒状态遇到危险函数立即报告一条污染路径。RULES = [rule_banned_call, rule_taint_chain, rule_todo_note]规则引擎把若干条独立检查函数组装成规则库,像体检手册一样按页翻开逐条核对。findings.extend(rule(tokens))逐条跑规则并合并所有发现,模拟引擎的“规则匹配 → 聚合”阶段。if __name__ == '__main__':可执行入口,支持把任意 Python 文件喂给分析器,立即得到体检报告。
常见误区
误区我以为静态分析就是写几个测试用例把程序跑起来,看会不会报错、有没有 bug。反正都是“检查代码质量”的手段,差别应该不大。
正解这是完全不同的两类检查。单元测试属于动态分析,必须真正运行程序、构造输入、观察输出;静态分析恰恰相反,它从头到尾不运行程序,只把源代码当文本做结构分析。前者像让运动员跑一次看成绩,后者像拍 X 光看骨骼:一个看表现,一个看结构。很多静态分析工具甚至不需要可运行的环境,光秃秃一份源码文件就能检查。
为何常见:初学者接触质量检查时,最先接触的是测试,容易把“检查”与“运行”画等号,忽略了“不运行也能分析”这条静态路径。
误区静态分析工具那么聪明,它报出来的每一个问题应该都是真实的 bug,直接照着修就完事了。
正解工具本质是“模式匹配 + 启发式推断”,只能给出“可能性”而非“确定性”。误报(FP)是常态:变量看似未初始化,实际被某个宏提前赋值;看似危险函数调用,实际输入早已被清洗。成熟的团队会建立“告警分流”机制:确认、误报、修改后复查,并把确认的误报反馈给规则库优化——就像体检指标偶尔出现假阳性,需要复查而不是直接开刀。
为何常见:对工具原理不了解时,容易把机器的输出当成权威结论;再加上报告的语气斩钉截铁,人很容易被带着走。
误区静态分析工具就是要把所有规则全部打开,一个隐患都不能放过,规则越多越安全。
正解规则多而不精会带来“告警疲劳”:开发者每天面对几百条噪音,很快就不再认真看报告,真正的严重问题反而被淹没在红色大海里。好的工程实践是先按行业基线开几十条高价值规则,跑通后再逐步增补;对高误报规则宁可先关闭,也不要让团队失去对工具的信任。体检套餐也不是越贵越好,而是项目越精准越好。
为何常见:安全直觉上“多多益善”,但忽略了告警噪音对人类注意力的侵蚀——工具不是决策者,而是决策支持者。
误区既然工具能自动查出这么多问题,代码评审是不是可以取消了?让机器把把关就够了。
正解静态分析擅长的是“确定性规则”:语法错误、未定义变量、已知漏洞模式。但它理解不了业务语义——为什么这么设计、有没有更好的架构、这段代码三年后还值不值得保留。人工评审负责“品味与决策”,工具负责“纪律与底线”,两者互补。一个管衣冠整洁,一个管气质内涵,缺一不可。
为何常见:自动化的价值容易被夸大,尤其在 AI 工具表现惊艳的今天,但语义理解与业务判断仍然是机器的短板。
面试题
Q1. 静态分析最核心的特点是什么?
- A.运行并跟踪程序的运行时内存
- B.不运行程序直接解析源代码文本← 正确答案
- C.在浏览器中执行前端页面代码
- D.只分析运行时的日志文件
答案:B。静态分析的关键是“不运行程序”,直接对源代码做结构分析,就像拍 X 光不用让病人先跑一圈。A、C 都需要运行程序,属于动态分析;D 分析的是运行产物而非源码。正确答案为 B。
Q2. 词法分析阶段的主要产出是什么?
- A.抽象语法树 AST
- B.Token 序列← 正确答案
- C.控制流图 CFG
- D.运行日志记录
答案:B。词法分析把字符流切分成带类型标签的 Token 序列,相当于体检中把血样分离成各类指标。AST 是语法分析的产出,CFG 是数据流分析的基础,运行日志与静态分析无关。正确答案为 B。
Q3. 抽象语法树(AST)的根节点通常代表什么?
- A.整个文件的第一个单词
- B.语句的语法根操作← 正确答案
- C.最大的代码缩进级别
- D.最后一个变量的名字
答案:B。AST 的根节点代表一条语句最顶层的语法操作,如赋值语句的根是“=“,加法表达式的根是”+”,对应骨架图中支撑全身的主干。它不是文本顺序里的第一个词,更与缩进无关。正确答案为 B。
Q4. 到达定值数据流方程 out[B] = gen[B] ∪ (in[B] - kill[B]) 中,kill[B] 表示什么?
- A.在 B 中被覆盖掉的旧定义← 正确答案
- B.在 B 中全新产生的定义
- C.从 B 流出并被后续使用的值
- D.B 中所有未被使用的变量
答案:A。kill[B] 是基本块 B 内对某变量再次赋值后、被覆盖掉的旧定义,好比新血液注入后旧血液被代谢。gen[B] 才是 B 中新生定义;C、D 描述的是活跃变量分析关注的角度。正确答案为 A。
Q5. 污点分析的三个核心要素是什么?
- A.污点源、传播路径、汇聚点← 正确答案
- B.词法、语法、语义三层面
- C.输入、输出、日志三条线
- D.类、对象、继承的关系
答案:A。污点分析追踪“脏数据”从污点源(用户输入)出发,沿传播路径流动,最终抵达危险汇聚点(如 SQL 查询),构成完整攻击证据链,如同食物中毒的毒素从口入、经血液、伤肝脏。其余选项是别的概念集合。正确答案为 A。
Q6. 关于误报(FP)与漏报(FN),下列说法正确的是?
- A.提高召回率就必然降低精确率
- B.降低误报往往可能增加漏报← 正确答案
- C.误报和漏报可以同时无限降低
- D.误报与漏报之和恒等于一
答案:B。误报与漏报存在此消彼长的权衡:规则收严(更谨慎地报警)会减少误报,但可能放过更多真问题,增加漏报;反之亦然。此消彼长是常态而非必然的数学关系,二者也并非互补概率。B 的描述最符合工程实际。
Q7. 静态分析用作 CI 门禁时,最合适的告警处理策略是?
- A.所有告警一律阻断发布
- B.阻断级告警拦截发布← 正确答案
- C.关闭全部规则避免打扰
- D.只统计不拦截任何告警
答案:B。成熟的门禁策略是分级处置:阻断级(blocker)直接红灯拦住,高危超标也拦截,低级别告警引导修复但不阻塞,类似机场安检只拦危险品而不拦普通行李。一刀切全部阻断会拖垮迭代,全关或全放则让门禁形同虚设。正确答案为 B。
Q8. 以下哪些属于静态分析的典型应用场景?
- A.代码风格统一检查← 正确答案
- B.安全漏洞模式扫描← 正确答案
- C.实时监控线上流量
- D.检测未定义变量引用← 正确答案
答案:ABD。静态分析不运行程序即可完成风格检查(如缩进命名)、漏洞模式扫描(如危险函数)和未定义变量检测,这些都是“看体检单”就能发现的问题。实时监控线上流量必须运行系统并观察行为,属于动态范畴,因此不能选。
Q9. 下列属于静态分析处理流程关键步骤的有哪些?
- A.词法切分得到词法标记← 正确答案
- B.构建抽象语法树 AST← 正确答案
- C.部署负载均衡集群
- D.数据流与污点分析← 正确答案
答案:ABD。标准流程是:词法分析得到 Token、语法分析构建 AST,再在 AST 和数据流图上做数据流分析、污点分析等高级检查。C 是基础设施部署,与代码静态检查无关,属于干扰项。正确答案为 A、B、D。
Q10. 关于静态分析的工程化实践,正确的做法有哪些?
- A.存量问题先建立基线逐步清零← 正确答案
- B.新增阻断级问题则门禁失败← 正确答案
- C.直接删除高误报规则而不评估
- D.用增量门禁防止历史欠账扩大← 正确答案
答案:ABD。工程化落地的关键是“先定基线再清零”:历史存量单独跟踪、逐步消化;新增阻断级问题必须拦截,防止欠账扩大;用增量门禁只拦新问题。C 错在“直接删除”——应先分析误报根因、评估规则价值,再决定优化还是关闭,而不是一刀切删规则,否则可能丢掉有价值的检测能力。正确答案为 A、B、D。