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