Repository navigation
Conversation
… using 'char*' instead of 'const char*' which meant it would not type check when attempting to use string literals as keys (if we had been using a real implementation of those containers).
…nce it in models. Ideally, we should have a synthetic fields in dataflow for this instead. But this PR is large enough as it is, and this won't be a problem in real code as the member will always exist.
``` std::pair<std::pair<const char *, const char *>, const char *> m; ... sink(m); ``` and we only had a sink type for `std::pair<const char *, const char *>`.
… that templated constructors are instantiated. So this commit ensures that all the constructors that were not previously instantiated are now instantiated.
In `map.cpp` we had:
```
char *source();
...
std::unordered_map<const char *, std::pair<int, int>> m31;
...
sink(m31.try_emplace("abc", source(), 2));
```
which was incorrect because `source()` returns a `char*` and we're trying to stick it into a constructor for `std::pair<int, int>`.
…licated std::string declarations in 'azure.cpp' and 'bslx.cpp'.
…k flow on all integral types (which includes char-like types). Also add some MaD pretty-printing.
…ccept test changes.
There was a problem hiding this comment.
🟡 Changes recommended
A critical finding remains because the expected output file is not updated for the changed postprocessor output order, causing the query test to fail.
1 open issue
What changed in this PR
This PR isolates C++ test updates for the upcoming STL dataflow-model migration. It expands taint and security-test coverage, consolidates shared test stubs, and refreshes generated expectations.
Changes:
- Adds coverage for
std::string_view, string flows, maps, pairs, unordered maps, and cleartext storage. - Replaces duplicated STL and type-traits test stubs with shared definitions.
- Updates query references and generated model, flow, source, sink, and validation expectations.
The review identified one critical issue (2 votes) involving stale ExecTainted.expected output ordering, plus three moderate issues (1 vote each) involving assignment-result coverage, a synthetic string_view::subview API, and missing indirect-pointer string-view coverage.
| File | Reviewed changes and findings |
|---|---|
cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test2.cpp |
Adds cleartext-flow coverage for strings, character iteration, and references. |
cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextFileWrite.qlref |
Adds model pretty-printing to the query test. |
cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextFileWrite.expected |
Updates generated cleartext-flow expectations. |
cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.qlref |
Adds model pretty-printing; critical (2 votes): the corresponding expected output must be regenerated to reflect the changed output order. |
cpp/ql/test/library-tests/dataflow/taint-tests/type_traits.h |
Removes the obsolete local type-traits stub. |
cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected |
Updates generated signature and type-resolution expectations. |
cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp |
Adds string-view and reverse-flow coverage; moderate (1 vote): replace the synthetic basic_string_view::subview case with a real API or remove it; add an indirect_source() iterator-constructor case. |
cpp/ql/test/library-tests/dataflow/taint-tests/stl.h |
Expands shared STL declarations for strings, string views, containers, and related operations. |
cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp |
Updates map and pair tests; moderate (1 vote): exercise the map and unordered-map assignment expressions themselves, including their returned container/reference access paths. |
cpp/ql/test/library-tests/dataflow/external-models/validatemodels.expected |
Updates generated model-validation diagnostics. |
cpp/ql/test/library-tests/dataflow/external-models/steps.expected |
Updates generated external-model flow steps. |
cpp/ql/test/library-tests/dataflow/external-models/std_string.h |
Removes the obsolete external-model string stub. |
cpp/ql/test/library-tests/dataflow/external-models/sources.expected |
Updates generated external-source expectations. |
cpp/ql/test/library-tests/dataflow/external-models/sinks.expected |
Updates generated external-sink expectations. |
cpp/ql/test/library-tests/dataflow/external-models/protobuf.cpp |
Reuses the shared STL stub for protobuf tests. |
cpp/ql/test/library-tests/dataflow/external-models/bslx.cpp |
Reuses the shared STL stub for BSLX tests. |
cpp/ql/test/library-tests/dataflow/external-models/azure.cpp |
Reuses shared STL declarations and adds query-parameter coverage. |
cpp/ql/test/library-tests/dataflow/external-models/asio_streams.cpp |
Reuses shared STL and string-view declarations for Asio tests. |
cpp/ql/test/include/type_traits.h |
Provides shared global and std::size_t definitions for test stubs. |
Review effort: Lite (auto)
| sink(resolver.resolve(host_view, service_view, error)); // $ ir | ||
| sink(resolver.resolve(host_view, service_view, flags)); // $ ir | ||
| sink(resolver.resolve(host_view, service_view, flags, error)); // $ ir | ||
| sink(resolver.resolve(host_view, service_view)); // $ MISSING: ir |
There was a problem hiding this comment.
Why do these swap over to missing?
There was a problem hiding this comment.
Oh that's a good question. It took me some time to figure out what's going on here. I apologize for not making that clear in the commit why that is.
On main the string_view class declaration that's imported by asio_streams is very simplistic:
In 18200b7 we make the string_view much more realistic. In particular, we make the 6'th constructor from cppreference explicit. This has the effect of removing the generic taint-model we have for this constructor. So that's why we're losing the result.
| } | ||
|
|
||
| void test_GetHeader() { | ||
| std::pair<std::string, std::string>(); |
There was a problem hiding this comment.
This looks weird, as it just adds a constructor call.
There was a problem hiding this comment.
See the commit message here: 5f676c6
Does that explain it?
There was a problem hiding this comment.
So it uses that somewhere under the hood, but doesn't instantiate it there?
There was a problem hiding this comment.
In this case we need the class to be instantiated since we need a specific FieldContent to be present (for this piece of code).
There are two related problems that are being solved by instantiating the std::map<std::string, std::string> constructor here.
The main problem is that we've stubbed the body of the Azure::Core::Http::Request class. In a real implementation there would be a std::map<std::string, std::string> somewhere in that class (since such a value is returned by GetHeaders). So somewhere in that class where would be an instantiation which would make the members appear in the DB. However, as we only have declarations in our tests these members aren't instantiated.
So this commit adds the instantiations that were missing from the test database.
In this case we need it because #22939 will model std::map flow using a pair of Contents (like C# models them): a std::pair::second field content, and an ElementContent. The problem is that the std::pair::second field content doesn't exist in the database unless a the templated std::pair class is actually instantiated somewhere in the database.
There are other places where we need the constructor to be present since #22939 will model certain insertion-like STL member functions by forwarding the container insertion arguments to the corresponding constructor, and if the constructor isn't in the DB we cannot do that. Again, this would not be a problem in a real DB since those constructors will always exist, but with our tests stubs that won't happen since we only have declarations of the insertion-like functions and not the actual bodies.
Does that make sense?
There was a problem hiding this comment.
Yeah. Makes sense. I see that in cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp you added a comment when you did something similar, could you do that here too?
| sink(make_pair("123", "456").first); | ||
| sink(make_pair("123", "456").second); | ||
| sink(make_pair(source(), "456")); // $ MISSING: ast,ir | ||
| sink(make_pair(source(), "456")); // $ ir MISSING: ast |
There was a problem hiding this comment.
This happens because of dc46def. Before that commit, the sink had to be of type std::pair<const char*, const char*> so this converting constructor would be invoked before reaching the sink. And we don't have models for std::pair's constructors.
After dc46def we allow any pair<T, U> as a sink argument and thus no conversion takes place.
jketema
left a comment
There was a problem hiding this comment.
Few small questions above, otherwise this LGTM.
|
@jketema I believe I've addressed your questions! Thanks for the great comments 🙇 |
jketema
left a comment
There was a problem hiding this comment.
LGTM. Thanks for the clarifications!
Agreed that this doesn't need DCA.

This PR moves the test-related changes from #22939 into its own PR (as requested by @jketema).
Since no production code changes I don't think a DCA run is necessary.