Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go/ql/lib/semmle/go/Decls.qll
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ class FieldBase extends @field, ExprParent {
/**
* Gets the expression representing the type of the fields declared in this declaration.
*/
pragma[nomagic]
Expr getTypeExpr() { result = this.getChildExpr(0) }

/**
Expand Down Expand Up @@ -489,6 +490,7 @@ class FieldBase extends @field, ExprParent {
class FieldDecl extends FieldBase, Documentable, ExprParent {
StructTypeExpr st;

pragma[nomagic]
FieldDecl() { this = st.getField(_) }

/**
Expand Down
34 changes: 19 additions & 15 deletions go/ql/lib/semmle/go/Expr.qll
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ class Ellipsis extends @ellipsis, Expr {
* ```
*/
class Literal extends Expr {
pragma[nomagic]
Literal() {
this instanceof @basiclit or this instanceof @funclit or this instanceof @compositelit
}
Expand Down Expand Up @@ -575,10 +576,14 @@ class ParenExpr extends @parenexpr, Expr {
* ```
*/
class SelectorExpr extends @selectorexpr, Expr {
pragma[nomagic]
SelectorExpr() { any() }

/** Gets the base of this selector expression. */
Expr getBase() { result = this.getChildExpr(0) }

/** Gets the selector of this selector expression. */
pragma[inline]
Ident getSelector() { result = this.getChildExpr(1) }

/** Holds if this selector is a use of `e`. */
Expand Down Expand Up @@ -984,6 +989,9 @@ class KeyValueExpr extends @keyvalueexpr, Expr {
* ```
*/
class ArrayTypeExpr extends @arraytypeexpr, TypeExpr {
pragma[nomagic]
ArrayTypeExpr() { any() }

/** Gets the length expression of this array type. */
Expr getLength() { result = this.getChildExpr(0) }

Expand Down Expand Up @@ -2035,6 +2043,9 @@ class ConstantName extends ValueName {
override string getAPrimaryQlClass() { result = "ConstantName" }
}

/** Holds if `e` is an expression that refers to the `nil` constant. */
predicate exprRefersToNil(Expr e) { e.(ConstantName).getTarget() = Builtin::nil() }

/**
* A name referring to a variable.
*
Expand Down Expand Up @@ -2131,11 +2142,12 @@ private predicate isTypeExprBottomUp(Expr e) {
* Holds if `e` must be a type expression because it either occurs in a syntactic
* position where a type is expected, or it is part of a larger type expression.
*
* This predicate is only needed on snapshots for which type information is
* incomplete. It is an underapproximation; in cases where it is syntactically ambiguous
* whether an expression refers to a type or a value, we conservatively assume that
* it may be the latter and so this predicate does not consider the expression to be
* a type expression.
* This predicate is only needed on databases for which type information is
* incomplete - for example, when some dependencies could not be reached during
* extraction. It is an underapproximation; in cases where it is syntactically
* ambiguous whether an expression refers to a type or a value, we conservatively
* assume that it may be the latter and so this predicate does not consider the
* expression to be a type expression.
*/
pragma[nomagic]
private predicate isTypeExprTopDown(Expr e) {
Expand All @@ -2145,20 +2157,12 @@ private predicate isTypeExprTopDown(Expr e) {
or
e = any(ArrayTypeExpr ae).getElement()
or
e = any(FieldDecl f).getTypeExpr()
or
e = any(ParameterDecl pd).getTypeExpr()
e = any(FieldBase fb).getTypeExpr()
or
e = any(TypeParamDecl tpd).getTypeConstraintExpr()
or
e = any(TypeParamDecl tpd).getNameExpr(_)
or
e = any(ReceiverDecl rd).getTypeExpr()
or
e = any(ResultVariableDecl rvd).getTypeExpr()
or
e = any(MethodSpec md).getTypeExpr()
or
e = any(MapTypeExpr mt).getKeyTypeExpr()
or
e = any(MapTypeExpr mt).getValueTypeExpr()
Expand All @@ -2175,7 +2179,7 @@ private predicate isTypeExprTopDown(Expr e) {
or
e = any(TypeSwitchStmt s).getACase().getExpr(_) and
// special case: `nil` is allowed in a type case but isn't a type
not e = Builtin::nil().getAReference()
not exprRefersToNil(e)
or
e = any(SelectorExpr sel | isTypeExprTopDown(sel)).getBase()
or
Expand Down
2 changes: 1 addition & 1 deletion go/ql/lib/semmle/go/dataflow/Properties.qll
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Property extends TProperty {
isTrue = eq.getPolarity().booleanXor(e.getBoolValue().booleanXor(outcome))
or
this = IsNil(isTrue) and
e = Builtin::nil().getAReference() and
exprRefersToNil(e) and
isTrue = eq.getPolarity().booleanXor(outcome).booleanNot()
)
or
Expand Down
6 changes: 3 additions & 3 deletions go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ private predicate onlyPossibleReturnOfBool(FuncDecl fd, FunctionOutput res, Node
*/
predicate possiblyReturnsNonNil(FuncDecl fd, FunctionOutput res, Node ret) {
ret = res.getEntryNode(fd) and
not ret.asExpr() = Builtin::nil().getAReference()
not exprRefersToNil(ret.asExpr())
}

/**
Expand All @@ -570,7 +570,7 @@ predicate possiblyReturnsNonNil(FuncDecl fd, FunctionOutput res, Node ret) {
private predicate onlyPossibleReturnOfNonNil(FuncDecl fd, FunctionOutput res, Node ret) {
possiblyReturnsNonNil(fd, res, ret) and
forall(Node otherRet | otherRet = res.getEntryNode(fd) and otherRet != ret |
otherRet.asExpr() = Builtin::nil().getAReference()
exprRefersToNil(otherRet.asExpr())
)
}

Expand Down Expand Up @@ -609,7 +609,7 @@ private predicate isCertainlyNotNil(DataFlow::Node node) {
*/
private predicate onlyPossibleReturnOfNil(FuncDecl fd, FunctionOutput res, DataFlow::Node ret) {
ret = res.getEntryNode(fd) and
ret.asExpr() = Builtin::nil().getAReference() and
exprRefersToNil(ret.asExpr()) and
forall(DataFlow::Node otherRet | otherRet = res.getEntryNode(fd) and otherRet != ret |
isCertainlyNotNil(otherRet)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ predicate functionEnsuresInputIsConstant(
forex(DataFlow::Node ret, IR::ReturnInstruction ri |
ret = outp.getEntryNode(fd) and
ri.getReturnStmt().getAnExpr() = ret.asExpr() and
ret.asExpr() = Builtin::nil().getAReference()
exprRefersToNil(ret.asExpr())
|
DataFlow::localFlow(inp.getExitNode(fd), _) and
mustPassConstantCaseTestToReach(ri, inp.getExitNode(fd))
Expand Down
2 changes: 1 addition & 1 deletion go/ql/src/RedundantCode/UnreachableStatement.ql
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ ControlFlow::Node nonGuardPredecessor(ControlFlow::Node nd) {
* Matches if `retval` is a constant or a struct composed wholly of constants.
*/
predicate isAllowedReturnValue(Expr retval) {
retval = Builtin::nil().getAReference()
exprRefersToNil(retval)
or
retval = Builtin::true_().getAReference()
or
Expand Down
6 changes: 3 additions & 3 deletions go/ql/src/experimental/CWE-203/Timing.ql
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ private class SensitiveStringCompareSink extends Sink {
not op1 = nonSensitiveOperand and
not (
// Comparisons with `nil` should be excluded.
nonSensitiveOperand = Builtin::nil().getAReference()
exprRefersToNil(nonSensitiveOperand)
or
// Comparisons with empty string should also be excluded.
nonSensitiveOperand.getStringValue().length() = 0
Expand All @@ -60,7 +60,7 @@ private class SensitiveCompareSink extends Sink {
not op1 = op2 and
not (
// Comparisons with `nil` should be excluded.
op2 = Builtin::nil().getAReference()
exprRefersToNil(op2)
or
// Comparisons with empty string should also be excluded.
op2.getStringValue().length() = 0
Expand All @@ -85,7 +85,7 @@ private class SensitiveStringSink extends Sink {
not op1 = op2 and
not (
// Comparisons with `nil` should be excluded.
op2 = Builtin::nil().getAReference()
exprRefersToNil(op2)
or
// Comparisons with empty string should also be excluded.
op2.getStringValue().length() = 0
Expand Down
Loading