Coverage Report

Created: 2025-07-12 06:12

/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
}