Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Unified Diff: tools/clang/plugins/tests/ipc.cpp

Issue 1810243002: Check for unstable types in IPC messages. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add comment Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/clang/plugins/Options.h ('k') | tools/clang/plugins/tests/ipc.flags » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/clang/plugins/tests/ipc.cpp
diff --git a/tools/clang/plugins/tests/ipc.cpp b/tools/clang/plugins/tests/ipc.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d2bcef1d58d85e552c1dbaf00a7336edac14a10b
--- /dev/null
+++ b/tools/clang/plugins/tests/ipc.cpp
@@ -0,0 +1,353 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Blacklisted typedefs
+typedef __INTMAX_TYPE__ intmax_t;
+typedef __UINTMAX_TYPE__ uintmax_t;
+typedef int intptr_t;
+typedef unsigned int uintptr_t;
+typedef __WINT_TYPE__ wint_t;
+typedef __SIZE_TYPE__ size_t;
+typedef __SIZE_TYPE__ rsize_t;
+typedef long ssize_t;
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+typedef unsigned int dev_t;
+typedef int off_t;
+typedef long clock_t;
+typedef int time_t;
+typedef long suseconds_t;
+
+// Other typedefs
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef long int64_t;
+typedef unsigned long uint64_t;
+
+namespace std {
+
+template <class T>
+struct allocator {};
+
+template <class T, class A = allocator<T>>
+struct vector {};
+
+template <class F, class S>
+struct pair {};
+
+} // namespace std
+
+namespace base {
+
+class Pickle {};
+
+template <class T, class... Ts>
+struct Tuple {
+ T value;
+};
+
+} // namespace base
+
+namespace IPC {
+
+template <class... T>
+struct CheckedTuple {
+ typedef base::Tuple<T...> Tuple;
+};
+
+template <class T>
+struct ParamTraits {
+ static void Write(base::Pickle*, const T&) {}
+};
+
+template <class T>
+void WriteParam(base::Pickle* pickle, const T& value) {
+ ParamTraits<T>::Write(pickle, value);
+}
+
+} // namespace IPC
+
+
+/* Test IPC::WriteParam() usage in templates. ERRORS: 6 */
+
+struct Data {
+ uint32_t value;
+ size_t size;
+};
+
+template <>
+struct IPC::ParamTraits<Data> {
+ static void Write(base::Pickle* pickle, const Data& p) {
+ // OK: WriteParam() called in explicit specialization
+ WriteParam(pickle, p.value); // OK
+ WriteParam(pickle, p.size); // ERROR
+ }
+};
+
+template <class T>
+struct Container {
+ T value;
+};
+
+template <class T>
+struct IPC::ParamTraits<Container<T>> {
+ static void Write(base::Pickle* pickle, const Container<T>& container) {
+ // NOT CHECKED: T is not explicitly referenced
+ IPC::WriteParam(pickle, container.value); // NOT CHECKED
+ WriteParam(pickle, container.value); // NOT CHECKED
+
+ // NOT CHECKED: T explicitly referenced
+ IPC::WriteParam<T>(pickle, container.value); // NOT CHECKED
+ WriteParam<T>(pickle, container.value); // NOT CHECKED
+
+ // OK: explicit cast to non-dependent allowed type
+ WriteParam(pickle, static_cast<uint32_t>(container.value)); // OK
+
+ // ERROR: explicit cast to non-dependent banned type
+ WriteParam(pickle, static_cast<long>(container.value)); // ERROR
+ }
+};
+
+template <class T, class... Ts>
+struct MultiContainer {
+ T value;
+};
+
+template <class T, class... Ts>
+struct IPC::ParamTraits<MultiContainer<T, Ts...>> {
+ static void Write(base::Pickle* pickle,
+ const MultiContainer<T, Ts...>& container) {
+ // NOT CHECKED: template argument explicitly referenced
+ bool helper[] = {
+ (WriteParam<Ts>(pickle, container.value), true)... // NOT CHECKED
+ };
+ (void)helper;
+ }
+};
+
+template <class T>
+struct SomeClass {
+ static void Write(base::Pickle* pickle) {
+ // NOT CHECKED: WriteParam() calls on dependent types
+ IPC::WriteParam(pickle, T(0)); // NOT CHECKED
+
+ // Non-dependent types are checked
+ IPC::WriteParam(pickle, size_t(0)); // ERROR
+ IPC::WriteParam(pickle, uint64_t(0)); // OK
+ }
+
+ template <class U>
+ static void WriteEx(base::Pickle* pickle) {
+ // NOT CHECKED: WriteParam() calls on dependent types
+ IPC::WriteParam(pickle, U(0)); // NOT CHECKED
+
+ // Non-dependent types are checked
+ IPC::WriteParam(pickle, time_t(0)); // ERROR
+ IPC::WriteParam(pickle, uint32_t(0)); // OK
+ }
+};
+
+template <class T>
+void SomeWriteFunction(base::Pickle* pickle) {
+ // NOT CHECKED: WriteParam() calls on dependent types
+ IPC::WriteParam(pickle, T(0)); // NOT CHECKED
+
+ // Non-dependent types are checked
+ IPC::WriteParam(pickle, long(0)); // ERROR
+ IPC::WriteParam(pickle, char(0)); // OK
+
+ [&](){
+ IPC::WriteParam(pickle, T(0)); // NOT CHECKED
+
+ IPC::WriteParam(pickle, clock_t(0)); // ERROR
+ IPC::WriteParam(pickle, int64_t(0)); // OK
+ }();
+}
+
+void TestWriteParamInTemplates() {
+ // These specializations call WriteParam() on various banned types, either
+ // because they were specified directly (long) or because non-blacklisted
+ // typedef (uint64_t) was stripped down to its underlying type, which is
+ // blacklisted when used as is (unsigned long).
+ // However, since it's hard (if not impossible) to check specializations
+ // properly, we're simply not checking them.
+ SomeClass<long>::Write(nullptr);
+ SomeClass<long>::WriteEx<uint64_t>(nullptr);
+ SomeWriteFunction<uint64_t>(nullptr);
+}
+
+
+/* Test IPC::CheckedTuple. ERRORS: 5 */
+
+#define IPC_TUPLE(...) IPC::CheckedTuple<__VA_ARGS__>::Tuple
+
+#define IPC_MESSAGE_DECL(name, id, in_tuple) \
+ struct name ## Meta_ ## id { \
+ using InTuple = in_tuple; \
+ };
+
+#define IPC_TEST_MESSAGE(id, in) \
+ IPC_MESSAGE_DECL(TestMessage, id, IPC_TUPLE in)
+
+struct Empty {};
+
+IPC_TEST_MESSAGE(__COUNTER__, (bool, size_t, Empty, long)) // 2 ERRORs
+
+typedef std::vector<long> long1D;
+typedef std::vector<long1D> long2D;
+IPC_TEST_MESSAGE(__COUNTER__, (bool, long2D)) // ERROR
+
+IPC_TEST_MESSAGE(__COUNTER__, (char, short, std::pair<size_t, bool>)) // ERROR
+
+IPC_TEST_MESSAGE(__COUNTER__, (std::vector<std::vector<long&>&>&)) // ERROR
+
+
+/* Check IPC::WriteParam() arguments. ERRORS: 30 */
+
+// ERRORS: 21
+void TestWriteParamArgument() {
+ #define CALL_WRITEPARAM(Type) \
+ { \
+ Type p; \
+ IPC::WriteParam(nullptr, p); \
+ }
+
+ // ERROR: blacklisted types / typedefs
+ CALL_WRITEPARAM(long) // ERROR
+ CALL_WRITEPARAM(unsigned long) // ERROR
+ CALL_WRITEPARAM(intmax_t) // ERROR
+ CALL_WRITEPARAM(uintmax_t) // ERROR
+ CALL_WRITEPARAM(intptr_t) // ERROR
+ CALL_WRITEPARAM(uintptr_t) // ERROR
+ CALL_WRITEPARAM(wint_t) // ERROR
+ CALL_WRITEPARAM(size_t) // ERROR
+ CALL_WRITEPARAM(rsize_t) // ERROR
+ CALL_WRITEPARAM(ssize_t) // ERROR
+ CALL_WRITEPARAM(ptrdiff_t) // ERROR
+ CALL_WRITEPARAM(dev_t) // ERROR
+ CALL_WRITEPARAM(off_t) // ERROR
+ CALL_WRITEPARAM(clock_t) // ERROR
+ CALL_WRITEPARAM(time_t) // ERROR
+ CALL_WRITEPARAM(suseconds_t) // ERROR
+
+ // ERROR: typedef to blacklisted typedef
+ typedef size_t my_size;
+ CALL_WRITEPARAM(my_size) // ERROR
+
+ // ERROR: expression ends up with type "unsigned long"
+ {
+ uint64_t p = 0;
+ IPC::WriteParam(nullptr, p + 1); // ERROR
+ }
+
+ // ERROR: long chain of typedefs, ends up with blacklisted typedef
+ {
+ typedef size_t my_size_base;
+ typedef const my_size_base my_size;
+ typedef my_size& my_size_ref;
+ my_size_ref p = 0;
+ IPC::WriteParam(nullptr, p); // ERROR
+ }
+
+ // ERROR: template specialization references blacklisted type
+ CALL_WRITEPARAM(std::vector<long>) // ERROR
+ CALL_WRITEPARAM(std::vector<size_t>) // ERROR
+
+ // OK: typedef to blacklisted type
+ typedef long my_long;
+ CALL_WRITEPARAM(my_long) // OK
+
+ // OK: other types / typedefs
+ CALL_WRITEPARAM(char) // OK
+ CALL_WRITEPARAM(int) // OK
+ CALL_WRITEPARAM(uint32_t) // OK
+ CALL_WRITEPARAM(int64_t) // OK
+
+ // OK: long chain of typedefs, ends up with non-blacklisted typedef
+ {
+ typedef uint32_t my_int_base;
+ typedef const my_int_base my_int;
+ typedef my_int& my_int_ref;
+ my_int_ref p = 0;
+ IPC::WriteParam(nullptr, p); // OK
+ }
+
+ // OK: template specialization references non-blacklisted type
+ CALL_WRITEPARAM(std::vector<char>) // OK
+ CALL_WRITEPARAM(std::vector<my_long>) // OK
+
+ #undef CALL_WRITEPARAM
+}
+
+struct Provider {
+ typedef unsigned int flags;
+
+ short get_short() const { return 0; }
+ uint64_t get_uint64() const { return 0; }
+ long get_long() const { return 0; }
+ unsigned int get_uint() const { return 0; }
+ flags get_flags() const { return 0; }
+ size_t get_size() const { return 0; }
+
+ const std::vector<size_t>& get_sizes() const { return sizes_data; }
+ const std::vector<uint64_t>& get_uint64s() const { return uint64s_data; }
+
+ template <class T>
+ T get() const { return T(); }
+
+ short short_data;
+ unsigned int uint_data;
+ flags flags_data;
+ long long_data;
+ size_t size_data;
+ uint64_t uint64_data;
+ std::vector<size_t> sizes_data;
+ std::vector<uint64_t> uint64s_data;
+};
+
+// ERRORS: 9
+void TestWriteParamMemberArgument() {
+ Provider p;
+
+ IPC::WriteParam(nullptr, p.get<short>()); // OK
+ IPC::WriteParam(nullptr, p.get_short()); // OK
+ IPC::WriteParam(nullptr, p.short_data); // OK
+
+ IPC::WriteParam(nullptr, p.get<unsigned int>()); // OK
+ IPC::WriteParam(nullptr, p.get_uint()); // OK
+ IPC::WriteParam(nullptr, p.uint_data); // OK
+
+ IPC::WriteParam(nullptr, p.get<Provider::flags>()); // OK
+ IPC::WriteParam(nullptr, p.get_flags()); // OK
+ IPC::WriteParam(nullptr, p.flags_data); // OK
+
+ IPC::WriteParam(nullptr, p.get<long>()); // ERROR
+ IPC::WriteParam(nullptr, p.get_long()); // ERROR
+ IPC::WriteParam(nullptr, p.long_data); // ERROR
+
+ // This one is flaky and depends on whether size_t is typedefed to a
+ // blacklisted type (unsigned long).
+ //IPC::WriteParam(nullptr, p.get<size_t>()); // ERROR
+ IPC::WriteParam(nullptr, p.get_size()); // ERROR
+ IPC::WriteParam(nullptr, p.size_data); // ERROR
+
+ // Information about uint64_t gets lost, and plugin sees WriteParam()
+ // call on unsigned long, which is blacklisted.
+ IPC::WriteParam(nullptr, p.get<uint64_t>()); // ERROR
+ IPC::WriteParam(nullptr, p.get_uint64()); // OK
+ IPC::WriteParam(nullptr, p.uint64_data); // OK
+
+ // Same thing here, WriteParam() sees vector<unsigned long>, and denies it.
+ IPC::WriteParam(nullptr, p.get<std::vector<uint64_t>>()); // ERROR
+ IPC::WriteParam(nullptr, p.get_uint64s()); // OK
+ IPC::WriteParam(nullptr, p.uint64s_data); // OK
+
+ // This one is flaky and depends on whether size_t is typedefed to a
+ // blacklisted type (unsigned long).
+ //IPC::WriteParam(nullptr, p.get<std::vector<size_t>>());
+ IPC::WriteParam(nullptr, p.get_sizes()); // ERROR
+ IPC::WriteParam(nullptr, p.sizes_data); // ERROR
+}
+
+
+/* ERRORS: 41 */
« no previous file with comments | « tools/clang/plugins/Options.h ('k') | tools/clang/plugins/tests/ipc.flags » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698