/src/logging-log4cxx/src/fuzzers/cpp/PatternLayoutFuzzer.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
3 | | * contributor license agreements. See the NOTICE file distributed with |
4 | | * this work for additional information regarding copyright ownership. |
5 | | * The ASF licenses this file to You under the Apache License, Version 2.0 |
6 | | * (the "License"); you may not use this file except in compliance with |
7 | | * the License. You may obtain a copy of the License at |
8 | | * |
9 | | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | | * |
11 | | * Unless required by applicable law or agreed to in writing, software |
12 | | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | | * See the License for the specific language governing permissions and |
15 | | * limitations under the License. |
16 | | */ |
17 | | |
18 | | #include <iostream> // for `cout`, `endl` |
19 | | #include <cstdlib> // for `exit()`, `EXIT_FAILURE` |
20 | | #include <unistd.h> // for `readlink`, `chdir` |
21 | | #include <libgen.h> // for `dirname` |
22 | | #include <limits.h> // for `PATH_MAX` |
23 | | #include <iomanip> // for `put_time()` |
24 | | #include <ctime> // for `time()` |
25 | | #include <fuzzer/FuzzedDataProvider.h> |
26 | | #include <log4cxx/propertyconfigurator.h> |
27 | | #include <log4cxx/appenderskeleton.h> |
28 | | |
29 | | using namespace LOG4CXX_NS; |
30 | | |
31 | | namespace LOG4CXX_NS::fuzzer { |
32 | | |
33 | | /** |
34 | | * Appender encoding incoming log events using the provided layout. |
35 | | * It is intended for appender-agnostic fuzzing. |
36 | | */ |
37 | | class EncodingAppender : public AppenderSkeleton { |
38 | | |
39 | | public: |
40 | | DECLARE_LOG4CXX_OBJECT(EncodingAppender) |
41 | 7 | BEGIN_LOG4CXX_CAST_MAP() |
42 | 7 | LOG4CXX_CAST_ENTRY(EncodingAppender) |
43 | 7 | LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton) |
44 | 1 | END_LOG4CXX_CAST_MAP() |
45 | | |
46 | 1 | EncodingAppender() : AppenderSkeleton() {} |
47 | | |
48 | 0 | EncodingAppender(const LayoutPtr& layout) : AppenderSkeleton(layout) {} |
49 | | |
50 | 1 | void close() override {} |
51 | | |
52 | 1 | bool requiresLayout() const override { |
53 | 1 | return true; |
54 | 1 | } |
55 | | |
56 | 428k | void append(const spi::LoggingEventPtr& event, helpers::Pool& pool) override { |
57 | 428k | LogString msg; |
58 | 428k | getLayout()->format(msg, event, pool); |
59 | 428k | } |
60 | | |
61 | 1 | void activateOptions(helpers::Pool& pool) override {} |
62 | | |
63 | 0 | void setOption(const LogString& option, const LogString& value) override {} |
64 | | |
65 | | }; // class |
66 | | |
67 | | IMPLEMENT_LOG4CXX_OBJECT(EncodingAppender) |
68 | | |
69 | | LOG4CXX_PTR_DEF(EncodingAppender); |
70 | | |
71 | | } // namespace |
72 | | |
73 | | static std::time_t logTime; |
74 | | static std::tm* logTimeBuffer; |
75 | | #define LOG(stream) \ |
76 | 4 | logTime = std::time(nullptr); \ |
77 | 4 | logTimeBuffer = std::localtime(&logTime); \ |
78 | 4 | stream << std::put_time(logTimeBuffer, "%Y-%m-%d %H:%M:%S") << " [" << __FILE_NAME__ << ":" << __LINE__ << "] " |
79 | | |
80 | 1 | static void findExecutablePath(char* buffer) { |
81 | 1 | ssize_t length = readlink("/proc/self/exe", buffer, PATH_MAX); |
82 | 1 | if (length == -1) { |
83 | 0 | LOG(std::cerr) << "ERROR: Failed to find the executable path" << std::endl; |
84 | 0 | exit(EXIT_FAILURE); |
85 | 0 | } |
86 | 1 | buffer[length] = '\0'; |
87 | 1 | } |
88 | | |
89 | 1 | static void chdirExecutableHome() { |
90 | 1 | char executablePath[PATH_MAX]; |
91 | 1 | findExecutablePath(executablePath); |
92 | 1 | char* executableHome = dirname(executablePath); |
93 | 1 | if (chdir(executableHome) != 0) { |
94 | 0 | LOG(std::cerr) << "DEBUG: Executable path: " << executablePath << std::endl; |
95 | 0 | LOG(std::cerr) << "DEBUG: Executable home: " << executableHome << std::endl; |
96 | 0 | LOG(std::cerr) << "ERROR: Failed to `chdir()` the executable path" << std::endl; |
97 | 0 | } |
98 | 1 | } |
99 | | |
100 | | static int INITIALIZED = 0; |
101 | | |
102 | 573 | static void init() { |
103 | 573 | if (INITIALIZED != 0) { |
104 | 572 | return; |
105 | 572 | } |
106 | 1 | LOG(std::cout) << "INFO: Produced using the Git commit ID: " << GIT_COMMIT_ID << std::endl; |
107 | 1 | chdirExecutableHome(); |
108 | 1 | PropertyConfigurator::configure("PatternLayoutFuzzer.properties"); |
109 | 1 | INITIALIZED = 1; |
110 | 1 | } |
111 | | |
112 | 428k | #define MAX_STRING_LENGTH 512 |
113 | | |
114 | 573 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
115 | 573 | init(); |
116 | 573 | LoggerPtr logger = Logger::getRootLogger(); |
117 | 573 | FuzzedDataProvider dataProvider(data, size); |
118 | 428k | while (dataProvider.remaining_bytes() > 0) { |
119 | 428k | std::string message = dataProvider.ConsumeRandomLengthString(MAX_STRING_LENGTH); |
120 | 428k | LOG4CXX_INFO(logger, message); |
121 | 428k | } |
122 | 573 | return 0; |
123 | 573 | } |