Merge pull request #765 from github/lcartey/rule-8-13-copies

`RULE-8-13`: Address false positive issues
This commit is contained in:
Nicolas Will 2024-10-22 22:24:24 +00:00 коммит произвёл GitHub
Родитель 5d247beb04 460fb26a4b
Коммит 1566129d5c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
6 изменённых файлов: 94 добавлений и 27 удалений

Просмотреть файл

@ -18,29 +18,54 @@ import cpp
import codingstandards.c.misra
import codingstandards.cpp.Pointers
import codingstandards.cpp.SideEffect
import codingstandards.cpp.alertreporting.HoldsForAllCopies
from Variable ptr, PointerOrArrayType type
where
not isExcluded(ptr, Pointers1Package::pointerShouldPointToConstTypeWhenPossibleQuery()) and
class NonConstPointerVariableCandidate extends Variable {
NonConstPointerVariableCandidate() {
// Ignore parameters in functions without bodies
(this instanceof Parameter implies exists(this.(Parameter).getFunction().getBlock())) and
// Ignore variables in functions that use ASM commands
not exists(AsmStmt a |
a.getEnclosingFunction() = this.(LocalScopeVariable).getFunction()
or
// In a type declared locally
this.(Field).getDeclaringType+().getEnclosingFunction() = a.getEnclosingFunction()
) and
exists(PointerOrArrayType type |
// include only pointers which point to a const-qualified type
ptr.getType() = type and
not type.isDeeplyConstBelow() and
this.getType() = type and
not type.isDeeplyConstBelow()
) and
// exclude pointers passed as arguments to functions which take a
// parameter that points to a non-const-qualified type
not exists(FunctionCall fc, int i |
fc.getArgument(i) = ptr.getAnAccess() and
fc.getArgument(i) = this.getAnAccess() and
not fc.getTarget().getParameter(i).getType().isDeeplyConstBelow()
) and
// exclude any pointers which have their underlying data modified
not exists(VariableEffect effect |
effect.getTarget() = ptr and
effect.getTarget() = this and
// but not pointers that are only themselves modified
not effect.(AssignExpr).getLValue() = effect.getAnAccess() and
not effect.(CrementOperation).getOperand() = effect.getAnAccess()
not effect.(AssignExpr).getLValue() = this.getAnAccess() and
not effect.(CrementOperation).getOperand() = this.getAnAccess()
) and
// exclude pointers assigned to another pointer to a non-const-qualified type
not exists(Variable a |
a.getAnAssignedValue() = ptr.getAnAccess() and
a.getAnAssignedValue() = this.getAnAccess() and
not a.getType().(PointerOrArrayType).isDeeplyConstBelow()
)
select ptr, "$@ points to a non-const-qualified type.", ptr, ptr.getName()
}
}
/**
* Ensure that all copies of a variable are considered to be missing const qualification to avoid
* false positives where a variable is only used/modified in a single copy.
*/
class NonConstPointerVariable =
HoldsForAllCopies<NonConstPointerVariableCandidate, Variable>::LogicalResultElement;
from NonConstPointerVariable ptr
where
not isExcluded(ptr.getAnElementInstance(),
Pointers1Package::pointerShouldPointToConstTypeWhenPossibleQuery())
select ptr, "$@ points to a non-const-qualified type.", ptr, ptr.getAnElementInstance().getName()

Просмотреть файл

@ -12,3 +12,4 @@
| test.c:66:23:66:24 | p1 | $@ points to a non-const-qualified type. | test.c:66:23:66:24 | p1 | p1 |
| test.c:71:17:71:18 | p1 | $@ points to a non-const-qualified type. | test.c:71:17:71:18 | p1 | p1 |
| test.c:75:15:75:16 | p1 | $@ points to a non-const-qualified type. | test.c:75:15:75:16 | p1 | p1 |
| test.c:103:30:103:30 | s | $@ points to a non-const-qualified type. | test.c:103:30:103:30 | s | s |

Просмотреть файл

@ -76,3 +76,37 @@ int f17(char *p1) { // NON_COMPLIANT
p1++;
return 0;
}
#include <stdint.h>
int16_t
test_r(int16_t *value) { // COMPLIANT - ignored because of the use of ASM
int16_t result;
struct S {
int *x; // COMPLIANT - ignored because of the use of ASM
struct S2 {
int *y; // COMPLIANT - ignored because of the use of ASM
} s2;
};
__asm__("movb %bh (%eax)");
return result;
}
struct S {
int x;
};
void test_struct(struct S *s) { // COMPLIANT
s->x = 1;
}
void test_struct_2(struct S *s) { // NON_COMPLIANT - could be const
s = 0;
}
void test_no_body(int *p); // COMPLIANT - no body, so cannot evaluate whether it
// should be const
void increment(int *p) { // COMPLIANT
*p++ = 1;
}

Просмотреть файл

@ -0,0 +1,7 @@
- `RULE-8-13` - `PointerShouldPointToConstTypeWhenPossible.ql`
- Exclude false positives where a variable occurs in a file compiled multiple times, but where it may only be const in some of those scenarios.
- Exclude results for local scope variables in functions that use assembly code, as CodeQL cannot determine the impact of the assembly.
- Exclude false positives when an assignment is made to a struct field.
- Exclude false positives where the object pointed to by the variable is modified using `*p++ = ...`.
- Exclude false positives for functions without bodies.
- Rules that rely on the determination of side-effects of an expression may change as a result of considering `*p++ = ...` as having a side-effect on `p`.

Просмотреть файл

@ -190,6 +190,8 @@ Expr getAnEffect(Expr base) {
or
exists(PointerDereferenceExpr e | e.getOperand() = base | result = getAnEffect(e))
or
exists(CrementOperation c | c.getOperand() = base | result = getAnEffect(c))
or
// local alias analysis, assume alias when data flows to derived type (pointer/reference)
// auto ptr = &base;
exists(VariableAccess va, AddressOfExpr addressOf |

Просмотреть файл

@ -85,11 +85,9 @@ module HoldsForAllCopies<CandidateElementSig CandidateElement, ElementSetSig Ele
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
exists(CandidateElement s |
// Only consider candidates where we can match up the location
isNotWithinMacroExpansion(s) and
hasLocation(s, filepath, startline, startcolumn, endline, endcolumn) and
// All relevant elements that occur at the same location are candidates
forex(RelevantElement relevantElement | s = relevantElement.getCandidateElement() |
forall(RelevantElement relevantElement | s = relevantElement.getCandidateElement() |
relevantElement instanceof CandidateElement
)
)