Skip to content

Commit eca7609

Browse files
committed
checkpoint
1 parent f73ee76 commit eca7609

File tree

1 file changed

+53
-5
lines changed

1 file changed

+53
-5
lines changed

cpp/common/src/codingstandards/cpp/Concurrency.qll

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -501,13 +501,42 @@ class C11MutexSource extends MutexSource, FunctionCall {
501501

502502
/**
503503
* Models a thread dependent mutex. A thread dependent mutex is a mutex
504-
* that is used by a thread.
504+
* that is used by a thread. This dependency is established either by directly
505+
* passing in a mutex or by referencing a mutex that is in the local scope. The utility
506+
* of this class is it captures the `DataFlow::Node` source at which the mutex
507+
* came from. For example, if it is passed in from a local function to a thread.
508+
* This functionality is critical, since it allows one to inspect how the thread
509+
* behaves with respect to the owner of a resource.
505510
*/
506-
class ThreadDependentMutex extends DataFlow::Node {
511+
abstract class ThreadDependentMutex extends DataFlow::Node {
512+
DataFlow::Node sink;
513+
514+
}
515+
class FlowBasedThreadDependentMutex extends ThreadDependentMutex {
507516
DataFlow::Node sink;
508517

509518
ThreadDependentMutex() {
510-
exists(ThreadDependentMutexTaintTrackingConfiguration config | config.hasFlow(this, sink))
519+
520+
// this predicate captures two cases. The first being some sort of dataflow,
521+
// likely through parameter passing.
522+
exists(ThreadDependentMutexTaintTrackingConfiguration config | config.hasFlow(this, sink)) or
523+
524+
// the second encapsulates usages from outside scopes not directly expressed
525+
// in dataflow.
526+
exists(MutexSource mutexSrc, ThreadedFunction f, Variable variableSource |
527+
DataFlow::exprNode(mutexSrc) = this and
528+
529+
// find a variable that was assigned the mutex
530+
TaintTracking::localTaint(DataFlow::exprNode(mutexSrc), DataFlow::exprNode(variableSource.getAnAssignedValue())) and
531+
532+
// find all subsequent accesses of that variable that are within a
533+
// function and set those to the sink
534+
exists(VariableAccess va |
535+
va = variableSource.getAnAccess() and
536+
va.getEnclosingFunction() = f
537+
and sink = DataFlow::exprNode(va)
538+
)
539+
)
511540
}
512541

513542
DataFlow::Node getASource() {
@@ -524,10 +553,23 @@ class ThreadDependentMutex extends DataFlow::Node {
524553
* dependent mutex.
525554
*/
526555
DataFlow::Node getAThreadSource() {
556+
// here we line up the actual parameter at the thread creation
557+
// site with the formal parameter in the target thread.
558+
// Note that there are differences between the C and C++ versions
559+
// of the argument ordering in the thread creation function. However,
560+
// since the C version only takes one parameter (as opposed to multiple)
561+
// we can simplify this search by considering only the first argument.
527562
exists(FunctionCall fc, Function f, int n |
563+
// Get the argument to which the mutex flowed.
528564
fc.getArgument(n) = sink.asExpr() and
565+
// Get the thread function we are calling.
529566
f = fc.getArgument(0).(FunctionAccess).getTarget() and
530-
result = DataFlow::exprNode(f.getParameter(n - 1).getAnAccess())
567+
// in C++, there is an extra argument to the `std::thread` call
568+
// so we must subtract 1 since this is not passed to the thread.
569+
(result = DataFlow::exprNode(f.getParameter(n - 1).getAnAccess()) or
570+
// In C, only one argument is allowed. Thus IF the flow predicate holds,
571+
// it will be to the first argument
572+
result = DataFlow::exprNode(f.getParameter(0).getAnAccess()))
531573
)
532574
}
533575

@@ -543,11 +585,17 @@ class ThreadDependentMutex extends DataFlow::Node {
543585
}
544586

545587
/**
546-
* Gets a set of usages of this mutex in both the local and thread scope.
588+
* Gets a set of usages of this mutex in both the local and thread scope.
589+
* In the case of scoped usage, this also captures typical accesses of variables.
547590
*/
548591
DataFlow::Node getAUsage() { TaintTracking::localTaint(getASource(), result) }
549592
}
550593

594+
class AccessBasedThreadDependentMutex extends ThreadDependentMutex {
595+
596+
}
597+
598+
551599
class ThreadDependentMutexTaintTrackingConfiguration extends TaintTracking::Configuration {
552600
ThreadDependentMutexTaintTrackingConfiguration() {
553601
this = "ThreadDependentMutexTaintTrackingConfiguration"

0 commit comments

Comments
 (0)