Skip to content

Commit 7faf286

Browse files
committed
C++: Add more QLDoc to the 'is modifiable' predicates.
1 parent 90b06c2 commit 7faf286

File tree

1 file changed

+51
-6
lines changed

1 file changed

+51
-6
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,30 @@ class BaseCallVariable extends AbstractBaseSourceVariable, TBaseCallVariable {
418418
}
419419

420420
private module IsModifiableAtImpl {
421+
/**
422+
* Holds if the `indirectionIndex`'th dereference of a value of type
423+
* `cppType` is a type that can be modified (either by modifying the value
424+
* itself or one of its fields if it's a class type).
425+
*
426+
* For example, a value of type `const int* const` cannot be modified
427+
* at any indirection index (because it's a constant pointer to constant
428+
* data), and a value of type `int *const *` is modifiable at indirection index
429+
* 2 only.
430+
*
431+
* A value of type `const S2* s2` where `s2` is
432+
* ```cpp
433+
* struct S { int x; }
434+
* ```
435+
* can be modified at indirection index 1. This is to ensure that we generate
436+
* a `PostUpdateNode` for the argument corresponding to the `s2` parameter in
437+
* an example such as:
438+
* ```cpp
439+
* void set_field(const S2* s2)
440+
* {
441+
* s2->s->x = 42;
442+
* }
443+
* ```
444+
*/
421445
bindingset[cppType, indirectionIndex]
422446
pragma[inline_late]
423447
private predicate impl(CppType cppType, int indirectionIndex) {
@@ -436,6 +460,18 @@ private module IsModifiableAtImpl {
436460
)
437461
}
438462

463+
/**
464+
* Holds if `cppType` is modifiable with an indirection index of at least 1.
465+
*
466+
* This predicate factored out into a seperate predicate for two reasons:
467+
* - This predicate needs to be recursive because, if a type is modifiable
468+
* at indirection `i`, then it's also modifiable at indirection index `i+1`
469+
* (because the pointer could be completely re-assigned at indirection `i`).
470+
* - We special-case indirection index `0` so that pointer arguments that can
471+
* be modified at some index always have a `PostUpdateNode` at indiretion
472+
* index 0 even though the 0'th indirection can never be modified by a
473+
* callee.
474+
*/
439475
private predicate isModifiableAtImplAtLeast1(CppType cppType, int indirectionIndex) {
440476
indirectionIndex = [1 .. countIndirectionsForCppType(cppType)] and
441477
(
@@ -447,12 +483,21 @@ private module IsModifiableAtImpl {
447483
)
448484
}
449485

486+
/**
487+
* Holds if `cppType` is modifiable at indirection index 0.
488+
*
489+
* In reality, the 0'th indirection of a pointer (i.e., the pointer itself)
490+
* can never be modified by a callee, but it is sometimes useful to be able
491+
* to specify the value of the pointer, as its coming out of a function, as
492+
* a source of dataflow since the shared library's reverse-read mechanism
493+
* then ensures that field-flow is accounted for.
494+
*/
450495
private predicate isModifiableAtImplAt0(CppType cppType) { impl(cppType, 0) }
451496

452497
/**
453-
* Holds if `t` is a pointer or reference type that supports at least `indirectionIndex` number
454-
* of indirections, and the `indirectionIndex` indirection cannot be modfiied by passing a
455-
* value of `t` to a function.
498+
* Holds if `t` is a pointer or reference type that supports at least
499+
* `indirectionIndex` number of indirections, and the `indirectionIndex`
500+
* indirection cannot be modfiied by passing a value of `t` to a function.
456501
*/
457502
private predicate isModifiableAtImpl(CppType cppType, int indirectionIndex) {
458503
isModifiableAtImplAtLeast1(cppType, indirectionIndex)
@@ -462,9 +507,9 @@ private module IsModifiableAtImpl {
462507
}
463508

464509
/**
465-
* Holds if `t` is a type with at least `indirectionIndex` number of indirections,
466-
* and the `indirectionIndex` indirection can be modified by passing a value of
467-
* type `t` to a function function.
510+
* Holds if `t` is a type with at least `indirectionIndex` number of
511+
* indirections, and the `indirectionIndex` indirection can be modified by
512+
* passing a value of type `t` to a function function.
468513
*/
469514
bindingset[indirectionIndex]
470515
predicate isModifiableAt(CppType cppType, int indirectionIndex) {

0 commit comments

Comments
 (0)