@@ -78,15 +78,25 @@ module StringOps {
78
78
}
79
79
80
80
/**
81
- * An expression of form `strings.Index(A, B) === 0`.
81
+ * Holds if `eq` is of the form `nd == 0` or `nd != 0`.
82
+ */
83
+ pragma [ noinline]
84
+ private predicate comparesToZero ( DataFlow:: EqualityTestNode eq , DataFlow:: Node nd ) {
85
+ exists ( DataFlow:: Node zero |
86
+ eq .hasOperands ( globalValueNumber ( nd ) .getANode ( ) , zero ) and
87
+ zero .getIntValue ( ) = 0
88
+ )
89
+ }
90
+
91
+ /**
92
+ * An expression of form `strings.Index(A, B) == 0`.
82
93
*/
83
94
private class HasPrefix_IndexOfEquals extends Range , DataFlow:: EqualityTestNode {
84
95
DataFlow:: CallNode indexOf ;
85
96
86
97
HasPrefix_IndexOfEquals ( ) {
87
- indexOf .getTarget ( ) .hasQualifiedName ( "strings" , "Index" ) and
88
- getAnOperand ( ) = globalValueNumber ( indexOf ) .getANode ( ) and
89
- getAnOperand ( ) .getIntValue ( ) = 0
98
+ comparesToZero ( this , indexOf ) and
99
+ indexOf .getTarget ( ) .hasQualifiedName ( "strings" , "Index" )
90
100
}
91
101
92
102
override DataFlow:: Node getBaseString ( ) { result = indexOf .getArgument ( 0 ) }
@@ -97,19 +107,30 @@ module StringOps {
97
107
}
98
108
99
109
/**
100
- * A comparison of form `x[0] === 'k'` for some rune literal `k`.
110
+ * Holds if `eq` is of the form `str[0] == rhs` or `str[0] != rhs`.
111
+ */
112
+ pragma [ noinline]
113
+ private predicate comparesFirstCharacter (
114
+ DataFlow:: EqualityTestNode eq , DataFlow:: Node str , DataFlow:: Node rhs
115
+ ) {
116
+ exists ( DataFlow:: ElementReadNode read |
117
+ eq .hasOperands ( globalValueNumber ( read ) .getANode ( ) , rhs ) and
118
+ str = read .getBase ( ) and
119
+ str .getType ( ) .getUnderlyingType ( ) instanceof StringType and
120
+ read .getIndex ( ) .getIntValue ( ) = 0
121
+ )
122
+ }
123
+
124
+ /**
125
+ * A comparison of form `x[0] == 'k'` for some rune literal `k`.
101
126
*/
102
127
private class HasPrefix_FirstCharacter extends Range , DataFlow:: EqualityTestNode {
103
- DataFlow:: ElementReadNode read ;
128
+ DataFlow:: Node base ;
104
129
DataFlow:: Node runeLiteral ;
105
130
106
- HasPrefix_FirstCharacter ( ) {
107
- read .getBase ( ) .getType ( ) .getUnderlyingType ( ) instanceof StringType and
108
- read .getIndex ( ) .getIntValue ( ) = 0 and
109
- eq ( _, globalValueNumber ( read ) .getANode ( ) , runeLiteral )
110
- }
131
+ HasPrefix_FirstCharacter ( ) { comparesFirstCharacter ( this , base , runeLiteral ) }
111
132
112
- override DataFlow:: Node getBaseString ( ) { result = read . getBase ( ) }
133
+ override DataFlow:: Node getBaseString ( ) { result = base }
113
134
114
135
override DataFlow:: Node getSubstring ( ) { result = runeLiteral }
115
136
0 commit comments