Home | History | Annotate | Download | only in tests
      1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Blacklisted typedefs
      6 typedef __INTMAX_TYPE__ intmax_t;
      7 typedef __UINTMAX_TYPE__ uintmax_t;
      8 typedef int intptr_t;
      9 typedef unsigned int uintptr_t;
     10 typedef __WINT_TYPE__ wint_t;
     11 typedef __SIZE_TYPE__ size_t;
     12 typedef __SIZE_TYPE__ rsize_t;
     13 typedef long ssize_t;
     14 typedef __PTRDIFF_TYPE__ ptrdiff_t;
     15 typedef unsigned int dev_t;
     16 typedef int off_t;
     17 typedef long clock_t;
     18 typedef int time_t;
     19 typedef long suseconds_t;
     20 
     21 // Other typedefs
     22 typedef int int32_t;
     23 typedef unsigned int uint32_t;
     24 typedef long int64_t;
     25 typedef unsigned long uint64_t;
     26 
     27 namespace std {
     28 
     29 template <class T>
     30 struct allocator {};
     31 
     32 template <class T, class A = allocator<T>>
     33 struct vector {};
     34 
     35 template <class F, class S>
     36 struct pair {};
     37 
     38 }  // namespace std
     39 
     40 namespace base {
     41 
     42 class Pickle {};
     43 
     44 template <class T, class... Ts>
     45 struct Tuple {
     46   T value;
     47 };
     48 
     49 }  // namespace base
     50 
     51 namespace IPC {
     52 
     53 template <class... T>
     54 struct CheckedTuple {
     55   typedef base::Tuple<T...> Tuple;
     56 };
     57 
     58 template <class T>
     59 struct ParamTraits {
     60   static void Write(base::Pickle*, const T&) {}
     61 };
     62 
     63 template <class T>
     64 void WriteParam(base::Pickle* pickle, const T& value) {
     65   ParamTraits<T>::Write(pickle, value);
     66 }
     67 
     68 }  // namespace IPC
     69 
     70 
     71 /* Test IPC::WriteParam() usage in templates. ERRORS: 6 */
     72 
     73 struct Data {
     74   uint32_t value;
     75   size_t size;
     76 };
     77 
     78 template <>
     79 struct IPC::ParamTraits<Data> {
     80   static void Write(base::Pickle* pickle, const Data& p) {
     81     // OK: WriteParam() called in explicit specialization
     82     WriteParam(pickle, p.value); // OK
     83     WriteParam(pickle, p.size); // ERROR
     84   }
     85 };
     86 
     87 template <class T>
     88 struct Container {
     89   T value;
     90 };
     91 
     92 template <class T>
     93 struct IPC::ParamTraits<Container<T>> {
     94   static void Write(base::Pickle* pickle, const Container<T>& container) {
     95     // NOT CHECKED: T is not explicitly referenced
     96     IPC::WriteParam(pickle, container.value); // NOT CHECKED
     97     WriteParam(pickle, container.value); // NOT CHECKED
     98 
     99     // NOT CHECKED: T explicitly referenced
    100     IPC::WriteParam<T>(pickle, container.value); // NOT CHECKED
    101     WriteParam<T>(pickle, container.value); // NOT CHECKED
    102 
    103     // OK: explicit cast to non-dependent allowed type
    104     WriteParam(pickle, static_cast<uint32_t>(container.value)); // OK
    105 
    106     // ERROR: explicit cast to non-dependent banned type
    107     WriteParam(pickle, static_cast<long>(container.value)); // ERROR
    108   }
    109 };
    110 
    111 template <class T, class... Ts>
    112 struct MultiContainer {
    113   T value;
    114 };
    115 
    116 template <class T, class... Ts>
    117 struct IPC::ParamTraits<MultiContainer<T, Ts...>> {
    118   static void Write(base::Pickle* pickle,
    119                     const MultiContainer<T, Ts...>& container) {
    120     // NOT CHECKED: template argument explicitly referenced
    121     bool helper[] = {
    122         (WriteParam<Ts>(pickle, container.value), true)... // NOT CHECKED
    123     };
    124     (void)helper;
    125   }
    126 };
    127 
    128 template <class T>
    129 struct SomeClass {
    130   static void Write(base::Pickle* pickle) {
    131     // NOT CHECKED: WriteParam() calls on dependent types
    132     IPC::WriteParam(pickle, T(0)); // NOT CHECKED
    133 
    134     // Non-dependent types are checked
    135     IPC::WriteParam(pickle, size_t(0)); // ERROR
    136     IPC::WriteParam(pickle, uint64_t(0)); // OK
    137   }
    138 
    139   template <class U>
    140   static void WriteEx(base::Pickle* pickle) {
    141     // NOT CHECKED: WriteParam() calls on dependent types
    142     IPC::WriteParam(pickle, U(0)); // NOT CHECKED
    143 
    144     // Non-dependent types are checked
    145     IPC::WriteParam(pickle, time_t(0)); // ERROR
    146     IPC::WriteParam(pickle, uint32_t(0)); // OK
    147   }
    148 };
    149 
    150 template <class T>
    151 void SomeWriteFunction(base::Pickle* pickle) {
    152   // NOT CHECKED: WriteParam() calls on dependent types
    153   IPC::WriteParam(pickle, T(0)); // NOT CHECKED
    154 
    155   // Non-dependent types are checked
    156   IPC::WriteParam(pickle, long(0)); // ERROR
    157   IPC::WriteParam(pickle, char(0)); // OK
    158 
    159   [&](){
    160     IPC::WriteParam(pickle, T(0)); // NOT CHECKED
    161 
    162     IPC::WriteParam(pickle, clock_t(0)); // ERROR
    163     IPC::WriteParam(pickle, int64_t(0)); // OK
    164   }();
    165 }
    166 
    167 void TestWriteParamInTemplates() {
    168   // These specializations call WriteParam() on various banned types, either
    169   // because they were specified directly (long) or because non-blacklisted
    170   // typedef (uint64_t) was stripped down to its underlying type, which is
    171   // blacklisted when used as is (unsigned long).
    172   // However, since it's hard (if not impossible) to check specializations
    173   // properly, we're simply not checking them.
    174   SomeClass<long>::Write(nullptr);
    175   SomeClass<long>::WriteEx<uint64_t>(nullptr);
    176   SomeWriteFunction<uint64_t>(nullptr);
    177 }
    178 
    179 
    180 /* Test IPC::CheckedTuple. ERRORS: 5 */
    181 
    182 #define IPC_TUPLE(...) IPC::CheckedTuple<__VA_ARGS__>::Tuple
    183 
    184 #define IPC_MESSAGE_DECL(name, id, in_tuple) \
    185   struct name ## Meta_ ## id { \
    186     using InTuple = in_tuple; \
    187   };
    188 
    189 #define IPC_TEST_MESSAGE(id, in) \
    190   IPC_MESSAGE_DECL(TestMessage, id, IPC_TUPLE in)
    191 
    192 struct Empty {};
    193 
    194 IPC_TEST_MESSAGE(__COUNTER__, (bool, size_t, Empty, long)) // 2 ERRORs
    195 
    196 typedef std::vector<long> long1D;
    197 typedef std::vector<long1D> long2D;
    198 IPC_TEST_MESSAGE(__COUNTER__, (bool, long2D)) // ERROR
    199 
    200 IPC_TEST_MESSAGE(__COUNTER__, (char, short, std::pair<size_t, bool>)) // ERROR
    201 
    202 IPC_TEST_MESSAGE(__COUNTER__, (std::vector<std::vector<long&>&>&)) // ERROR
    203 
    204 
    205 /* Check IPC::WriteParam() arguments. ERRORS: 30 */
    206 
    207 // ERRORS: 21
    208 void TestWriteParamArgument() {
    209   #define CALL_WRITEPARAM(Type) \
    210     { \
    211       Type p; \
    212       IPC::WriteParam(nullptr, p); \
    213     }
    214 
    215   // ERROR: blacklisted types / typedefs
    216   CALL_WRITEPARAM(long) // ERROR
    217   CALL_WRITEPARAM(unsigned long) // ERROR
    218   CALL_WRITEPARAM(intmax_t) // ERROR
    219   CALL_WRITEPARAM(uintmax_t) // ERROR
    220   CALL_WRITEPARAM(intptr_t) // ERROR
    221   CALL_WRITEPARAM(uintptr_t) // ERROR
    222   CALL_WRITEPARAM(wint_t) // ERROR
    223   CALL_WRITEPARAM(size_t) // ERROR
    224   CALL_WRITEPARAM(rsize_t) // ERROR
    225   CALL_WRITEPARAM(ssize_t) // ERROR
    226   CALL_WRITEPARAM(ptrdiff_t) // ERROR
    227   CALL_WRITEPARAM(dev_t) // ERROR
    228   CALL_WRITEPARAM(off_t) // ERROR
    229   CALL_WRITEPARAM(clock_t) // ERROR
    230   CALL_WRITEPARAM(time_t) // ERROR
    231   CALL_WRITEPARAM(suseconds_t) // ERROR
    232 
    233   // ERROR: typedef to blacklisted typedef
    234   typedef size_t my_size;
    235   CALL_WRITEPARAM(my_size) // ERROR
    236 
    237   // ERROR: expression ends up with type "unsigned long"
    238   {
    239     uint64_t p = 0;
    240     IPC::WriteParam(nullptr, p + 1); // ERROR
    241   }
    242 
    243   // ERROR: long chain of typedefs, ends up with blacklisted typedef
    244   {
    245     typedef size_t my_size_base;
    246     typedef const my_size_base my_size;
    247     typedef my_size& my_size_ref;
    248     my_size_ref p = 0;
    249     IPC::WriteParam(nullptr, p); // ERROR
    250   }
    251 
    252   // ERROR: template specialization references blacklisted type
    253   CALL_WRITEPARAM(std::vector<long>) // ERROR
    254   CALL_WRITEPARAM(std::vector<size_t>) // ERROR
    255 
    256   // OK: typedef to blacklisted type
    257   typedef long my_long;
    258   CALL_WRITEPARAM(my_long) // OK
    259 
    260   // OK: other types / typedefs
    261   CALL_WRITEPARAM(char) // OK
    262   CALL_WRITEPARAM(int) // OK
    263   CALL_WRITEPARAM(uint32_t) // OK
    264   CALL_WRITEPARAM(int64_t) // OK
    265 
    266   // OK: long chain of typedefs, ends up with non-blacklisted typedef
    267   {
    268     typedef uint32_t my_int_base;
    269     typedef const my_int_base my_int;
    270     typedef my_int& my_int_ref;
    271     my_int_ref p = 0;
    272     IPC::WriteParam(nullptr, p); // OK
    273   }
    274 
    275   // OK: template specialization references non-blacklisted type
    276   CALL_WRITEPARAM(std::vector<char>) // OK
    277   CALL_WRITEPARAM(std::vector<my_long>) // OK
    278 
    279   #undef CALL_WRITEPARAM
    280 }
    281 
    282 struct Provider {
    283   typedef unsigned int flags;
    284 
    285   short get_short() const { return 0; }
    286   uint64_t get_uint64() const { return 0; }
    287   long get_long() const { return 0; }
    288   unsigned int get_uint() const { return 0; }
    289   flags get_flags() const { return 0; }
    290   size_t get_size() const { return 0; }
    291 
    292   const std::vector<size_t>& get_sizes() const { return sizes_data; }
    293   const std::vector<uint64_t>& get_uint64s() const { return uint64s_data; }
    294 
    295   template <class T>
    296   T get() const { return T(); }
    297 
    298   short short_data;
    299   unsigned int uint_data;
    300   flags flags_data;
    301   long long_data;
    302   size_t size_data;
    303   uint64_t uint64_data;
    304   std::vector<size_t> sizes_data;
    305   std::vector<uint64_t> uint64s_data;
    306 };
    307 
    308 // ERRORS: 9
    309 void TestWriteParamMemberArgument() {
    310   Provider p;
    311 
    312   IPC::WriteParam(nullptr, p.get<short>()); // OK
    313   IPC::WriteParam(nullptr, p.get_short()); // OK
    314   IPC::WriteParam(nullptr, p.short_data); // OK
    315 
    316   IPC::WriteParam(nullptr, p.get<unsigned int>()); // OK
    317   IPC::WriteParam(nullptr, p.get_uint()); // OK
    318   IPC::WriteParam(nullptr, p.uint_data); // OK
    319 
    320   IPC::WriteParam(nullptr, p.get<Provider::flags>()); // OK
    321   IPC::WriteParam(nullptr, p.get_flags()); // OK
    322   IPC::WriteParam(nullptr, p.flags_data); // OK
    323 
    324   IPC::WriteParam(nullptr, p.get<long>()); // ERROR
    325   IPC::WriteParam(nullptr, p.get_long()); // ERROR
    326   IPC::WriteParam(nullptr, p.long_data); // ERROR
    327 
    328   // This one is flaky and depends on whether size_t is typedefed to a
    329   // blacklisted type (unsigned long).
    330   //IPC::WriteParam(nullptr, p.get<size_t>()); // ERROR
    331   IPC::WriteParam(nullptr, p.get_size()); // ERROR
    332   IPC::WriteParam(nullptr, p.size_data); // ERROR
    333 
    334   // Information about uint64_t gets lost, and plugin sees WriteParam()
    335   // call on unsigned long, which is blacklisted.
    336   IPC::WriteParam(nullptr, p.get<uint64_t>()); // ERROR
    337   IPC::WriteParam(nullptr, p.get_uint64()); // OK
    338   IPC::WriteParam(nullptr, p.uint64_data); // OK
    339 
    340   // Same thing here, WriteParam() sees vector<unsigned long>, and denies it.
    341   IPC::WriteParam(nullptr, p.get<std::vector<uint64_t>>()); // ERROR
    342   IPC::WriteParam(nullptr, p.get_uint64s()); // OK
    343   IPC::WriteParam(nullptr, p.uint64s_data); // OK
    344 
    345   // This one is flaky and depends on whether size_t is typedefed to a
    346   // blacklisted type (unsigned long).
    347   //IPC::WriteParam(nullptr, p.get<std::vector<size_t>>());
    348   IPC::WriteParam(nullptr, p.get_sizes()); // ERROR
    349   IPC::WriteParam(nullptr, p.sizes_data); // ERROR
    350 }
    351 
    352 
    353 /* ERRORS: 41 */
    354