You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Predicates that use type tracking usually conform to the following general pattern (explanation follows below):
124
+
Predicates that use type tracking usually conform to the following general pattern, which we explain below:
125
125
126
126
.. code-block:: ql
127
127
@@ -175,7 +175,7 @@ this is the starting point of type tracking:
175
175
t.start() and
176
176
result = firebase().getAMethodCall("database")
177
177
178
-
In the recursive case, we apply the ``track`` predicate on a previously-found firebase database node, such as ``firebase.database()``.
178
+
In the recursive case, we apply the ``track`` predicate on a previously-found Firebase database node, such as ``firebase.database()``.
179
179
The ``track`` predicate maps this to a successor of that node, such as ``getDatabase()``, and
180
180
binds ``t`` to the continuation of ``t2`` with this extra step included:
181
181
@@ -186,8 +186,8 @@ binds ``t`` to the continuation of ``t2`` with this extra step included:
186
186
)
187
187
188
188
To understand the role of ``t`` here, note that type tracking can step *into* a property, which means
189
-
the data flow node returned from ``track`` is not necessarily a firebase database instance, it could be
190
-
an object *containing* a firebase database in one of its properties.
189
+
the data flow node returned from ``track`` is not necessarily a Firebase database instance, it could be
190
+
an object *containing* a Firebase database in one of its properties.
191
191
192
192
For example, in the program below, the ``firebaseDatabase(t)`` predicate includes the ``obj`` node in its result,
193
193
but with ``t`` recording the fact that the actual value being tracked is inside the ``DB`` property:
@@ -198,7 +198,7 @@ but with ``t`` recording the fact that the actual value being tracked is inside
198
198
let db =obj.DB;
199
199
200
200
This brings us to the last predicate. This uses ``TypeTracker::end()`` to filter out
201
-
the paths where the firebase database instance ended up inside a property of another object,
201
+
the paths where the Firebase database instance ended up inside a property of another object,
202
202
so it includes ``db`` but not ``obj``:
203
203
204
204
.. code-block:: ql
@@ -275,12 +275,12 @@ For reference, here's our simple Firebase model with type tracking on every pred
275
275
}
276
276
277
277
`Here <https://lgtm.com/query/1053770500827789481>`__ is a run of an example query using the model to find `set` calls on one of the Firebase sample projects.
278
-
It's been modified slightly to handle a bit more of the API, which is out of scope of this tutorial.
278
+
It's been modified slightly to handle a bit more of the API, which is beyond the scope of this tutorial.
279
279
280
280
Tracking associated data
281
281
------------------------
282
282
283
-
By adding extra parameters to the type-tracking predicate we can carry along
283
+
By adding extra parameters to the type-tracking predicate, we can carry along
284
284
extra bits of information about the result.
285
285
286
286
For example, here's a type-tracking version of ``firebaseRef()``, which
@@ -339,12 +339,12 @@ Reading is an asynchronous operation and the result is obtained through a callba
339
339
The actual forecast is obtained by the call to ``snapshot.val()``.
340
340
341
341
Looking for all method calls named ``val`` will in practice find many unrelated methods,
342
-
so we'll use type tracking again in order to take the receiver type into account.
342
+
so we'll use type tracking again to take the receiver type into account.
343
343
344
344
The receiver ``snapshot`` is a parameter to a callback function, which ultimately escapes
345
345
into the ``once()`` call. We'll extend our model from above to use back-tracking to find
346
-
all functions that flow into the ``once()`` call. Type tracking backwards is not much
347
-
different from forwards; the differences are:
346
+
all functions that flow into the ``once()`` call.
347
+
Backwards type tracking is not too different from forwards type tracking. The differences are:
348
348
349
349
- The ``TypeTracker`` parameter instead has type ``TypeBackTracker``.
350
350
- The call to ``.track()`` is instead a call to ``.backtrack()``
@@ -387,14 +387,14 @@ Based on that we can track the ``snapshot`` value and find the ``val()`` call it
387
387
result = firebaseSnapshot(refName).getAMethodCall("val")
388
388
}
389
389
390
-
With this addition, ``firebaseDatabaseRead("forecast")`` finds the call to ``snapshot.val()`` which contains the value of the forecast.
390
+
With this addition, ``firebaseDatabaseRead("forecast")`` finds the call to ``snapshot.val()`` that contains the value of the forecast.
391
391
392
392
`Here <https://lgtm.com/query/8761360814276109092>`__ is a run of an example query using the model to find `val` calls.
393
393
394
394
Summary
395
395
-------
396
396
397
-
This covers the use of the type-tracking library. To recap, use this template to define forward type-tracking predicates:
397
+
We have covered how to use the type-tracking library. To recap, use this template to define forward type-tracking predicates:
398
398
399
399
.. code-block:: ql
400
400
@@ -443,7 +443,7 @@ Limitations
443
443
As mentioned, type tracking will track values in and out of function calls and properties,
444
444
but only within some limits.
445
445
446
-
For example, type tracking does not always track *through* functions, that is, if a value flows into a parameter
446
+
For example, type tracking does not always track *through* functions. That is, if a value flows into a parameter
447
447
and back out of the return value, it might not be tracked back out to the call site again.
448
448
Here's an example that the model from this tutorial won't find:
449
449
@@ -455,12 +455,12 @@ Here's an example that the model from this tutorial won't find:
455
455
let wrapper =wrapDB(firebase.database())
456
456
wrapper.db.ref("forecast"); // <-- not found
457
457
458
-
This is an example of where `dataflow configurations <https://help.semmle.com/QL/learn-ql/javascript/dataflow.html#global-data-flow>`__ are more powerful.
458
+
This is an example of where `data-flow configurations <https://help.semmle.com/QL/learn-ql/javascript/dataflow.html#global-data-flow>`__ are more powerful.
459
459
460
460
When to use type tracking
461
461
-------------------------
462
462
463
-
Type tracking and dataflow configurations are different solutions to the same
463
+
Type tracking and data-flow configurations are different solutions to the same
464
464
problem, each with their own tradeoffs.
465
465
466
466
Type tracking can be used in any number of predicates, which may depend on each other
@@ -470,23 +470,23 @@ Type-tracking predicates can have any number of extra parameters, making it poss
470
470
to construct source/sink pairs. Omitting source/sink pairs can be useful when there is a huge number
471
471
of sources and sinks.
472
472
473
-
Dataflow configurations have more restricted dependencies but are more powerful in other ways.
473
+
Data-flow configurations have more restricted dependencies but are more powerful in other ways.
474
474
For performance reasons,
475
475
the sources, sinks, and steps of a configuration should not depend on whether a flow path has been found using
476
476
that configuration or any other configuration.
477
477
In that sense, the sources, sinks, and steps must be configured "up front" and can't be discovered on-the-fly.
478
478
The upside is that they track flow through functions and callbacks in some ways that type tracking doesn't,
479
479
which is particularly important for security queries.
480
-
Also, path queries can only be defined using dataflow configurations.
480
+
Also, path queries can only be defined using data-flow configurations.
481
481
482
482
Prefer type tracking when:
483
483
484
484
- Disambiguating generically named methods or properties.
485
485
- Making reusable library components to be shared between queries.
486
486
- The set of source/sink pairs is too large to compute or has insufficient information.
487
-
- The information is needed as input to a dataflow configuration.
487
+
- The information is needed as input to a data-flow configuration.
488
488
489
-
Prefer dataflow configurations when:
489
+
Prefer data-flow configurations when:
490
490
491
491
- Tracking user-controlled data -- use `taint tracking <https://help.semmle.com/QL/learn-ql/javascript/dataflow.html#using-global-taint-tracking>`__.
492
492
- Differentiating between different kinds of user-controlled data -- use :doc:`flow labels <flow-labels>`.
0 commit comments