wala / ML

Eclipse Public License 2.0
25 stars 17 forks source link

Creating a list using an iterable results in an incorrect pointer analysis #122

Open khatchad opened 9 months ago

khatchad commented 9 months ago

Consider the following example:

# test.py
my_list = list([5, 6])

for element in my_list:
    print(element)

Which results in the following IR:

IR of node 2, context CallStringContext: [ com.ibm.wala.FakeRootClass.fakeRootMethod()V@2 ]
<Code body of function Lscript test.py>
CFG:
BB0[-1..-2]
    -> BB1
BB1[0..93]
    -> BB2
    -> BB5
BB2[94..95]
    -> BB3
BB3[96..100]
    -> BB4
    -> BB5
BB4[101..106]
    -> BB3
BB5[-1..-2]
Instructions:
BB0
BB1
0   global:global script test.py = v1<no information>
1   v3 = new <PythonLoader,Lwala/builtin/enumerate>@1<no information> [3=[enumerate]]
2   v4 = new <PythonLoader,Lwala/builtin/int>@2<no information> [4=[int]]
3   v5 = new <PythonLoader,Lwala/builtin/round>@3<no information> [5=[round]]
4   v6 = new <PythonLoader,Lwala/builtin/len>@4<no information> [6=[len]]
5   v7 = new <PythonLoader,Lwala/builtin/list>@5<no information> [7=[list]]
6   v8 = new <PythonLoader,Lwala/builtin/range>@6<no information> [8=[range]]
7   v9 = new <PythonLoader,Lwala/builtin/sorted>@7<no information> [9=[sorted]]
8   v10 = new <PythonLoader,Lwala/builtin/str>@8<no information> [10=[str]]
9   v11 = new <PythonLoader,Lwala/builtin/sum>@9<no information> [11=[sum]]
10   v12 = new <PythonLoader,Lwala/builtin/type>@10<no information> [12=[type]]
11   v13 = new <PythonLoader,Lwala/builtin/zip>@11<no information> [13=[zip]]
12   v14 = new <PythonLoader,Lwala/builtin/slice>@12<no information> [14=[slice]]
13   v15 = new <PythonLoader,Lwala/builtin/__delete__>@13<no information> [15=[__delete__]]
14   v16 = new <PythonLoader,Lwala/builtin/print>@14<no information> [16=[print]]
15   v19 = invokestatic < PythonLoader, LBaseException, import()LBaseException; > @15 exception:v20<no information> [19=[BaseException]]
16   v22 = invokestatic < PythonLoader, LDeprecationWarning, import()LDeprecationWarning; > @16 exception:v23<no information> [22=[DeprecationWarning]]
17   v25 = invokestatic < PythonLoader, LException, import()LException; > @17 exception:v26<no information> [25=[Exception]]
18   v28 = invokestatic < PythonLoader, LFutureWarning, import()LFutureWarning; > @18 exception:v29<no information> [28=[FutureWarning]]
19   v31 = invokestatic < PythonLoader, LNameError, import()LNameError; > @19 exception:v32<no information> [31=[NameError]]
20   v34 = invokestatic < PythonLoader, LNone, import()LNone; > @20 exception:v35<no information> [34=[None]]
21   v37 = invokestatic < PythonLoader, LRuntimeError, import()LRuntimeError; > @21 exception:v38<no information> [37=[RuntimeError]]
22   v40 = invokestatic < PythonLoader, LStopIteration, import()LStopIteration; > @22 exception:v41<no information> [40=[StopIteration]]
23   v43 = invokestatic < PythonLoader, LTypeError, import()LTypeError; > @23 exception:v44<no information> [43=[TypeError]]
24   v46 = invokestatic < PythonLoader, LUserWarning, import()LUserWarning; > @24 exception:v47<no information> [46=[UserWarning]]
25   v49 = invokestatic < PythonLoader, LValueError, import()LValueError; > @25 exception:v50<no information> [49=[ValueError]]
26   v52 = invokestatic < PythonLoader, L__doc__, import()L__doc__; > @26 exception:v53<no information> [52=[__doc__]]
27   v55 = invokestatic < PythonLoader, L__file__, import()L__file__; > @27 exception:v56<no information> [55=[__file__]]
28   v58 = invokestatic < PythonLoader, L__name__, import()L__name__; > @28 exception:v59<no information> [58=[__name__]]
29   v61 = invokestatic < PythonLoader, Labs, import()Labs; > @29 exception:v62<no information> [61=[abs]]
30   v64 = invokestatic < PythonLoader, Lall, import()Lall; > @30 exception:v65<no information> [64=[all]]
31   v67 = invokestatic < PythonLoader, Lany, import()Lany; > @31 exception:v68<no information> [67=[any]]
32   v70 = invokestatic < PythonLoader, Lbin, import()Lbin; > @32 exception:v71<no information> [70=[bin]]
33   v73 = invokestatic < PythonLoader, Lbool, import()Lbool; > @33 exception:v74<no information> [73=[bool]]
34   v76 = invokestatic < PythonLoader, Lbytes, import()Lbytes; > @34 exception:v77<no information> [76=[bytes]]
35   v79 = invokestatic < PythonLoader, Lcallable, import()Lcallable; > @35 exception:v80<no information> [79=[callable]]
36   v82 = invokestatic < PythonLoader, Lchr, import()Lchr; > @36 exception:v83<no information> [82=[chr]]
37   v85 = invokestatic < PythonLoader, Lcomplex, import()Lcomplex; > @37 exception:v86<no information> [85=[complex]]
38   v88 = invokestatic < PythonLoader, Ldel, import()Ldel; > @38 exception:v89<no information> [88=[del]]
39   v91 = invokestatic < PythonLoader, Ldict, import()Ldict; > @39 exception:v92<no information> [91=[dict]]
40   v94 = invokestatic < PythonLoader, Ldir, import()Ldir; > @40 exception:v95<no information> [94=[dir]]
41   v97 = invokestatic < PythonLoader, Ldivmod, import()Ldivmod; > @41 exception:v98<no information> [97=[divmod]]
42   v100 = invokestatic < PythonLoader, Leval, import()Leval; > @42 exception:v101<no information> [100=[eval]]
43   v103 = invokestatic < PythonLoader, Lexec, import()Lexec; > @43 exception:v104<no information> [103=[exec]]
44   v106 = invokestatic < PythonLoader, Lexit, import()Lexit; > @44 exception:v107<no information> [106=[exit]]
45   v109 = invokestatic < PythonLoader, Lfilter, import()Lfilter; > @45 exception:v110<no information> [109=[filter]]
46   v112 = invokestatic < PythonLoader, Lfloat, import()Lfloat; > @46 exception:v113<no information> [112=[float]]
47   v115 = invokestatic < PythonLoader, Lformat, import()Lformat; > @47 exception:v116<no information> [115=[format]]
48   v118 = invokestatic < PythonLoader, Lfrozenset, import()Lfrozenset; > @48 exception:v119<no information> [118=[frozenset]]
49   v121 = invokestatic < PythonLoader, Lget_ipython, import()Lget_ipython; > @49 exception:v122<no information> [121=[get_ipython]]
50   v124 = invokestatic < PythonLoader, Lgetattr, import()Lgetattr; > @50 exception:v125<no information> [124=[getattr]]
51   v127 = invokestatic < PythonLoader, Lglobals, import()Lglobals; > @51 exception:v128<no information> [127=[globals]]
52   v130 = invokestatic < PythonLoader, Lhasattr, import()Lhasattr; > @52 exception:v131<no information> [130=[hasattr]]
53   v133 = invokestatic < PythonLoader, Lhelp, import()Lhelp; > @53 exception:v134<no information> [133=[help]]
54   v136 = invokestatic < PythonLoader, Lhex, import()Lhex; > @54 exception:v137<no information> [136=[hex]]
55   v139 = invokestatic < PythonLoader, Lid, import()Lid; > @55 exception:v140<no information> [139=[id]]
56   v142 = invokestatic < PythonLoader, Linput, import()Linput; > @56 exception:v143<no information> [142=[input]]
57   v145 = invokestatic < PythonLoader, Lisinstance, import()Lisinstance; > @57 exception:v146<no information> [145=[isinstance]]
58   v148 = invokestatic < PythonLoader, Liter, import()Liter; > @58 exception:v149<no information> [148=[iter]]
59   v151 = invokestatic < PythonLoader, Llocals, import()Llocals; > @59 exception:v152<no information> [151=[locals]]
60   v154 = invokestatic < PythonLoader, Lmap, import()Lmap; > @60 exception:v155<no information> [154=[map]]
61   v157 = invokestatic < PythonLoader, Lmax, import()Lmax; > @61 exception:v158<no information> [157=[max]]
62   v160 = invokestatic < PythonLoader, Lmin, import()Lmin; > @62 exception:v161<no information> [160=[min]]
63   v163 = invokestatic < PythonLoader, Lnext, import()Lnext; > @63 exception:v164<no information> [163=[next]]
64   v166 = invokestatic < PythonLoader, Lobject, import()Lobject; > @64 exception:v167<no information> [166=[object]]
65   v169 = invokestatic < PythonLoader, Lopen, import()Lopen; > @65 exception:v170<no information> [169=[open]]
66   v172 = invokestatic < PythonLoader, Lord, import()Lord; > @66 exception:v173<no information> [172=[ord]]
67   v175 = invokestatic < PythonLoader, Lpow, import()Lpow; > @67 exception:v176<no information> [175=[pow]]
68   v178 = invokestatic < PythonLoader, Lprint, import()Lprint; > @68 exception:v179<no information> [178=[print]]
70   v181 = invokestatic < PythonLoader, Lproperty, import()Lproperty; > @70 exception:v182<no information> [181=[property]]
71   v184 = invokestatic < PythonLoader, Lrepr, import()Lrepr; > @71 exception:v185<no information> [184=[repr]]
72   v187 = invokestatic < PythonLoader, Lreversed, import()Lreversed; > @72 exception:v188<no information> [187=[reversed]]
73   v190 = invokestatic < PythonLoader, Lset, import()Lset; > @73 exception:v191<no information> [190=[set]]
74   v193 = invokestatic < PythonLoader, Lsuper, import()Lsuper; > @74 exception:v194<no information> [193=[super]]
75   v196 = invokestatic < PythonLoader, Ltuple, import()Ltuple; > @75 exception:v197<no information> [196=[tuple]]
76   v199 = invokestatic < PythonLoader, Lvars, import()Lvars; > @76 exception:v200<no information> [199=[vars]]
77   v202 = invokestatic < PythonLoader, LNotImplementedError, import()LNotImplementedError; > @77 exception:v203<no information> [202=[NotImplementedError]]
78   v205 = invokestatic < PythonLoader, LWarning, import()LWarning; > @78 exception:v206<no information> [205=[Warning]]
79   v208 = invokestatic < PythonLoader, Lcd, import()Lcd; > @79 exception:v209<no information> [208=[cd]]
80   v211 = invokestatic < PythonLoader, Lclear, import()Lclear; > @80 exception:v212<no information> [211=[clear]]
81   v214 = invokestatic < PythonLoader, Lpylab, import()Lpylab; > @81 exception:v215<no information> [214=[pylab]]
82   v217 = invokestatic < PythonLoader, LRuntimeWarning, import()LRuntimeWarning; > @82 exception:v218<no information> [217=[RuntimeWarning]]
83   v220 = invokestatic < PythonLoader, Lhist, import()Lhist; > @83 exception:v221<no information> [220=[hist]]
84   v223 = invokestatic < PythonLoader, Lmatplotlib, import()Lmatplotlib; > @84 exception:v224<no information> [223=[matplotlib]]
85   v226 = invokestatic < PythonLoader, Lrecall, import()Lrecall; > @85 exception:v227<no information> [226=[recall]]
86   v229 = invokestatic < PythonLoader, Lhistory, import()Lhistory; > @86 exception:v230<no information> [229=[history]]
87   v232 = invokestatic < PythonLoader, Ltime, import()Ltime; > @87 exception:v233<no information> [232=[time]]
88   v235 = invokestatic < PythonLoader, LKeyError, import()LKeyError; > @88 exception:v236<no information> [235=[KeyError]]
89   v238 = invokestatic < PythonLoader, Ldisplay, import()Ldisplay; > @89 exception:v239<no information> [238=[display]]
90   v241 = new <PythonLoader,Llist>@90      test.py [1:15] -> [1:21]
91   fieldref v241.v242:#0 = v243:#5 = v243:#5test.py [1:15] -> [1:21]
92   fieldref v241.v244:#1 = v245:#6 = v245:#6test.py [1:15] -> [1:21]
93   v240 = invokeFunction < PythonLoader, LCodeBody, do()LRoot; > v7,v241 @93 exception:v246test.py [1:10] -> [1:22] [240=[my_list, temp 3]7=[list]]
BB2
BB3
96   v252 = global:global element            test.py [3:4] -> [3:11]
97   v253 = a property name of v240          <no information> [240=[my_list, temp 3]]
98   global:global element = v253            test.py [1:0] -> [4:18]
99   v249 = binaryop(ne) v250:#null , v253   test.py [1:0] -> [4:18]
100   conditional branch(eq, to iindex=-1) v249,v242:#0test.py [1:0] -> [4:18]
BB4
101   v255 = global:global element           test.py [3:4] -> [3:11]
102   v254 = fieldref v240.v255              test.py [1:0] -> [4:18] [240=[my_list, temp 3]]
103   global:global element = v254           test.py [1:0] -> [4:18]
104   v256 = global:global element           test.py [4:10] -> [4:17]
105   echo/print v256                        test.py [1:0] -> [4:18]
106   goto (from iindex= 106 to iindex = 96) test.py [1:0] -> [4:18]
BB5

In the pointer analysis, the points-to set for the final variable v256 is empty:

[Node: <Code body of function Lscript test.py> Context: CallStringContext: [ com.ibm.wala.FakeRootClass.fakeRootMethod()V@2 ], v256] --> []

It should be the constant keys for 5 and 6.

Regression

It works for literals passed to list ctors. In fact, the list passed to the list() built-in works fine. The built-in list() does also return Llist:

[Node: <Code body of function Lscript test.py> Context: CallStringContext: [ com.ibm.wala.FakeRootClass.fakeRootMethod()V@2 ], v240] --> [SITE_IN_NODE{synthetic < PythonLoader, Lwala/builtin/list, do()LRoot; >:Llist in CallStringContext: [ script test.py.do()LRoot;@93 ]}]