Fix a few bugs to make results of semantic sign analysis match the original AST analysis

This commit is contained in:
Dave Bartolomeo
2022-02-18 17:03:10 -05:00
parent 99f24e5a9e
commit e2e2c0e540
4 changed files with 23 additions and 48 deletions

View File

@@ -13,7 +13,7 @@ private int pointerSize() { result = 8 }
predicate voidType(Type type) { type instanceof J::VoidType }
predicate addressType(Type type, int byteSize) {
type instanceof J::ClassOrInterface and
(type instanceof J::RefType or type instanceof J::NullType) and
byteSize = pointerSize()
}
@@ -37,7 +37,7 @@ predicate floatingPointType(Type type, int byteSize) {
predicate integerType(Type type, int byteSize, boolean signed) {
exists(J::PrimitiveType primType | primType = type |
primType.hasName("byte") and byteSize = 1 and signed = false
primType.hasName("byte") and byteSize = 1 and signed = true
or
primType.hasName("char") and byteSize = 2 and signed = false
or

View File

@@ -6,6 +6,7 @@ private import semmle.code.java.semantic.SemanticCFG
private import semmle.code.java.semantic.SemanticExpr
private import semmle.code.java.semantic.SemanticGuard
private import semmle.code.java.semantic.SemanticSSA
private import semmle.code.java.semantic.SemanticType
private import RangeAnalysisSpecific as Specific
private import ConstantAnalysis
@@ -122,3 +123,15 @@ predicate semValueFlowStep(SemExpr e2, SemExpr e1, int delta) {
x.(SemConstantIntegerExpr).getIntValue() = -delta
)
}
/**
* Gets the type used to track the specified expression's range information.
*
* Usually, this just `e.getSemType()`, but the language can override this to track immutable boxed
* primitive types as the underlying primitive type.
*/
SemType getTrackedType(SemExpr e) {
result = Specific::getAlternateType(e)
or
not exists(Specific::getAlternateType(e)) and result = e.getSemType()
}

View File

@@ -47,7 +47,7 @@ private predicate unknownSign(SemExpr e) {
or
exists(SemCastExpr cast, SemType fromtyp |
cast = e and
fromtyp = cast.getSemType() and
fromtyp = getTrackedType(cast.getExpr()) and
not fromtyp instanceof SemNumericType
)
or
@@ -291,7 +291,7 @@ Sign semExprSign(SemExpr e) {
s = specificSubExprSign(e)
)
|
if e.getSemType() instanceof SemUnsignedIntegerType and s = TNeg()
if getTrackedType(e) instanceof SemUnsignedIntegerType and s = TNeg()
then result = TPos()
else result = s
)

View File

@@ -3,54 +3,16 @@ import semmle.code.java.dataflow.SignAnalysis
import semmle.code.java.semantic.analysis.SignAnalysisCommon
import semmle.code.java.semantic.SemanticExpr
string getSemSignString(Expr e) {
result =
concat(string sign |
exists(SemExpr semExpr | semExpr = getSemanticExpr(e) |
semPositive(semExpr) and
not semStrictlyPositive(semExpr) and
sign = "positive"
or
semNegative(semExpr) and
not semStrictlyNegative(semExpr) and
sign = "negative"
or
semStrictlyPositive(semExpr) and
sign = "strictlyPositive"
or
semStrictlyNegative(semExpr) and
sign = "strictlyNegative"
)
|
sign, " "
)
string getSemanticSign(Expr e) {
result = concat(string s | s = semExprSign(getSemanticExpr(e)).toString() | s, "")
}
string getASTSignString(Expr e) {
result =
concat(string sign |
positive(e) and
not strictlyPositive(e) and
sign = "positive"
or
negative(e) and
not strictlyNegative(e) and
sign = "negative"
or
strictlyPositive(e) and
sign = "strictlyPositive"
or
strictlyNegative(e) and
sign = "strictlyNegative"
|
sign, " "
)
}
string getASTSign(Expr e) { result = concat(string s | s = exprSign(e).toString() | s, "") }
from Expr e, string semSign, string astSign
where
e.getEnclosingCallable().fromSource() and
semSign = getSemSignString(e) and
astSign = getASTSignString(e) and
semSign = getSemanticSign(e) and
astSign = getASTSign(e) and
semSign != astSign
select e, astSign, semSign
select e, "AST sign was '" + astSign + "', but semantic sign was '" + semSign + "'."