@@ -418,6 +418,30 @@ class BaseCallVariable extends AbstractBaseSourceVariable, TBaseCallVariable {
418
418
}
419
419
420
420
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
+ */
421
445
bindingset [ cppType, indirectionIndex]
422
446
pragma [ inline_late]
423
447
private predicate impl ( CppType cppType , int indirectionIndex ) {
@@ -436,6 +460,18 @@ private module IsModifiableAtImpl {
436
460
)
437
461
}
438
462
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
+ */
439
475
private predicate isModifiableAtImplAtLeast1 ( CppType cppType , int indirectionIndex ) {
440
476
indirectionIndex = [ 1 .. countIndirectionsForCppType ( cppType ) ] and
441
477
(
@@ -447,12 +483,21 @@ private module IsModifiableAtImpl {
447
483
)
448
484
}
449
485
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
+ */
450
495
private predicate isModifiableAtImplAt0 ( CppType cppType ) { impl ( cppType , 0 ) }
451
496
452
497
/**
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.
456
501
*/
457
502
private predicate isModifiableAtImpl ( CppType cppType , int indirectionIndex ) {
458
503
isModifiableAtImplAtLeast1 ( cppType , indirectionIndex )
@@ -462,9 +507,9 @@ private module IsModifiableAtImpl {
462
507
}
463
508
464
509
/**
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.
468
513
*/
469
514
bindingset [ indirectionIndex]
470
515
predicate isModifiableAt ( CppType cppType , int indirectionIndex ) {
0 commit comments