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