Page 45 - 《软件学报》2025年第4期
P. 45

沈阚 等: 基于静态分析的      Python  第三方库  API 兼容性问题检测方法                                  1451


                 v1  版本中无法正常运行. 而性能提升和方法重构并不会改变                 API 的输出. 文献  [12] 中还总结了第三方库良性语义
                 变化的实现方式, 例如替换内部调用的方法              (第  3–6  行)、添加  try-except 结构  (第  9–11  行)、添加或删除条件分支
                 结构  (第  12–17  行)、更改原有条件分支结构的判断条件           (第  18–21  行) 等. CallMethod(stmt) 返回语句  stmt 中调用
                 方法的名称, Parameter(method, stmt) 返回语句  stmt 中方法  method  的参数列表.
                    然后, 算法   3  第  24–26  行分析匹配的  return  语句<s a , s b >, 若  s a 或  s b 的后向切片语句中存在非良性变化, 则认
                 为存在输出不同的返回值         (CI7). 第  27  行分析新增和删除的    return  语句, 若存在非良性变化的新增       return  语句或
                 删除  return  语句, 则认为存在输出不同的返回值        (CI7).

                 算法  3. 检测与返回值有关的兼容性问题.

                 输入: M, R, E, S, G, B;
                 输出: CI.

                 Function DetectReturn
                 21.     BSC 1  = BSC 1 ∪{s a }, BSC 2  = BSC 2 ∪{s b }
                 1.  BSC 1  , BSC 2  = { }, { }
                 2.  BSC 1  = BSC 1 ∪(M.del∩G 2 ), BSC 2  = BSC 2 ∪(M.add∩G 1 )
                 3.  for each <s a , s b > in M.change then:
                 4.    m 1  = CallMethod(s a ), m 2  = CallMethod(s b )
                 5.    if m 1  != m 2  and Parameter(m 1 , s a ) == Parameter(m 2 , s b ) then:
                 6.     BSC 1  = BSC 1 ∪{s a }, BSC 2  = BSC 2 ∪{s b }
                 7.   while True then:

                 8.    tmp_BSC 1  = BSC 1 , tmp_BSC 2  = BSC 2
                 9.    for each s in M.add∩E 2 .C then:
                 10.   if E 2 .C[s].TryStmts⊆M.add or E 2 .C[s].TryStmts⊆M 2 .unchange∪BSC 2  then:
                 11.    BSC 2  = BSC 2 ∪E 2 .C[s].AllStmts
                 12.  for each s in M.add∩B 2  then:
                 13.   if B 2 [s].Stmts⊆M.add or B 2 [s].Stmts⊆M 2 .unchange∪BSC 2  then:
                 14.    BSC 2  = BSC 2 ∪{s}∪B 2 [s].Stmts
                 15.  for each s in M.del∩B 1  then:
                 16.   if B 1 [s].Stmts⊆M.del or B 1 [s].Stmts⊆M 1 .unchange∪BSC 1  then:
                 17.    BSC 1  = BSC 1 ∪{s}∪B 1 [s].Stmts
                 18.  for each <s a , s b > in M.change then:
                 19.   if (s a  in B 1 ) and (s b  in B 2 ) and (B 1 [s a ].condition != B 2 [s b ].condition) then:
                 20.    if B 1 [s a ].Stmts⊆M 1 .unchange∪BSC 1  and B 2 [s b ].Stmts⊆M 2 .unchange∪BSC 2  then:


                 22.  if tmp_BSC 1  == BSC 1  and tmp_BSC 2  == BSC 2  then:
                 23.   break
                 24.   for each <s a , s b > in M.change∪M.unchange then:
                 25.  if s a  in R 1  and s b  in R 2  then:
                 26.   CI ← {CI7} if Len(S 1 .BR[s a ]-BSC 1 -M 1 .unchange)>0 or Len(S 2 .BR[s b ]-BSC 2 -M 2 .unchange)>0
                 27.   CI ← {CI7} if Len(M.del∩R 1 -BSC 1 )>0 or Len(M.add∩R 2 -BSC 2 )>0
                 28.   return CI
                 Function End
   40   41   42   43   44   45   46   47   48   49   50