You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Joern的Scala脚本函数参数异常:IF-ELSE分析结果不符

问题描述

使用Joern分析demo.c的IF-ELSE结构时,两段逻辑一致的Scala脚本运行结果不同:

  • 封装复用函数的Scala1脚本中,node2的结果为0(正确结果应为1)
  • 未封装函数的Scala2脚本运行结果正确

疑问:是否是函数参数Traversal[ControlStructure]传递错误?如何修改Scala1以得到正确结果?

附相关代码

demo.c

#include <stdio.h>
 
int main () {

   /* local variable definition */
   int a = 100;
 
   /* check the boolean condition */
   if(a>10) {
      if(a>100){
         printf("a > 100");
      }else{
         printf("10<a<100");
      }
   }else if( a <= 10 && a > 0) {
      
      printf("Value of a is 20\n" );
   }else {  
      printf("None of the values is matching\n" );
   }
   printf("Exact value of a is: %d\n", a );

   if ( x > 10 ) {
    printf("111");
   }else{
      printf("222")
   }

   while(x++ < MAX) {
      if(x!=0) {
         int y = 2*x;
         sink(y);
      }
   }
         
   return 0;
}

Scala脚本1(结果异常)

open("demo")
def Outermost_layer_branch =     
       cpg.method("main").block.astChildren.isControlStructure.controlStructureType("IF")
def fun(node:Traversal[ControlStructure]){
    def node1 = node.astChildren.isControlStructure.controlStructureType("ELSE")
    println(node1.size)
    // the result is 1, it's right
    def node2 = 
         node1.astChildren.filter(_.isBlock).astChildren.isControlStructure.controlStructureType("IF")
    println(node2.size)
    //the result is 0, it's wrong!! 
}
fun(Outermost_layer_branch.order(3))

Scala脚本2(结果正确)

open("demo")
def Outermost_layer_branch= 
        cpg.method("main").block.astChildren.isControlStructure.controlStructureType("IF")
def node1 = Outermost_layer_branch.order(3).astChildren.isControlStructure.controlStructureType("ELSE")
println(node1.size)
// the result is 1,and it is right!
def node2 = node1.astChildren.filter(_.isBlock).astChildren.isControlStructure.controlStructureType("IF")
println(node2.size)
// the result is 1,and it is right!
问题分析与解决

问题原因

并非参数传递错误,核心问题在于Joern的Traversal是惰性求值的查询链:

  1. 传递Traversal[ControlStructure]给函数时,该查询链并未立即执行求值
  2. 函数内用def定义node1、node2会导致每次引用都重新执行查询,结合Traversal的惰性特性,可能出现子节点查询匹配失效的情况
  3. 直接对整个Traversal进行链式操作时,查询上下文的传递可能出现预期外的偏差

修改方案

方案一:传递单个ControlStructure节点

将函数参数类型改为单个ControlStructure节点,调用时用.head提取Traversal中的目标节点,同时将def改为val避免重复求值:

open("demo")
def Outermost_layer_branch =     
       cpg.method("main").block.astChildren.isControlStructure.controlStructureType("IF")
def fun(node: ControlStructure){
    val node1 = node.astChildren.isControlStructure.controlStructureType("ELSE")
    println(node1.size)
    val node2 = 
         node1.astChildren.filter(_.isBlock).astChildren.isControlStructure.controlStructureType("IF")
    println(node2.size)
}
fun(Outermost_layer_branch.order(3).head)

方案二:在函数内提取单个节点

保留Traversal[ControlStructure]参数,在函数内部先提取单个节点再操作:

open("demo")
def Outermost_layer_branch =     
       cpg.method("main").block.astChildren.isControlStructure.controlStructureType("IF")
def fun(nodeTraversal: Traversal[ControlStructure]){
    val node = nodeTraversal.head // 提取Traversal中的单个节点
    val node1 = node.astChildren.isControlStructure.controlStructureType("ELSE")
    println(node1.size)
    val node2 = 
         node1.astChildren.filter(_.isBlock).astChildren.isControlStructure.controlStructureType("IF")
    println(node2.size)
}
fun(Outermost_layer_branch.order(3))

两种方案都能确保查询基于明确的单个节点执行,避免惰性求值带来的上下文问题,最终node2.size会输出正确的1。

内容的提问来源于stack exchange,提问作者kiki Shao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 08:56:06