| 1 | /* |
| 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
| 3 | * All rights reserved. |
| 4 | * |
| 5 | * This source code is licensed under both the BSD-style license (found in the |
| 6 | * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| 7 | * in the COPYING file in the root directory of this source tree). |
| 8 | * You may select, at your option, one of the above-listed licenses. |
| 9 | */ |
| 10 | |
| 11 | #include "fuzz.h" |
| 12 | #include "fuzz_helpers.h" |
| 13 | #include "util.h" |
| 14 | #include <stddef.h> |
| 15 | #include <stdint.h> |
| 16 | #include <stdio.h> |
| 17 | #include <stdlib.h> |
| 18 | |
| 19 | int main(int argc, char const **argv) { |
| 20 | size_t const kMaxFileSize = (size_t)1 << 27; |
| 21 | int const kFollowLinks = 1; |
| 22 | FileNamesTable* files; |
| 23 | const char** const fnTable = argv + 1; |
| 24 | uint8_t *buffer = NULL; |
| 25 | size_t bufferSize = 0; |
| 26 | unsigned i; |
| 27 | unsigned numFilesTested = 0; |
| 28 | int ret = 0; |
| 29 | |
| 30 | { |
| 31 | unsigned const numFiles = (unsigned)(argc - 1); |
| 32 | #ifdef UTIL_HAS_CREATEFILELIST |
| 33 | files = UTIL_createExpandedFNT(fnTable, numFiles, kFollowLinks); |
| 34 | #else |
| 35 | files = UTIL_createFNT_fromROTable(fnTable, numFiles); |
| 36 | assert(numFiles == files->tableSize); |
| 37 | #endif |
| 38 | } |
| 39 | if (!files) { |
| 40 | fprintf(stderr, "ERROR: Failed to create file names table\n"); |
| 41 | return 1; |
| 42 | } |
| 43 | if (files->tableSize == 0) |
| 44 | fprintf(stderr, "WARNING: No files passed to %s\n", argv[0]); |
| 45 | for (i = 0; i < files->tableSize; ++i) { |
| 46 | char const *fileName = files->fileNames[i]; |
| 47 | DEBUGLOG(3, "Running %s", fileName); |
| 48 | size_t const fileSize = UTIL_getFileSize(fileName); |
| 49 | size_t readSize; |
| 50 | FILE *file; |
| 51 | |
| 52 | /* Check that it is a regular file, and that the fileSize is valid. |
| 53 | * If it is not a regular file, then it may have been deleted since we |
| 54 | * constructed the list, so just skip it, but return an error exit code. |
| 55 | */ |
| 56 | if (!UTIL_isRegularFile(fileName)) { |
| 57 | ret = 1; |
| 58 | continue; |
| 59 | } |
| 60 | FUZZ_ASSERT_MSG(fileSize <= kMaxFileSize, fileName); |
| 61 | /* Ensure we have a large enough buffer allocated */ |
| 62 | if (fileSize > bufferSize) { |
| 63 | free(buffer); |
| 64 | buffer = (uint8_t *)malloc(fileSize); |
| 65 | FUZZ_ASSERT_MSG(buffer, fileName); |
| 66 | bufferSize = fileSize; |
| 67 | } |
| 68 | /* Open the file */ |
| 69 | file = fopen(fileName, "rb"); |
| 70 | FUZZ_ASSERT_MSG(file, fileName); |
| 71 | /* Read the file */ |
| 72 | readSize = fread(buffer, 1, fileSize, file); |
| 73 | FUZZ_ASSERT_MSG(readSize == fileSize, fileName); |
| 74 | /* Close the file */ |
| 75 | fclose(file); |
| 76 | /* Run the fuzz target */ |
| 77 | LLVMFuzzerTestOneInput(buffer, fileSize); |
| 78 | ++numFilesTested; |
| 79 | } |
| 80 | fprintf(stderr, "Tested %u files: ", numFilesTested); |
| 81 | if (ret == 0) { |
| 82 | fprintf(stderr, "Success!\n"); |
| 83 | } else { |
| 84 | fprintf(stderr, "Failure!\n"); |
| 85 | } |
| 86 | free(buffer); |
| 87 | UTIL_freeFileNamesTable(files); |
| 88 | return ret; |
| 89 | } |