Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cpp/ql/test/include/type_traits.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#if !defined(CODEQL_TYPE_TRAITS_H)
#define CODEQL_TYPE_TRAITS_H

typedef unsigned long size_t;
using size_t = decltype(sizeof(0));

namespace std {
using size_t = decltype(sizeof(0));
template<class T>
struct remove_const { typedef T type; };

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@

// --- stub library headers ---

#include "std_string.h"
#include "../taint-tests/stl.h"

#define SIZE_MAX 0xFFFFFFFF

namespace std {
class string_view {
public:
string_view(const char* s);
};
};

namespace boost {
namespace system {
class error_code {
Expand Down Expand Up @@ -150,20 +143,20 @@ void test_resolve_host() {
sink(resolver.resolve(host, service, flags)); // $ ir
sink(resolver.resolve(host, service, flags, error)); // $ ir

sink(resolver.resolve(host_view, service_view)); // $ ir
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do these swap over to missing?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

namespace std {
class string_view {
public:
string_view(const char* s);
};
};

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.

sink(resolver.resolve(host_view, service_view, error)); // $ MISSING: ir
sink(resolver.resolve(host_view, service_view, flags)); // $ MISSING: ir
sink(resolver.resolve(host_view, service_view, flags, error)); // $ MISSING: ir

sink(resolver.resolve(protocol, host, service)); // $ ir
sink(resolver.resolve(protocol, host, service, error)); // $ ir
sink(resolver.resolve(protocol, host, service, flags)); // $ ir
sink(resolver.resolve(protocol, host, service, flags, error)); // $ ir

sink(resolver.resolve(protocol, host_view, service_view)); // $ ir
sink(resolver.resolve(protocol, host_view, service_view, error)); // $ ir
sink(resolver.resolve(protocol, host_view, service_view, flags)); // $ ir
sink(resolver.resolve(protocol, host_view, service_view, flags, error)); // $ ir
sink(resolver.resolve(protocol, host_view, service_view)); // $ MISSING: ir
sink(resolver.resolve(protocol, host_view, service_view, error)); // $ MISSING: ir
sink(resolver.resolve(protocol, host_view, service_view, flags)); // $ MISSING: ir
sink(resolver.resolve(protocol, host_view, service_view, flags, error)); // $ MISSING: ir
}

void test_resolve_service() {
Expand All @@ -181,18 +174,18 @@ void test_resolve_service() {
sink(resolver.resolve(host, service, flags)); // $ ir
sink(resolver.resolve(host, service, flags, error)); // $ ir

sink(resolver.resolve(host_view, service_view)); // $ ir
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
sink(resolver.resolve(host_view, service_view, error)); // $ MISSING: ir
sink(resolver.resolve(host_view, service_view, flags)); // $ MISSING: ir
sink(resolver.resolve(host_view, service_view, flags, error)); // $ MISSING: ir

sink(resolver.resolve(protocol, host, service)); // $ ir
sink(resolver.resolve(protocol, host, service, error)); // $ ir
sink(resolver.resolve(protocol, host, service, flags)); // $ ir
sink(resolver.resolve(protocol, host, service, flags, error)); // $ ir

sink(resolver.resolve(protocol, host_view, service_view)); // $ ir
sink(resolver.resolve(protocol, host_view, service_view, error)); // $ ir
sink(resolver.resolve(protocol, host_view, service_view, flags)); // $ ir
sink(resolver.resolve(protocol, host_view, service_view, flags, error)); // $ ir
sink(resolver.resolve(protocol, host_view, service_view)); // $ MISSING: ir
sink(resolver.resolve(protocol, host_view, service_view, error)); // $ MISSING: ir
sink(resolver.resolve(protocol, host_view, service_view, flags)); // $ MISSING: ir
sink(resolver.resolve(protocol, host_view, service_view, flags, error)); // $ MISSING: ir
}
53 changes: 13 additions & 40 deletions cpp/ql/test/library-tests/dataflow/external-models/azure.cpp
Original file line number Diff line number Diff line change
@@ -1,55 +1,18 @@
#include "../taint-tests/stl.h"
using uint16_t = unsigned short;
using int64_t = long long;
using size_t = unsigned long;
using uint8_t = unsigned char;
using int32_t = int;
using uint32_t = unsigned int;

namespace std
{
class string
{
public:
string();
string(const char *);
~string();
};

template <typename K, typename V>
class map
{
public:
map();
~map();

V& operator[](const K& key);
};

template <typename T>
class vector
{
public:
vector();
~vector();

T& operator[](size_t);
};

template<typename T>
class unique_ptr {
public:
unique_ptr();
~unique_ptr();

T* get();
};
}

namespace Azure
{
template <typename T>
class Nullable
{
T m_value;

public:
Nullable();
Nullable(const T);
Expand Down Expand Up @@ -284,6 +247,9 @@ void test_RawResponse(Azure::Core::Http::RawResponse& resp) {
}

void test_GetHeader() {
// We instantiate the `std::pair` class since we need the `FieldContent` for
// `std::pair::second` to be present in the test DB.
std::pair<std::string, std::string>();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks weird, as it just adds a constructor call.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the commit message here: 5f676c6

Does that explain it?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it uses that somewhere under the hood, but doesn't instantiate it there?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 0854cc0

Azure::Core::Http::Request request(Azure::Core::Http::Get, Azure::Core::Url("http://example.com"));
{
auto headerValue = request.GetHeader("Content-Type").Value();
Expand All @@ -294,4 +260,11 @@ void test_GetHeader() {
std::string contentType = headers["Content-Type"];
sink(contentType); // $ ir
}
}

void test_QueryParameters() {
Azure::Core::Http::Request request(Azure::Core::Http::Get, Azure::Core::Url("http://example.com"));
Azure::Core::Url url;
url.SetQueryParameters(request.GetHeaders());
sink(url.GetQueryParameters()["query"]); // $ ir
}
18 changes: 1 addition & 17 deletions cpp/ql/test/library-tests/dataflow/external-models/bslx.cpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,4 @@

// --- stub library headers ---

namespace std {
typedef unsigned long size_t;
template <class T> class allocator {};
template<class charT> struct char_traits {};
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_string {
public:
basic_string();
basic_string(const charT* s, const Allocator& a = Allocator());
const charT* data() const;
size_t size() const;
};
typedef basic_string<char> string;
}
#include "../taint-tests/stl.h"

// BDE spells the standard string as `bsl::string`; alias it onto the stub above.
namespace bsl {
Expand Down
Loading
Loading