Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 554fea4

Browse files
author
Robert Marsh
committed
C++: Sign analysis for casts and unsigned integers
1 parent d1ae939 commit 554fea4

2 files changed

Lines changed: 233 additions & 7 deletions

File tree

cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,76 @@ private Sign certainInstructionSign(Instruction inst) {
119119
i > 0 and result = TPos()
120120
)
121121
or
122-
not inst instanceof IntegerConstantInstruction and
123122
exists(float f | f = inst.(FloatConstantInstruction).getValue().toFloat() |
124123
f < 0 and result = TNeg() or
125124
f = 0 and result = TZero() or
126125
f > 0 and result = TPos()
127126
)
128127
}
129128

129+
private newtype CastKind = TWiden() or TSame() or TNarrow()
130+
131+
private CastKind getCastKind(ConvertInstruction ci) {
132+
exists(int fromSize, int toSize |
133+
toSize = ci.getResultSize() and
134+
fromSize = ci.getOperand().getResultSize()
135+
|
136+
fromSize < toSize and
137+
result = TWiden()
138+
or
139+
fromSize = toSize and
140+
result = TSame()
141+
or
142+
fromSize > toSize and
143+
result = TNarrow()
144+
)
145+
}
146+
147+
private predicate bindBool(boolean bool) {
148+
bool = true or
149+
bool = false
150+
}
151+
152+
private Sign castSign(Sign s, boolean fromSigned, boolean toSigned, CastKind ck) {
153+
result = TZero() and
154+
(
155+
bindBool(fromSigned) and
156+
bindBool(toSigned) and
157+
s = TZero()
158+
or
159+
bindBool(fromSigned) and
160+
bindBool(toSigned) and
161+
ck = TNarrow()
162+
)
163+
or
164+
result = TPos() and
165+
(
166+
bindBool(fromSigned) and
167+
bindBool(toSigned) and
168+
s = TPos()
169+
or
170+
bindBool(fromSigned) and
171+
bindBool(toSigned) and
172+
s = TNeg() and
173+
ck = TNarrow()
174+
or
175+
fromSigned = true and
176+
toSigned = false and
177+
s = TNeg()
178+
)
179+
or
180+
result = TNeg() and
181+
(
182+
fromSigned = true and
183+
toSigned = true and
184+
s = TNeg()
185+
or
186+
fromSigned = false and
187+
toSigned = true and
188+
s = TPos() and
189+
ck != TWiden()
190+
)
191+
}
130192

131193
/** Holds if the sign of `e` is too complicated to determine. */
132194
private predicate unknownSign(Instruction i) {
@@ -140,9 +202,6 @@ private predicate unknownSign(Instruction i) {
140202
i instanceof BuiltInInstruction
141203
or
142204
i instanceof CallInstruction
143-
or
144-
i instanceof ConvertInstruction and
145-
i.getResultType().(IntegralType).isSigned()
146205
)
147206
}
148207

@@ -154,6 +213,7 @@ private predicate lowerBound(IRGuardCondition comp, Instruction lowerbound, Inst
154213
exists(int adjustment, Instruction compared |
155214
valueNumber(bounded) = valueNumber(compared) and
156215
bounded = pos.getAnOperand() and
216+
not unknownSign(lowerbound) and
157217
/*
158218
* Java library uses guardControlsSsaRead here. I think that the phi node logic doesn't need to
159219
* be duplicated but the implication predicates may need to be ported
@@ -178,6 +238,8 @@ private predicate upperBound(IRGuardCondition comp, Instruction upperbound, Inst
178238
exists(int adjustment, Instruction compared |
179239
valueNumber(bounded) = valueNumber(compared) and
180240
bounded = pos.getAnOperand() and
241+
not unknownSign(upperbound) and
242+
181243
/*
182244
* Java library uses guardControlsSsaRead here. I think that the phi node logic doesn't need to
183245
* be duplicated but the implication predicates may need to be ported
@@ -202,6 +264,7 @@ private predicate upperBound(IRGuardCondition comp, Instruction upperbound, Inst
202264
*/
203265
private predicate eqBound(IRGuardCondition guard, Instruction eqbound, Instruction bounded, Instruction pos, boolean isEq) {
204266
exists(Instruction compared |
267+
not unknownSign(eqbound) and
205268
valueNumber(bounded) = valueNumber(compared) and
206269
bounded = pos.getAnOperand() and
207270
guard.ensuresEq(compared, eqbound, 0, pos.getBlock(), isEq)
@@ -316,9 +379,29 @@ private Sign instructionSign(Instruction i) {
316379
result = certainInstructionSign(i)
317380
or
318381
not exists(certainInstructionSign(i)) and
382+
not (
383+
result = TNeg() and
384+
i.getResultType().(IntegralType).isUnsigned()
385+
) and
319386
(
320387
unknownSign(i)
321388
or
389+
exists(ConvertInstruction ci, Instruction prior, boolean fromSigned, boolean toSigned |
390+
i = ci and
391+
prior = ci.getOperand() and
392+
(
393+
if ci.getResultType().(IntegralType).isSigned()
394+
then toSigned = true
395+
else toSigned = false
396+
) and
397+
(
398+
if prior.getResultType().(IntegralType).isSigned()
399+
then fromSigned = true
400+
else fromSigned = false
401+
) and
402+
result = castSign(operandSign(ci, prior), fromSigned, toSigned, getCastKind(ci))
403+
)
404+
or
322405
exists(Instruction prior |
323406
prior = i.(CopyInstruction).getSourceValue()
324407
|

0 commit comments

Comments
 (0)