1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "parcel_fuzzer.h" 17 18#include "fuzz_log.h" 19#include "fuzzer/FuzzedDataProvider.h" 20#include "parcel.h" 21#include "securec.h" 22#include "string_ex.h" 23 24using namespace std; 25 26namespace OHOS { 27const uint8_t MAX_BUFFER_SIZE = 255; 28const uint8_t MAX_STRING_LENGTH = 255; 29const uint8_t MAX_VECTOR_SIZE = 10; 30const int MAX_OPERATIONS_GENERAL = 500; 31const int MAX_OPERATIONS_UNALIGNED = 100; 32const int MAX_OPERATIONS_OTHER = 15; 33 34enum Group { 35 GENERAL_GROUP = 0, 36 UNALIGNED_GROUP = 1, 37 OTHER_GROUP = 2, 38}; 39 40#define PARCEL_NO_INPUT_WITH_RETURN(T, FUN) \ 41 [](FuzzedDataProvider*, Parcel& p) { \ 42 FUZZ_LOGI("%{public}s", #FUN); \ 43 T t = p.FUN(); \ 44 (void)t; \ 45 } 46 47#define PARCEL_INT_INPUT_WITH_BOOL_RETURN(T, FUN) \ 48 [](FuzzedDataProvider* d, Parcel& p) { \ 49 FUZZ_LOGI("%{public}s", #FUN); \ 50 T data = d->ConsumeIntegral<T>(); \ 51 bool t = p.FUN(data); \ 52 (void)t; \ 53 } 54 55#define PARCEL_REF_INPUT_WITH_BOOL_RETURN(T, FUN) \ 56 [](FuzzedDataProvider*, Parcel& p) { \ 57 FUZZ_LOGI("%{public}s", #FUN); \ 58 T out {}; \ 59 bool t = p.FUN(out); \ 60 (void)t; \ 61 } 62 63#define PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(T, FUN) \ 64 [](FuzzedDataProvider* d, Parcel& p) { \ 65 FUZZ_LOGI("%{public}s", #FUN); \ 66 size_t n = d->ConsumeIntegralInRange<size_t>(1, MAX_VECTOR_SIZE); \ 67 void* buf = malloc(n * sizeof(T)); \ 68 size_t wb = d->ConsumeData(buf, n * sizeof(T)); \ 69 auto* tmp = static_cast<const T*>(buf); \ 70 std::vector<T> data(tmp, tmp + wb / sizeof(T)); \ 71 bool t = p.FUN(data); \ 72 (void)t; \ 73 free(buf); \ 74 } 75 76#define PARCEL_POINT_INPUT_WITH_BOOL_RETURN(T, FUN) \ 77 [](FuzzedDataProvider*, Parcel& p) { \ 78 FUZZ_LOGI("%{public}s", #FUN); \ 79 vector<T> out; \ 80 bool t = p.FUN(&out); \ 81 (void)t; \ 82 } 83 84class TestParcelable : public virtual Parcelable { 85public: 86 TestParcelable() = default; 87 explicit TestParcelable(bool asRemote) 88 { 89 asRemote_ = asRemote; 90 }; 91 ~TestParcelable() = default; 92 93 bool Marshalling(Parcel& parcel) const override; 94 static TestParcelable* Unmarshalling(Parcel& parcel); 95 static bool Marshalling(Parcel& parcel, const sptr<TestParcelable>& object); 96 97public: 98 int32_t int32Write_ = -0x12345678; 99 int32_t int32Read_; 100}; 101 102bool TestParcelable::Marshalling(Parcel& parcel) const 103{ 104 bool result = parcel.WriteInt32(this->int32Write_); 105 return result; 106} 107 108TestParcelable* TestParcelable::Unmarshalling(Parcel& parcel) 109{ 110 auto* read = new TestParcelable(); 111 read->int32Read_ = parcel.ReadInt32(); 112 return read; 113} 114 115bool TestParcelable::Marshalling(Parcel& parcel, const sptr<TestParcelable>& object) 116{ 117 bool result = parcel.WriteInt32(object->int32Write_); 118 return result; 119} 120 121class RemoteObject : public virtual Parcelable { 122public: 123 RemoteObject() 124 { 125 asRemote_ = true; 126 }; 127 bool Marshalling(Parcel& parcel) const override; 128 static sptr<RemoteObject> Unmarshalling(Parcel& parcel); 129}; 130 131bool RemoteObject::Marshalling(Parcel& parcel) const 132{ 133 parcel_flat_binder_object flat; 134 flat.hdr.type = 0xff; 135 flat.flags = 0x7f; 136 flat.binder = 0; 137 flat.handle = (uint32_t)(-1); 138 flat.cookie = reinterpret_cast<uintptr_t>(this); 139 bool status = parcel.WriteBuffer(&flat, sizeof(parcel_flat_binder_object)); 140 if (!status) { 141 return false; 142 } 143 return true; 144} 145 146sptr<RemoteObject> RemoteObject::Unmarshalling(Parcel& parcel) 147{ 148 const uint8_t* buffer = parcel.ReadBuffer(sizeof(parcel_flat_binder_object), false); 149 if (buffer == nullptr) { 150 return nullptr; 151 } 152 sptr<RemoteObject> obj = new RemoteObject(); 153 return obj; 154} 155 156const std::vector<std::function<void(FuzzedDataProvider*, Parcel&)>> operations = { 157 PARCEL_NO_INPUT_WITH_RETURN(size_t, GetDataSize), 158 PARCEL_NO_INPUT_WITH_RETURN(uintptr_t, GetData), 159 PARCEL_NO_INPUT_WITH_RETURN(size_t, GetOffsetsSize), 160 PARCEL_NO_INPUT_WITH_RETURN(size_t, GetWritableBytes), 161 PARCEL_NO_INPUT_WITH_RETURN(size_t, GetReadableBytes), 162 PARCEL_NO_INPUT_WITH_RETURN(size_t, GetDataCapacity), 163 PARCEL_NO_INPUT_WITH_RETURN(size_t, GetMaxCapacity), 164 165 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 166 FUZZ_LOGI("WriteBool"); 167 bool booltest = dataProvider->ConsumeBool(); 168 parcel.WriteBool(booltest); 169 }, 170 171 PARCEL_INT_INPUT_WITH_BOOL_RETURN(int8_t, WriteInt8), 172 PARCEL_INT_INPUT_WITH_BOOL_RETURN(int16_t, WriteInt16), 173 PARCEL_INT_INPUT_WITH_BOOL_RETURN(int32_t, WriteInt32), 174 PARCEL_INT_INPUT_WITH_BOOL_RETURN(int64_t, WriteInt64), 175 PARCEL_INT_INPUT_WITH_BOOL_RETURN(uint8_t, WriteUint8), 176 PARCEL_INT_INPUT_WITH_BOOL_RETURN(uint16_t, WriteUint16), 177 PARCEL_INT_INPUT_WITH_BOOL_RETURN(uint32_t, WriteUint32), 178 PARCEL_INT_INPUT_WITH_BOOL_RETURN(uint64_t, WriteUint64), 179 PARCEL_INT_INPUT_WITH_BOOL_RETURN(uintptr_t, WritePointer), 180 181 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 182 FUZZ_LOGI("WriteFloat"); 183 float floattest = dataProvider->ConsumeFloatingPoint<float>(); 184 parcel.WriteFloat(floattest); 185 }, 186 187 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 188 FUZZ_LOGI("WriteDouble"); 189 double doubletest = dataProvider->ConsumeFloatingPoint<double>(); 190 parcel.WriteDouble(doubletest); 191 }, 192 193 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 194 FUZZ_LOGI("WriteBuffer"); 195 size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE); 196 void* buffer = malloc(bufferSize); 197 size_t writtenBytes = dataProvider->ConsumeData(buffer, bufferSize); 198 parcel.WriteBuffer(buffer, writtenBytes); 199 free(buffer); 200 }, 201 202 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 203 FUZZ_LOGI("WriteBufferAddTerminator"); 204 size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE); 205 void* buffer = malloc(bufferSize); 206 size_t writtenBytes = dataProvider->ConsumeData(buffer, bufferSize); 207 const size_t maxTypeSize = 4; // max type size is 4 bytes. 208 if (writtenBytes == 0) { 209 free(buffer); 210 return; 211 } 212 size_t typeSize = dataProvider->ConsumeIntegralInRange<size_t>(0, maxTypeSize); 213 parcel.WriteBufferAddTerminator(buffer, writtenBytes, typeSize); 214 free(buffer); 215 }, 216 217 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 218 FUZZ_LOGI("WriteUnpadBuffer"); 219 size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE); 220 void* buffer = malloc(bufferSize); 221 size_t writtenBytes = dataProvider->ConsumeData(buffer, bufferSize); 222 parcel.WriteUnpadBuffer(buffer, writtenBytes); 223 free(buffer); 224 }, 225 226 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 227 FUZZ_LOGI("WriteCString"); 228 string teststr = dataProvider->ConsumeRandomLengthString(MAX_STRING_LENGTH); 229 parcel.WriteCString(teststr.c_str()); 230 }, 231 232 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 233 FUZZ_LOGI("WriteString"); 234 string teststr = dataProvider->ConsumeRandomLengthString(MAX_STRING_LENGTH); 235 parcel.WriteString(teststr); 236 }, 237 238 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 239 FUZZ_LOGI("WriteString16"); 240 string utf8 = dataProvider->ConsumeRandomLengthString(MAX_STRING_LENGTH); 241 u16string utf16 = Str8ToStr16(utf8); 242 parcel.WriteString16(utf16); 243 }, 244 245 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 246 FUZZ_LOGI("WriteString16WithLength"); 247 string utf8 = dataProvider->ConsumeRandomLengthString(MAX_STRING_LENGTH); 248 u16string utf16 = Str8ToStr16(utf8); 249 char16_t* value = utf16.data(); 250 parcel.WriteString16WithLength(value, utf16.length()); 251 }, 252 253 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 254 FUZZ_LOGI("WriteString8WithLength"); 255 string utf8 = dataProvider->ConsumeRandomLengthString(MAX_STRING_LENGTH); 256 char* value = utf8.data(); 257 parcel.WriteString8WithLength(value, utf8.length()); 258 }, 259 260 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 261 FUZZ_LOGI("WriteParcelable"); 262 bool remoteFlag = dataProvider->ConsumeBool(); 263 TestParcelable parcelableWrite(remoteFlag); 264 parcel.WriteParcelable(&parcelableWrite); 265 }, 266 267 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 268 FUZZ_LOGI("WriteStrongParcelable"); 269 bool remoteFlag = dataProvider->ConsumeBool(); 270 sptr<TestParcelable> parcelableWrite = new TestParcelable(remoteFlag); 271 parcel.WriteStrongParcelable(parcelableWrite); 272 }, 273 274 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 275 FUZZ_LOGI("WriteRemoteObject"); 276 RemoteObject obj; 277 parcel.WriteRemoteObject(&obj); 278 }, 279 280 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 281 FUZZ_LOGI("WriteObject"); 282 bool remoteFlag = dataProvider->ConsumeBool(); 283 sptr<TestParcelable> parcelableWrite = new TestParcelable(remoteFlag); 284 parcel.WriteObject(parcelableWrite); 285 }, 286 287 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 288 FUZZ_LOGI("ParseFrom"); 289 void* buffer = nullptr; 290 size_t testdataSize = parcel.GetDataSize(); 291 if (testdataSize > 0) { 292 buffer = malloc(testdataSize); 293 memcpy_s(buffer, testdataSize, reinterpret_cast<const uint8_t*>(parcel.GetData()), testdataSize); 294 } 295 Parcel parcel2(nullptr); 296 parcel2.ParseFrom(reinterpret_cast<uintptr_t>(buffer), testdataSize); 297 }, 298 299 PARCEL_NO_INPUT_WITH_RETURN(bool, ReadBool), 300 PARCEL_NO_INPUT_WITH_RETURN(int8_t, ReadInt8), 301 PARCEL_NO_INPUT_WITH_RETURN(int16_t, ReadInt16), 302 PARCEL_NO_INPUT_WITH_RETURN(int32_t, ReadInt32), 303 PARCEL_NO_INPUT_WITH_RETURN(int64_t, ReadInt64), 304 PARCEL_NO_INPUT_WITH_RETURN(uint8_t, ReadUint8), 305 PARCEL_NO_INPUT_WITH_RETURN(uint16_t, ReadUint16), 306 PARCEL_NO_INPUT_WITH_RETURN(uint32_t, ReadUint32), 307 PARCEL_NO_INPUT_WITH_RETURN(uint64_t, ReadUint64), 308 PARCEL_NO_INPUT_WITH_RETURN(float, ReadFloat), 309 PARCEL_NO_INPUT_WITH_RETURN(double, ReadDouble), 310 PARCEL_NO_INPUT_WITH_RETURN(uintptr_t, ReadPointer), 311 312 PARCEL_REF_INPUT_WITH_BOOL_RETURN(bool, ReadBool), 313 PARCEL_REF_INPUT_WITH_BOOL_RETURN(int8_t, ReadInt8), 314 PARCEL_REF_INPUT_WITH_BOOL_RETURN(int16_t, ReadInt16), 315 PARCEL_REF_INPUT_WITH_BOOL_RETURN(int32_t, ReadInt32), 316 PARCEL_REF_INPUT_WITH_BOOL_RETURN(int64_t, ReadInt64), 317 PARCEL_REF_INPUT_WITH_BOOL_RETURN(uint8_t, ReadUint8), 318 PARCEL_REF_INPUT_WITH_BOOL_RETURN(uint16_t, ReadUint16), 319 PARCEL_REF_INPUT_WITH_BOOL_RETURN(uint32_t, ReadUint32), 320 PARCEL_REF_INPUT_WITH_BOOL_RETURN(uint64_t, ReadUint64), 321 PARCEL_REF_INPUT_WITH_BOOL_RETURN(float, ReadFloat), 322 PARCEL_REF_INPUT_WITH_BOOL_RETURN(double, ReadDouble), 323 324 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 325 FUZZ_LOGI("ReadUnpadBuffer"); 326 size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE); 327 parcel.ReadUnpadBuffer(bufferSize); 328 }, 329 330 PARCEL_NO_INPUT_WITH_RETURN(const char*, ReadCString), 331 PARCEL_NO_INPUT_WITH_RETURN(string, ReadString), 332 PARCEL_REF_INPUT_WITH_BOOL_RETURN(string, ReadString), 333 PARCEL_NO_INPUT_WITH_RETURN(u16string, ReadString16), 334 PARCEL_REF_INPUT_WITH_BOOL_RETURN(u16string, ReadString16), 335 336 [](FuzzedDataProvider*, Parcel& parcel) { 337 FUZZ_LOGI("ReadString16WithLength"); 338 int32_t strlen = 0; 339 parcel.ReadString16WithLength(strlen); 340 }, 341 342 [](FuzzedDataProvider*, Parcel& parcel) { 343 FUZZ_LOGI("ReadString8WithLength"); 344 int32_t strlen = 0; 345 parcel.ReadString8WithLength(strlen); 346 }, 347 348 PARCEL_NO_INPUT_WITH_RETURN(size_t, GetReadPosition), 349 PARCEL_NO_INPUT_WITH_RETURN(size_t, GetWritePosition), 350 351 PARCEL_NO_INPUT_WITH_RETURN(sptr<TestParcelable>, ReadParcelable<TestParcelable>), 352 PARCEL_NO_INPUT_WITH_RETURN(sptr<TestParcelable>, ReadStrongParcelable<TestParcelable>), 353 PARCEL_NO_INPUT_WITH_RETURN(bool, CheckOffsets), 354 PARCEL_NO_INPUT_WITH_RETURN(sptr<TestParcelable>, ReadObject<TestParcelable>), 355 356 [](FuzzedDataProvider*, Parcel& parcel) { 357 FUZZ_LOGI("SetAllocator"); 358 parcel.SetAllocator(new DefaultAllocator()); 359 }, 360 361 [](FuzzedDataProvider*, Parcel& parcel) { 362 FUZZ_LOGI("InjectOffsets"); 363 Parcel parcel2(nullptr); 364 parcel2.InjectOffsets(parcel.GetObjectOffsets(), parcel.GetOffsetsSize()); 365 }, 366 367 [](FuzzedDataProvider*, Parcel& parcel) { 368 FUZZ_LOGI("FlushBuffer"); 369 parcel.FlushBuffer(); 370 }, 371 372 PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(int8_t, WriteInt8Vector), 373 PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(int32_t, WriteInt32Vector), 374 PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(int64_t, WriteInt64Vector), 375 PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(uint8_t, WriteUInt8Vector), 376 PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(uint16_t, WriteUInt16Vector), 377 PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(uint32_t, WriteUInt32Vector), 378 PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(uint64_t, WriteUInt64Vector), 379 PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(float, WriteFloatVector), 380 PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(double, WriteDoubleVector), 381 382 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 383 FUZZ_LOGI("WriteStringVector"); 384 size_t vectorSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_VECTOR_SIZE); 385 std::vector<string> testdata(vectorSize); 386 for (size_t i = 0; i < vectorSize; i++) { 387 size_t strlen = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_STRING_LENGTH); 388 std::vector<char> vec = dataProvider->ConsumeBytesWithTerminator<char>(strlen); 389 testdata[i] = vec.data(); 390 } 391 parcel.WriteStringVector(testdata); 392 }, 393 394 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 395 FUZZ_LOGI("WriteString16Vector"); 396 size_t vectorSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_VECTOR_SIZE); 397 std::vector<u16string> testdata(vectorSize); 398 for (size_t i = 0; i < vectorSize; i++) { 399 size_t strlen = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_STRING_LENGTH); 400 std::vector<char> vec = dataProvider->ConsumeBytesWithTerminator<char>(strlen); 401 string str = vec.data(); 402 testdata[i] = Str8ToStr16(str); 403 } 404 parcel.WriteString16Vector(testdata); 405 }, 406 407 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(int32_t, ReadInt32Vector), 408 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(int64_t, ReadInt64Vector), 409 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(uint32_t, ReadUInt32Vector), 410 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(uint64_t, ReadUInt64Vector), 411 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(float, ReadFloatVector), 412 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(double, ReadDoubleVector), 413 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(string, ReadStringVector), 414 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(u16string, ReadString16Vector), 415}; 416 417const std::vector<std::function<void(FuzzedDataProvider*, Parcel&)>> unaligned_operations = { 418 // error call ReadDouble after following methods, will crash with "signal SIGBUS: illegal alignment". 419 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 420 FUZZ_LOGI("ReadBuffer"); 421 size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE); 422 parcel.ReadBuffer(bufferSize); 423 }, 424 425 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 426 FUZZ_LOGI("SkipBytes"); 427 size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE); 428 parcel.SkipBytes(bufferSize); 429 }, 430 431 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 432 FUZZ_LOGI("RewindRead"); 433 size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE); 434 parcel.RewindRead(bufferSize); 435 }, 436 437 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(bool, ReadBoolVector), 438 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(int8_t, ReadInt8Vector), 439 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(int16_t, ReadInt16Vector), 440 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(uint8_t, ReadUInt8Vector), 441 PARCEL_POINT_INPUT_WITH_BOOL_RETURN(uint16_t, ReadUInt16Vector), 442 443 PARCEL_NO_INPUT_WITH_RETURN(bool, ReadBoolUnaligned), 444 PARCEL_REF_INPUT_WITH_BOOL_RETURN(int8_t, ReadInt8Unaligned), 445 PARCEL_REF_INPUT_WITH_BOOL_RETURN(int16_t, ReadInt16Unaligned), 446 PARCEL_REF_INPUT_WITH_BOOL_RETURN(uint8_t, ReadUint8Unaligned), 447 PARCEL_REF_INPUT_WITH_BOOL_RETURN(uint16_t, ReadUint16Unaligned), 448 449 // error call WriteDouble/WriteFloat after RewindWrite, will crash with "signal SIGBUS: illegal alignment". 450 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 451 FUZZ_LOGI("RewindWrite"); 452 size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE); 453 parcel.RewindWrite(bufferSize); 454 }, 455 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 456 FUZZ_LOGI("WriteBoolVector"); 457 size_t vectorSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_VECTOR_SIZE); 458 std::vector<uint8_t> data = dataProvider->ConsumeBytes<uint8_t>(vectorSize); 459 if (data.size() > 0) { 460 std::vector<bool> testdata(data.size()); 461 for (size_t i = 0; i < testdata.size(); i++) { 462 testdata[i] = 1 & data[i]; 463 } 464 parcel.WriteBoolVector(testdata); 465 } 466 }, 467 468 PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(int16_t, WriteInt16Vector), 469 470 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 471 FUZZ_LOGI("WriteBoolUnaligned"); 472 bool booltest = dataProvider->ConsumeBool(); 473 parcel.WriteBoolUnaligned(booltest); 474 }, 475 476 PARCEL_INT_INPUT_WITH_BOOL_RETURN(int8_t, WriteInt8Unaligned), 477 PARCEL_INT_INPUT_WITH_BOOL_RETURN(int16_t, WriteInt16Unaligned), 478 PARCEL_INT_INPUT_WITH_BOOL_RETURN(uint8_t, WriteUint8Unaligned), 479 PARCEL_INT_INPUT_WITH_BOOL_RETURN(uint16_t, WriteUint16Unaligned), 480}; 481 482const std::vector<std::function<void(FuzzedDataProvider*, Parcel&)>> other_operations = { 483 PARCEL_NO_INPUT_WITH_RETURN(size_t, GetDataSize), 484 PARCEL_NO_INPUT_WITH_RETURN(size_t, GetDataCapacity), 485 PARCEL_NO_INPUT_WITH_RETURN(size_t, GetMaxCapacity), 486 487 // cannot call randomly with other operations. 488 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 489 FUZZ_LOGI("SetDataCapacity"); 490 size_t capacity = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE); 491 parcel.SetDataCapacity(capacity); 492 }, 493 494 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 495 FUZZ_LOGI("SetDataSize"); 496 size_t dataSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE); 497 parcel.SetDataSize(dataSize); 498 }, 499 500 [](FuzzedDataProvider* dataProvider, Parcel& parcel) { 501 FUZZ_LOGI("SetMaxCapacity"); 502 size_t maxCapacity = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE); 503 parcel.SetMaxCapacity(maxCapacity); 504 }, 505}; 506 507void ParcelTestFunc(const uint8_t* data, size_t size, FuzzedDataProvider* dataProvider) 508{ 509 FUZZ_LOGI("ParcelTestFunc start"); 510 uint8_t opSet = dataProvider->ConsumeIntegralInRange<uint8_t>(GENERAL_GROUP, OTHER_GROUP); 511 uint8_t maxGeneral = operations.size() - 1; 512 uint8_t maxUnaligned = unaligned_operations.size() - 1; 513 uint8_t maxOther = other_operations.size() - 1; 514 Parcel parcel1(nullptr); 515 int opCnt = 0; 516 517 switch (opSet) { 518 case GENERAL_GROUP: 519 while (dataProvider->remaining_bytes() > 0 && opCnt++ < MAX_OPERATIONS_GENERAL) { 520 uint8_t op = dataProvider->ConsumeIntegralInRange<uint8_t>(0, maxGeneral); 521 operations[op](dataProvider, parcel1); 522 } 523 break; 524 case UNALIGNED_GROUP: 525 while (dataProvider->remaining_bytes() > 0 && opCnt++ < MAX_OPERATIONS_UNALIGNED) { 526 uint8_t op = dataProvider->ConsumeIntegralInRange<uint8_t>(0, maxUnaligned); 527 unaligned_operations[op](dataProvider, parcel1); 528 } 529 break; 530 case OTHER_GROUP: 531 while (dataProvider->remaining_bytes() > 0 && opCnt++ < MAX_OPERATIONS_OTHER) { 532 uint8_t op = dataProvider->ConsumeIntegralInRange<uint8_t>(0, maxOther); 533 other_operations[op](dataProvider, parcel1); 534 } 535 break; 536 default: 537 break; 538 } 539 FUZZ_LOGI("ParcelTestFunc end"); 540} 541 542} // namespace OHOS 543 544/* Fuzzer entry point */ 545extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) 546{ 547 FuzzedDataProvider dataProvider(data, size); 548 OHOS::ParcelTestFunc(data, size, &dataProvider); 549 return 0; 550} 551