diff --git a/.github/workflows/ci-fuzz-micro.yml b/.github/workflows/ci-fuzz-micro.yml
new file mode 100644
index 00000000..f9b16ebe
--- /dev/null
+++ b/.github/workflows/ci-fuzz-micro.yml
@@ -0,0 +1,47 @@
+name: fuzz-micro-job
+
+on:
+ push:
+ branches: [ '**' ]
+ pull_request:
+ branches: [ '**' ]
+
+permissions:
+ contents: read
+
+jobs:
+ fuzz:
+ runs-on: ci-test
+ if: ${{ github.repository != 'intel/pcm' }}
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
+ with:
+ egress-policy: audit
+
+ - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ with:
+ submodules: recursive
+
+ - name: Build and test
+ run: |
+ cmake --version
+ set -o pipefail
+ mkdir build
+ cd build
+ bash ${{ github.workspace }}/tests/fuzz.sh 5 2>&1 | tee fuzz-log.txt
+ cd ..
+
+ - name: Show report
+ run: |
+ cat build/report.txt
+ echo "Fuzzing completed"
+
+ - name: upload-artifact
+ uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ with:
+ name: fuzz-log-${{ github.sha }}
+ path: "build/fuzz-log.txt"
+
+
diff --git a/.github/workflows/ci-fuzz-short.yml b/.github/workflows/ci-fuzz-short.yml
new file mode 100644
index 00000000..d1437ef5
--- /dev/null
+++ b/.github/workflows/ci-fuzz-short.yml
@@ -0,0 +1,46 @@
+name: fuzz-short-job
+
+on:
+ # manual triggering
+ workflow_dispatch:
+
+
+permissions:
+ contents: read
+
+jobs:
+ fuzz:
+ runs-on: ci-test
+ if: ${{ github.repository != 'intel/pcm' }}
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
+ with:
+ egress-policy: audit
+
+ - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
+ with:
+ submodules: recursive
+
+ - name: Build and test
+ run: |
+ cmake --version
+ set -o pipefail
+ mkdir build
+ cd build
+ bash ${{ github.workspace }}/tests/fuzz.sh 10 2>&1 | tee fuzz-log.txt
+ cd ..
+
+ - name: Show report
+ run: |
+ cat build/report.txt
+ echo "Fuzzing completed"
+
+ - name: upload-artifact
+ uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ with:
+ name: fuzz-log-${{ github.sha }}
+ path: "build/fuzz-log.txt"
+
+
diff --git a/.github/workflows/ci-fuzz.yml b/.github/workflows/ci-fuzz.yml
index 30b182fd..b8a99417 100644
--- a/.github/workflows/ci-fuzz.yml
+++ b/.github/workflows/ci-fuzz.yml
@@ -32,7 +32,7 @@ jobs:
set -o pipefail
mkdir build
cd build
- sh ${{ github.workspace }}/tests/fuzz.sh 2>&1 | tee fuzz-log.txt
+ bash ${{ github.workspace }}/tests/fuzz.sh 300 2>&1 | tee fuzz-log.txt
cd ..
- name: Show report
diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml
index b18a7289..63231c9c 100644
--- a/.github/workflows/ci-test.yml
+++ b/.github/workflows/ci-test.yml
@@ -37,7 +37,7 @@ jobs:
- name: Test
run: |
set -o pipefail
- sh ${{ github.workspace }}/tests/test.sh 2>&1 | tee test-log.txt
+ bash ${{ github.workspace }}/tests/test.sh 2>&1 | tee test-log.txt
- name: upload-artifact
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 559aee9a..7317172c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -82,9 +82,18 @@ if(UNIX) # APPLE, LINUX, FREE_BSD
elseif()
set (PCM_DYNAMIC "")
endif()
- set(CMAKE_CXX_FLAGS_RELEASE "${PCM_OPTIONAL_FLAGS} -O3 ${PCM_DYNAMIC}")
- set(CMAKE_CXX_FLAGS_DEBUG "${PCM_OPTIONAL_FLAGS} -O0 -g ${PCM_DYNAMIC}")
- set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${PCM_OPTIONAL_FLAGS} -O3 -g ${PCM_DYNAMIC}")
+ set(PCM_HARDENING_FLAGS "-fPIE -fstack-protector -D_FORTIFY_SOURCE=2 -ftrapv -fsanitize=address -fwrapv -fno-delete-null-pointer-checks -fno-strict-overflow -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer")
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5)
+ message(WARNING "Old gcc compiler (version < 5), -fsanitize=undefined option is not supported.")
+ elseif()
+ set(PCM_HARDENING_FLAGS "${PCM_HARDENING_FLAGS} -fsanitize=undefined")
+ endif()
+ set(PCM_LINKER_HARDENING_FLAGS "-fsanitize=address")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PCM_LINKER_HARDENING_FLAGS}")
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${PCM_LINKER_HARDENING_FLAGS}")
+ set(CMAKE_CXX_FLAGS_RELEASE "${PCM_OPTIONAL_FLAGS} -O3 ${PCM_DYNAMIC} ${PCM_HARDENING_FLAGS}")
+ set(CMAKE_CXX_FLAGS_DEBUG "${PCM_OPTIONAL_FLAGS} -O0 -g ${PCM_DYNAMIC} ${PCM_HARDENING_FLAGS}")
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${PCM_OPTIONAL_FLAGS} -O3 -g ${PCM_DYNAMIC} ${PCM_HARDENING_FLAGS}")
if(FREE_BSD)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -lexecinfo")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -lexecinfo")
@@ -94,6 +103,10 @@ if(UNIX) # APPLE, LINUX, FREE_BSD
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
+ message(STATUS "CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}")
+ message(STATUS "CMAKE_CXX_FLAGS_DEBUG: ${CMAKE_CXX_FLAGS_DEBUG}")
+ message(STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
+
endif(UNIX)
if(FUZZ)
diff --git a/_service b/_service
new file mode 100644
index 00000000..ed1bc588
--- /dev/null
+++ b/_service
@@ -0,0 +1,12 @@
+
+
+ github.com
+ https
+ /intel/pcm/archive/master.zip
+
+
+ github.com
+ https
+ /intel/pcm/archive/master.tar.gz
+
+raw.githubusercontent.comhttps/intel/pcm/master/pcm.spec
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6e1a82cc..a7db0e4b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,10 +1,13 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2022, Intel Corporation
+include(FindOpenSSL)
# All pcm-* executables
set(PROJECT_NAMES pcm pcm-numa pcm-latency pcm-power pcm-msr pcm-memory pcm-tsx pcm-pcie pcm-core pcm-iio pcm-lspci pcm-pcicfg pcm-mmio pcm-tpmi pcm-raw pcm-accel)
+set(MINIMUM_OPENSSL_VERSION 1.1.1)
+
file(GLOB COMMON_SOURCES pcm-accel-common.cpp msr.cpp cpucounters.cpp pci.cpp mmio.cpp tpmi.cpp pmt.cpp bw.cpp utils.cpp topology.cpp debug.cpp threadpool.cpp uncore_pmu_discovery.cpp)
if (APPLE)
@@ -32,8 +35,11 @@ if(UNIX) # LINUX, FREE_BSD, APPLE
$<$:PCM_SILENT>
)
+ target_compile_options(PCM_STATIC_SILENT PRIVATE "-fPIC")
+
# libpcm.so
add_library(PCM_SHARED SHARED pcm-core.cpp)
+ target_compile_options(PCM_SHARED PRIVATE -DPCM_SHARED_LIBRARY=1)
# PCM_SILENT in Release* for pcm-core.cpp
target_compile_definitions(PCM_SHARED PRIVATE
$<$:PCM_SILENT>
@@ -44,6 +50,8 @@ if(UNIX) # LINUX, FREE_BSD, APPLE
add_subdirectory(MacMSRDriver)
include_directories("${CMAKE_SOURCE_DIR}/src/MacMSRDriver") # target_include_directories doesn't work
target_link_libraries(PCM_SHARED PRIVATE PCM_STATIC_SILENT PcmMsr Threads::Threads)
+ elseif(LINUX)
+ target_link_libraries(PCM_SHARED PRIVATE PCM_STATIC_SILENT Threads::Threads asan)
else()
target_link_libraries(PCM_SHARED PRIVATE PCM_STATIC_SILENT Threads::Threads)
endif()
@@ -145,9 +153,14 @@ foreach(PROJECT_NAME ${PROJECT_NAMES})
else()
message(STATUS "Compiling with SSL support, requires libssl-dev or openssl-devel or libopenssl-devel or libopenssl-dev package installed")
message(STATUS "To disable SSL support, use -DNO_SSL=1 option")
- find_package(OpenSSL REQUIRED)
- target_compile_options(${PROJECT_NAME} PRIVATE "-DUSE_SSL")
- set(LIBS ${LIBS} OpenSSL::SSL OpenSSL::Crypto)
+ find_package(OpenSSL ${MINIMUM_OPENSSL_VERSION} QUIET)
+ if(OPENSSL_FOUND)
+ message(STATUS "OpenSSL version ${OPENSSL_VERSION} >= ${MINIMUM_OPENSSL_VERSION}, OpenSSL support enabled")
+ target_compile_options(${PROJECT_NAME} PRIVATE "-DUSE_SSL")
+ set(LIBS ${LIBS} OpenSSL::SSL OpenSSL::Crypto)
+ else()
+ message(STATUS "OpenSSL support has been disabled, the version is less than ${MINIMUM_OPENSSL_VERSION}")
+ endif()
endif()
file(READ pcm-sensor-server.service.in SENSOR_SERVICE_IN)
string(REPLACE "@@CMAKE_INSTALL_SBINDIR@@" "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SBINDIR}" SENSOR_SERVICE "${SENSOR_SERVICE_IN}")
diff --git a/src/cpuasynchcounter.h b/src/cpuasynchcounter.h
index 92fd3981..7b33fe68 100644
--- a/src/cpuasynchcounter.h
+++ b/src/cpuasynchcounter.h
@@ -77,10 +77,10 @@ class AsynchronCounterState {
{
std::cerr << "PCM Error in ~AsynchronCounterState(). Exception " << e.what() << "\n";
}
- delete[] cstates1;
- delete[] cstates2;
- delete[] skstates1;
- delete[] skstates2;
+ deleteAndNullifyArray(cstates1);
+ deleteAndNullifyArray(cstates2);
+ deleteAndNullifyArray(skstates1);
+ deleteAndNullifyArray(skstates2);
}
uint32 getNumCores()
diff --git a/src/cpucounters.cpp b/src/cpucounters.cpp
index cbae950f..22afedff 100644
--- a/src/cpucounters.cpp
+++ b/src/cpucounters.cpp
@@ -513,7 +513,7 @@ bool PCM::isRDTDisabled() const
flag = 0;
}
#ifdef _MSC_VER
- free(env);
+ freeAndNullify(env);
#endif
}
return flag > 0;
@@ -1204,7 +1204,7 @@ bool PCM::discoverSystemTopology()
while (res == FALSE)
{
- delete[] slpi;
+ deleteAndNullifyArray(slpi);
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
@@ -1263,7 +1263,7 @@ bool PCM::discoverSystemTopology()
socketIdMap[entry.socket] = 0;
}
- delete[] base_slpi;
+ deleteAndNullifyArray(base_slpi);
#else
// for Linux, Mac OS, FreeBSD and DragonFlyBSD
@@ -1374,7 +1374,7 @@ bool PCM::discoverSystemTopology()
return false; \
} \
ret_value = convertUnknownToInt(size, pParam); \
- free(pParam); \
+ freeAndNullify(pParam); \
}
// End SAFE_SYSCTLBYNAME
@@ -3307,7 +3307,7 @@ PCM::~PCM()
{
destroyMSR();
instance = NULL;
- delete systemTopology;
+ deleteAndNullify(systemTopology);
}
}
@@ -7160,7 +7160,7 @@ PciHandleType * ServerUncorePMUs::createIntelPerfMonDevice(uint32 groupnr_, int3
if(vendor_id == PCM_INTEL_PCI_VENDOR_ID) return handle;
- delete handle;
+ deleteAndNullify(handle);
}
return NULL;
}
@@ -8600,6 +8600,18 @@ ServerUncorePMUs::~ServerUncorePMUs()
void ServerUncorePMUs::programServerUncoreMemoryMetrics(const ServerUncoreMemoryMetrics & metrics, const int rankA, const int rankB)
{
+ switch (metrics)
+ {
+ case PartialWrites:
+ case Pmem:
+ case PmemMemoryMode:
+ case PmemMixedMode:
+ break;
+ default:
+ std::cerr << "PCM Error: unknown memory metrics: " << metrics << "\n";
+ return;
+ }
+
PCM * pcm = PCM::getInstance();
uint32 MCCntConfig[4] = {0,0,0,0};
uint32 EDCCntConfig[4] = {0,0,0,0};
@@ -8695,6 +8707,16 @@ void ServerUncorePMUs::programServerUncoreMemoryMetrics(const ServerUncoreMemory
}
}
} else {
+ if (rankA < 0 || rankA > 7)
+ {
+ std::cerr << "PCM Error: invalid rankA value: " << rankA << "\n";
+ return;
+ }
+ if (rankB < 0 || rankB > 7)
+ {
+ std::cerr << "PCM Error: invalid rankB value: " << rankB << "\n";
+ return;
+ }
switch(cpu_model)
{
case PCM::IVYTOWN:
@@ -9742,7 +9764,7 @@ PciHandleType * getDeviceHandle(uint32 vendorId, uint32 deviceId)
const uint32 did = (value >> 16) & 0xffff;
if (vid == vendorId && did == deviceId)
return h;
- delete h;
+ deleteAndNullify(h);
}
}
}
@@ -9792,7 +9814,7 @@ uint32 PCM::getMaxNumOfCBoxesInternal() const
num = (uint32)weight32(value);
h->read32(0xa0, &value);
num += (uint32)weight32(value);
- delete h;
+ deleteAndNullify(h);
}
else
{
@@ -10457,8 +10479,8 @@ CounterWidthExtender::CounterWidthExtender(AbstractRawCounter * raw_counter_, ui
}
CounterWidthExtender::~CounterWidthExtender()
{
- delete UpdateThread;
- if (raw_counter) delete raw_counter;
+ deleteAndNullify(UpdateThread);
+ deleteAndNullify(raw_counter);
}
diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp
index ffa271f8..0a0bee20 100644
--- a/src/daemon/daemon.cpp
+++ b/src/daemon/daemon.cpp
@@ -89,8 +89,8 @@ namespace PCMDaemon {
Daemon::~Daemon()
{
- delete[] serverUncoreCounterStatesBefore_;
- delete[] serverUncoreCounterStatesAfter_;
+ deleteAndNullifyArray(serverUncoreCounterStatesBefore_);
+ deleteAndNullifyArray(serverUncoreCounterStatesAfter_);
}
void Daemon::setupPCM()
diff --git a/src/memoptest.cpp b/src/memoptest.cpp
index dda78042..3c852931 100644
--- a/src/memoptest.cpp
+++ b/src/memoptest.cpp
@@ -132,7 +132,7 @@ int main(int argc, char * argv[])
cout << "Bandwidth: " << (sizeof(T) * nelements * niter) / ((after_ts - before_ts) * 1024 * 1024) << " MByte/sec\n" << std::flush;
}
- delete[] vector;
+ deleteAndNullifyArray(vector);
return 0;
}
diff --git a/src/msr.cpp b/src/msr.cpp
index 27397e45..46c36cd3 100644
--- a/src/msr.cpp
+++ b/src/msr.cpp
@@ -126,8 +126,7 @@ MsrHandle::~MsrHandle()
MsrHandle::num_handles--;
if (MsrHandle::num_handles == 0)
{
- delete driver;
- driver = NULL;
+ deleteAndNullify(driver);
}
}
@@ -228,6 +227,7 @@ MsrHandle::MsrHandle(uint32 cpu) : fd(-1), cpu_id(cpu)
writesEnabled = true;
}
char * path = new char[200];
+ if (!path) throw std::runtime_error("Allocation of 200 bytes failed.");
snprintf(path, 200, "/dev/cpu/%d/msr", cpu);
int handle = ::open(path, O_RDWR);
if (handle < 0)
@@ -235,7 +235,7 @@ MsrHandle::MsrHandle(uint32 cpu) : fd(-1), cpu_id(cpu)
snprintf(path, 200, "/dev/msr%d", cpu);
handle = ::open(path, O_RDWR);
}
- delete[] path;
+ deleteAndNullifyArray(path);
if (handle < 0)
{
std::cerr << "PCM Error: can't open MSR handle for core " << cpu << " (" << strerror(errno) << ")\n";
diff --git a/src/msrtest.cpp b/src/msrtest.cpp
index a5ebf1d4..e2e08aee 100644
--- a/src/msrtest.cpp
+++ b/src/msrtest.cpp
@@ -73,7 +73,7 @@ int main()
assert(res >= 0);
}
for (i = 0; i < NUM_CORES; ++i)
- delete cpu_msr[i];
+ deleteAndNullify(cpu_msr[i]);
for (i = 0; i < NUM_CORES; ++i)
std::cout << "Core " << i <<
"\t Instructions: " << (counters_after[i][0] - counters_before[i][0]) <<
diff --git a/src/mutex.h b/src/mutex.h
index a64a1f63..3b4e717d 100644
--- a/src/mutex.h
+++ b/src/mutex.h
@@ -57,6 +57,9 @@ namespace pcm
class Scope {
Mutex & m;
+ Scope() = delete;
+ Scope(const Scope &) = delete;
+ Scope & operator = (const Scope &) = delete;
public:
Scope(Mutex & m_) : m(m_)
{
diff --git a/src/pcm-accel-common.cpp b/src/pcm-accel-common.cpp
index e1f27918..c702e93c 100644
--- a/src/pcm-accel-common.cpp
+++ b/src/pcm-accel-common.cpp
@@ -346,7 +346,7 @@ void readAccelCounters(SystemCounterState& sycs_)
break;
}
- delete[] currState;
+ deleteAndNullifyArray(currState);
}
diff --git a/src/pcm-accel.cpp b/src/pcm-accel.cpp
index 8c8d79a9..47af3003 100644
--- a/src/pcm-accel.cpp
+++ b/src/pcm-accel.cpp
@@ -291,8 +291,8 @@ void collect_data(PCM *m, const double delay, const ACCEL_IP accel, std::vector<
break;
}
- delete[] before;
- delete[] after;
+ deleteAndNullifyArray(before);
+ deleteAndNullifyArray(after);
}
diff --git a/src/pcm-core.cpp b/src/pcm-core.cpp
index 6ec183fd..9a1fbbf8 100644
--- a/src/pcm-core.cpp
+++ b/src/pcm-core.cpp
@@ -48,12 +48,14 @@ struct CoreEvent
char * description;
} events[PERF_MAX_CUSTOM_COUNTERS];
+#ifdef PCM_SHARED_LIBRARY
+
extern "C" {
- SystemCounterState globalSysBeforeState, globalSysAfterState;
- std::vector globalBeforeState, globalAfterState;
- std::vector globalDummySocketStates;
- EventSelectRegister globalRegs[PERF_MAX_COUNTERS];
- PCM::ExtendedCustomCoreEventDescription globalConf;
+ static std::shared_ptr globalSysBeforeState, globalSysAfterState;
+ static std::shared_ptr > globalBeforeState, globalAfterState;
+ static std::shared_ptr > globalDummySocketStates;
+ static EventSelectRegister globalRegs[PERF_MAX_COUNTERS];
+ static PCM::ExtendedCustomCoreEventDescription globalConf;
int pcm_c_build_core_event(uint8_t idx, const char * argv)
{
@@ -68,6 +70,11 @@ extern "C" {
int pcm_c_init()
{
PCM * m = PCM::getInstance();
+ globalSysBeforeState = std::make_shared();
+ globalSysAfterState = std::make_shared();
+ globalBeforeState = std::make_shared >();
+ globalAfterState = std::make_shared >();
+ globalDummySocketStates = std::make_shared >();
globalConf.fixedCfg = NULL; // default
globalConf.nGPCounters = m->getMaxCustomCoreEvents();
globalConf.gpCounterCfg = globalRegs;
@@ -85,31 +92,33 @@ extern "C" {
void pcm_c_start()
{
PCM * m = PCM::getInstance();
- m->getAllCounterStates(globalSysBeforeState, globalDummySocketStates, globalBeforeState);
+ m->getAllCounterStates(*globalSysBeforeState.get(), *globalDummySocketStates.get(), *globalBeforeState.get());
}
void pcm_c_stop()
{
PCM * m = PCM::getInstance();
- m->getAllCounterStates(globalSysAfterState, globalDummySocketStates, globalAfterState);
+ m->getAllCounterStates(*globalSysAfterState.get(), *globalDummySocketStates.get(), *globalAfterState.get());
}
uint64_t pcm_c_get_cycles(uint32_t core_id)
{
- return getCycles(globalBeforeState[core_id], globalAfterState[core_id]);
+ return getCycles((*globalBeforeState.get())[core_id], (*globalAfterState.get())[core_id]);
}
uint64_t pcm_c_get_instr(uint32_t core_id)
{
- return getInstructionsRetired(globalBeforeState[core_id], globalAfterState[core_id]);
+ return getInstructionsRetired((*globalBeforeState.get())[core_id], (*globalAfterState.get())[core_id]);
}
uint64_t pcm_c_get_core_event(uint32_t core_id, uint32_t event_id)
{
- return getNumberOfCustomEvents(event_id, globalBeforeState[core_id], globalAfterState[core_id]);
+ return getNumberOfCustomEvents(event_id, (*globalBeforeState.get())[core_id], (*globalAfterState.get())[core_id]);
}
}
+#endif // PCM_SHARED_LIBRARY
+
void print_usage(const string & progname)
{
cout << "\n Usage: \n " << progname
diff --git a/src/pcm-iio.cpp b/src/pcm-iio.cpp
index bfc8f570..ee97015c 100644
--- a/src/pcm-iio.cpp
+++ b/src/pcm-iio.cpp
@@ -1826,8 +1826,8 @@ result_content get_IIO_Samples(PCM *m, const std::vectorsocket_id][iio_unit_id][std::pair(ctr.h_id,ctr.v_id)] = trans_result;
}
}
- delete[] before;
- delete[] after;
+ deleteAndNullifyArray(before);
+ deleteAndNullifyArray(after);
return results;
}
diff --git a/src/pcm-latency.cpp b/src/pcm-latency.cpp
index 36c86e2e..144d6ed8 100644
--- a/src/pcm-latency.cpp
+++ b/src/pcm-latency.cpp
@@ -92,9 +92,9 @@ ServerUncoreCounterState * BeforeState;
ServerUncoreCounterState * AfterState;
-SystemCounterState SysBeforeState, SysAfterState;
-std::vector BeforeState_core, AfterState_core;
-std::vector DummySocketStates;
+std::shared_ptr SysBeforeState, SysAfterState;
+std::shared_ptr > BeforeState_core, AfterState_core;
+std::shared_ptr > DummySocketStates;
void collect_beforestate_uncore(PCM *m)
{
@@ -150,12 +150,12 @@ void store_latency_uncore(PCM *m, bool ddr, int delay_ms)
void collect_beforestate_core(PCM *m)
{
- m->getAllCounterStates(SysBeforeState, DummySocketStates, BeforeState_core);
+ m->getAllCounterStates(*SysBeforeState.get(), *DummySocketStates.get(), *BeforeState_core.get());
}
void collect_afterstate_core(PCM *m)
{
- m->getAllCounterStates(SysAfterState, DummySocketStates, AfterState_core);
+ m->getAllCounterStates(*SysAfterState.get(), *DummySocketStates.get(), *AfterState_core.get());
}
void store_latency_core(PCM *m)
@@ -173,12 +173,12 @@ void store_latency_core(PCM *m)
}
for (unsigned int i=0; igetNumCores(); i++)
{
- const double frequency = (((double)getCycles(BeforeState_core[i], AfterState_core[i]) /
- (double)getRefCycles(BeforeState_core[i], AfterState_core[i])) * (double)m->getNominalFrequency()) / 1000000000;
+ const double frequency = (((double)getCycles(BeforeState_core->operator[](i), AfterState_core->operator[](i)) /
+ (double)getRefCycles(BeforeState_core->operator[](i), AfterState_core->operator[](i))) * (double)m->getNominalFrequency()) / 1000000000;
for(int j=0; j<2; j++)// 2 events
{
core_event[j].core[i].core_id = i;
- core_event[j].core[i].latency = (double)getNumberOfCustomEvents(j, BeforeState_core[i], AfterState_core[i]);
+ core_event[j].core[i].latency = (double)getNumberOfCustomEvents(j, BeforeState_core->operator[](i), AfterState_core->operator[](i));
}
// L1 latency
//Adding 5 clocks for L1 Miss
@@ -443,8 +443,8 @@ void collect_data(PCM *m, bool enable_pmm, bool enable_verbose, int delay_ms, Ma
return true;
});
- delete[] BeforeState;
- delete[] AfterState;
+ deleteAndNullifyArray(BeforeState);
+ deleteAndNullifyArray(AfterState);
}
void print_usage()
@@ -512,6 +512,12 @@ int mainThrows(int argc, char * argv[])
PCM::ExtendedCustomCoreEventDescription conf;
PCM * m = PCM::getInstance();
+ SysBeforeState = std::make_shared();
+ SysAfterState = std::make_shared();
+ BeforeState_core = std::make_shared >();
+ AfterState_core = std::make_shared >();
+ DummySocketStates = std::make_shared >();
+
build_registers(m, conf, enable_pmm, enable_verbose);
collect_data(m, enable_pmm, enable_verbose, delay_ms, mainLoop);
diff --git a/src/pcm-sensor-server.cpp b/src/pcm-sensor-server.cpp
index 57d7e42f..9c68c3d8 100644
--- a/src/pcm-sensor-server.cpp
+++ b/src/pcm-sensor-server.cpp
@@ -1170,8 +1170,10 @@ class Server {
SignalHandler* shi = SignalHandler::getInstance();
shi->setSocket( serverSocket_ );
shi->ignoreSignal( SIGPIPE ); // Sorry Dennis Ritchie, we do not care about this, we always check return codes
+ #ifndef UNIT_TEST // libFuzzer installs own signal handlers
shi->installHandler( SignalHandler::handleSignal, SIGTERM );
shi->installHandler( SignalHandler::handleSignal, SIGINT );
+ #endif
}
Server( Server const & ) = delete;
Server & operator = ( Server const & ) = delete;
@@ -2369,8 +2371,9 @@ std::string& compressLWSAndRemoveCR( std::string& line ) {
}
// Remove trailing '\r'
- if ( line[line.size()-1] == '\r' )
+ if (!line.empty() && line.back() == '\r') {
line.pop_back();
+ }
return line;
}
@@ -2710,7 +2713,7 @@ class HTTPServer : public Server {
virtual ~HTTPServer() {
pcf_->stop();
std::this_thread::sleep_for( std::chrono::seconds(1) );
- delete pcf_;
+ deleteAndNullify(pcf_);
}
public:
@@ -2845,7 +2848,7 @@ void HTTPServer::run() {
connection = new HTTPConnection( this, clientSocketFD, clientAddress, callbackList_ );
} catch ( std::exception& e ) {
DBG( 3, "Exception caught while creating a HTTPConnection: " );
- if (connection) delete connection;
+ if (connection) deleteAndNullify(connection);
::close( clientSocketFD );
continue;
}
@@ -2883,9 +2886,13 @@ class HTTPSServer : public HTTPServer {
// SSL too old on development machine, not available yet FIXME
//OPENSSL_config(nullptr);
- sslCTX_ = SSL_CTX_new( SSLv23_method() );
+ // We require 1.1.1 now so TLS_method is available but still
+ // make sure minimum protocol is TSL1_VERSION below
+ sslCTX_ = SSL_CTX_new( TLS_method() );
if ( nullptr == sslCTX_ )
throw std::runtime_error( "Cannot create an SSL context" );
+ if( SSL_CTX_set_min_proto_version( sslCTX_, TLS1_VERSION ) != 1 )
+ throw std::runtime_error( "Cannot set minimum protocol to TSL1_VERSION" );
if ( SSL_CTX_use_certificate_file( sslCTX_, certificateFile_.c_str(), SSL_FILETYPE_PEM ) <= 0 )
throw std::runtime_error( "Cannot use certificate file" );
if ( SSL_CTX_use_PrivateKey_file( sslCTX_, privateKeyFile_.c_str(), SSL_FILETYPE_PEM ) <= 0 )
@@ -2954,6 +2961,7 @@ void HTTPSServer::run() {
}
} catch( std::exception& e ) {
DBG( 3, "SSL Accept: error accepting incoming connection, closing the FD and continuing: ", e.what() );
+ SSL_free( ssl ); // Free the SSL structure to prevent memory leaks
::close( clientSocketFD );
continue;
}
@@ -2964,6 +2972,7 @@ void HTTPSServer::run() {
char const * resbuf = ::inet_ntop( AF_INET, &(clientAddress.sin_addr), ipbuf, INET_ADDRSTRLEN );
if ( nullptr == resbuf ) {
std::cerr << strerror( errno ) << "\n";
+ SSL_free( ssl ); // Free the SSL structure to prevent memory leaks
::close( clientSocketFD );
continue;
}
diff --git a/src/realtime.cpp b/src/realtime.cpp
index 9285695a..e679253a 100644
--- a/src/realtime.cpp
+++ b/src/realtime.cpp
@@ -164,7 +164,7 @@ int main(int argc, char * argv[])
if (m->program() != PCM::Success) {
cout << "Program was not successful...\n";
- delete m;
+ deleteAndNullify(m);
return -1;
}
diff --git a/src/threadpool.cpp b/src/threadpool.cpp
index 356c0ed1..cf565bce 100644
--- a/src/threadpool.cpp
+++ b/src/threadpool.cpp
@@ -2,6 +2,7 @@
// Copyright (c) 2020-2022, Intel Corporation
#include "threadpool.h"
+#include "utils.h"
namespace pcm {
@@ -10,7 +11,7 @@ void ThreadPool::execute( ThreadPool* tp ) {
Work* w = tp->retrieveWork();
if ( w == nullptr ) break;
w->execute();
- delete w;
+ deleteAndNullify(w);
}
}
diff --git a/src/topology.h b/src/topology.h
index 6ba8db9e..526455ad 100644
--- a/src/topology.h
+++ b/src/topology.h
@@ -120,7 +120,7 @@ class Core : public SystemObject
virtual ~Core() {
pcm_ = nullptr;
for ( auto& thread : threads_ )
- delete thread;
+ deleteAndNullify(thread);
}
virtual void accept( Visitor& v ) override {
@@ -272,9 +272,9 @@ class Socket : public SystemObject {
virtual ~Socket() {
pcm_ = nullptr;
for ( auto& core : cores_ )
- delete core;
+ deleteAndNullify(core);
refCore_ = nullptr; // cores_ is owner so it is already deleted by here
- delete uncore_;
+ deleteAndNullify(uncore_);
}
virtual void accept( Visitor& v ) override {
@@ -352,9 +352,9 @@ class SystemRoot : public SystemObject {
virtual ~SystemRoot() {
pcm_ = nullptr;
for ( auto& socket : sockets_ )
- delete socket;
+ deleteAndNullify(socket);
for ( auto& thread : offlinedThreadsAtStart_ )
- delete thread;
+ deleteAndNullify(thread);
}
virtual void accept( Visitor& v ) override {
diff --git a/src/utils.cpp b/src/utils.cpp
index cf25efc6..1723ab23 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -348,8 +348,7 @@ void sigSEGV_handler(int signum)
{
std::cerr << backtrace_strings[i] << "\n";
}
- free(backtrace_strings);
- backtrace_strings = NULL;
+ freeAndNullify(backtrace_strings);
}
sigINT_handler(signum);
@@ -453,15 +452,16 @@ void set_signal_handlers(void)
std::cerr << "\nPCM ERROR: _dupenv_s failed.\n";
_exit(EXIT_FAILURE);
}
- free(envPath);
if (envPath)
{
std::cerr << "\nPCM ERROR: Detected cygwin/mingw environment which does not allow to setup PMU clean-up handlers on Ctrl-C and other termination signals.\n";
std::cerr << "See https://www.mail-archive.com/cygwin@cygwin.com/msg74817.html\n";
std::cerr << "As a workaround please run pcm directly from a native windows shell (e.g. cmd).\n";
std::cerr << "Exiting...\n\n";
+ freeAndNullify(envPath);
_exit(EXIT_FAILURE);
}
+ freeAndNullify(envPath);
std::cerr << "DEBUG: Setting Ctrl+C done.\n";
#else
@@ -826,7 +826,7 @@ std::string safe_getenv(const char* env)
if (_dupenv_s(&buffer, NULL, env) == 0 && buffer != nullptr)
{
result = buffer;
- free(buffer);
+ freeAndNullify(buffer);
}
return result;
}
diff --git a/src/utils.h b/src/utils.h
index f4775d90..23e0091d 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -41,6 +41,37 @@
#include
#endif
namespace pcm {
+
+ template
+ inline void deleteAndNullify(T & p)
+ {
+ if (p)
+ {
+ delete p;
+ p = nullptr;
+ }
+ }
+
+ template
+ inline void deleteAndNullifyArray(T & p)
+ {
+ if (p)
+ {
+ delete [] p;
+ p = nullptr;
+ }
+ }
+
+ template
+ inline void freeAndNullify(T & p)
+ {
+ if (p)
+ {
+ free(p);
+ p = nullptr;
+ }
+ }
+
std::string safe_getenv(const char* env);
#ifdef _MSC_VER
typedef std::wstring StringType;
@@ -288,7 +319,7 @@ class s_expect : public std::string
{
istr.setstate(std::ios_base::failbit);
}
- delete [] buffer;
+ deleteAndNullifyArray(buffer);
}
};
@@ -675,7 +706,7 @@ class TemporalThreadAffinity // speedup trick for Linux, FreeBSD, DragonFlyBSD,
bool supported() const { return true; }
#elif defined(__linux__)
- cpu_set_t* old_affinity;
+ cpu_set_t* old_affinity = nullptr;
static constexpr auto maxCPUs = 8192;
const size_t set_size;
bool restore;
@@ -691,7 +722,9 @@ class TemporalThreadAffinity // speedup trick for Linux, FreeBSD, DragonFlyBSD,
if (res != 0)
{
std::cerr << "ERROR: pthread_getaffinity_np for core " << core_id << " failed with code " << res << "\n";
- throw std::exception();
+ CPU_FREE(old_affinity);
+ old_affinity = nullptr;
+ throw std::runtime_error("pthread_getaffinity_np failed");
}
cpu_set_t* new_affinity = CPU_ALLOC(maxCPUs);
assert(new_affinity);
@@ -708,13 +741,16 @@ class TemporalThreadAffinity // speedup trick for Linux, FreeBSD, DragonFlyBSD,
if (res != 0 && checkStatus)
{
std::cerr << "ERROR: pthread_setaffinity_np for core " << core_id << " failed with code " << res << "\n";
- throw std::exception();
+ CPU_FREE(old_affinity);
+ old_affinity = nullptr;
+ throw std::runtime_error("pthread_setaffinity_np failed");
}
}
~TemporalThreadAffinity()
{
if (restore) pthread_setaffinity_np(pthread_self(), set_size, old_affinity);
CPU_FREE(old_affinity);
+ old_affinity = nullptr;
}
bool supported() const { return true; }
#elif defined(_MSC_VER)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index a55a15c5..eb78bb67 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -20,11 +20,11 @@ endif(UNIX)
if(FUZZ)
add_executable(urltest-fuzz urltest-fuzz.cpp)
- # TODO add_executable(pcm-sensor-server-fuzz pcm-sensor-server-fuzz.cpp)
+ add_executable(pcm-sensor-server-fuzz pcm-sensor-server-fuzz.cpp)
add_executable(pcm-fuzz pcm-fuzz.cpp)
add_executable(pcm-memory-fuzz pcm-memory-fuzz.cpp)
target_link_libraries(urltest-fuzz Threads::Threads PCM_STATIC)
- # TODO: target_link_libraries(pcm-sensor-server-fuzz Threads::Threads PCM_STATIC)
+ target_link_libraries(pcm-sensor-server-fuzz Threads::Threads PCM_STATIC)
target_link_libraries(pcm-fuzz Threads::Threads PCM_STATIC)
target_link_libraries(pcm-memory-fuzz Threads::Threads PCM_STATIC)
endif()
diff --git a/tests/daemon_alignment_test.cpp b/tests/daemon_alignment_test.cpp
index d4c61be2..acad1f8c 100644
--- a/tests/daemon_alignment_test.cpp
+++ b/tests/daemon_alignment_test.cpp
@@ -4,6 +4,7 @@
#include
#include "../src/daemon/common.h"
+#include "../src/utils.h"
#define ALIGNMENT 64
@@ -83,7 +84,7 @@ int main()
}
}
- free(pcmState);
+ pcm::freeAndNullify(pcmState);
printf("\n------ All passed ------\n\n");
diff --git a/tests/fuzz.sh b/tests/fuzz.sh
index 2a94779d..3172d1a1 100644
--- a/tests/fuzz.sh
+++ b/tests/fuzz.sh
@@ -1,14 +1,81 @@
export PCM_ENFORCE_MBM="1"
+factor=1
+
+if [ "$#" -eq 1 ]; then
+ factor=$1
+fi
+
+echo "Running fuzz tests with running time multiplier $factor"
+
CC=`which clang` CXX=`which clang++` cmake .. -DCMAKE_BUILD_TYPE=Debug -DFUZZ=1 && mkdir -p corpus &&
-make urltest-fuzz pcm-fuzz pcm-memory-fuzz -j &&
-LLVM_PROFILE_FILE="urltest.profraw" bin/tests/urltest-fuzz -max_total_time=1000 corpus > /dev/null &&
-LLVM_PROFILE_FILE="pcm.profraw" bin/tests/pcm-fuzz -max_total_time=500 corpus > /dev/null &&
-LLVM_PROFILE_FILE="pcm.no_perf.profraw" PCM_NO_PERF=1 bin/tests/pcm-fuzz -max_total_time=500 corpus > /dev/null &&
-LLVM_PROFILE_FILE="pcm.uncore_perf.profraw" PCM_USE_UNCORE_PERF=1 bin/tests/pcm-fuzz -max_total_time=500 corpus > /dev/null &&
-LLVM_PROFILE_FILE="pcm.nmi_watchdog.profraw" PCM_KEEP_NMI_WATCHDOG=1 bin/tests/pcm-fuzz -max_total_time=100 corpus > /dev/null &&
-LLVM_PROFILE_FILE="pcm-memory.profraw" bin/tests/pcm-memory-fuzz -max_total_time=1000 corpus > /dev/null &&
-llvm-profdata merge -sparse urltest.profraw pcm.profraw pcm.no_perf.profraw pcm.uncore_perf.profraw pcm.nmi_watchdog.profraw pcm-memory.profraw -o all.profdata &&
-llvm-cov report --summary-only -object ./bin/tests/pcm-fuzz -object ./bin/tests/urltest-fuzz -object ./bin/tests/pcm-memory-fuzz -instr-profile=all.profdata | tee report.txt
+make urltest-fuzz \
+ pcm-fuzz \
+ pcm-memory-fuzz \
+ pcm-sensor-server-fuzz \
+ -j &&
+rm -rf corpus/* &&
+printf '%b' "GET / HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n\r\n" > corpus/1 &&
+printf '%b' "GET /metrics HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n\r\n" > corpus/2 &&
+printf '%b' "GET /persecond HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n\r\n" > corpus/3 &&
+printf '%b' "GET /persecond HTTP/1.1\r\nHost: localhost\r\nAccept: application/json\r\n\r\n" > corpus/3.1 &&
+printf '%b' "GET /persecond HTTP/1.1\r\nHost: localhost\r\nAccept: text/plain; version=0.0.4\r\n\r\n" > corpus/3.2 &&
+printf '%b' "GET /persecond/1 HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n\r\n" > corpus/4 &&
+printf '%b' "GET /persecond/1 HTTP/1.1\r\nHost: localhost\r\nAccept: application/json\r\n\r\n" > corpus/4.1 &&
+printf '%b' "GET /persecond/1 HTTP/1.1\r\nHost: localhost\r\nAccept: text/plain; version=0.0.4\r\n\r\n" > corpus/4.2 &&
+printf '%b' "GET /persecond/10 HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n\r\n" > corpus/5 &&
+printf '%b' "GET /persecond/10 HTTP/1.1\r\nHost: localhost\r\nAccept: application/json\r\n\r\n" > corpus/5.1 &&
+printf '%b' "GET /persecond/10 HTTP/1.1\r\nHost: localhost\r\nAccept: text/plain; version=0.0.4\r\n\r\n" > corpus/5.2 &&
+printf '%b' "GET /persecond/100 HTTP/1.1\r\nHost: localhost\r\nAccept: application/json\r\n\r\n" > corpus/6 &&
+printf '%b' "GET /metrics HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n\r\n" > corpus/7 &&
+printf '%b' "GET /dashboard/influxdb HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n\r\n" > corpus/8 &&
+printf '%b' "GET /dashboard/prometheus HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n\r\n" > corpus/9 &&
+printf '%b' "GET /dashboard/prometheus/default HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n\r\n" > corpus/10 &&
+printf '%b' "GET /dashboard HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n\r\n" > corpus/11 &&
+printf '%b' "GET /favicon.ico HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n\r\n" > corpus/12 &&
+LLVM_PROFILE_FILE="pcm-sensor-server.profraw" bin/tests/pcm-sensor-server-fuzz -detect_leaks=0 -rss_limit_mb=10000 -max_total_time=$((10 * $factor)) corpus > /dev/null &&
+rm -rf corpus/* &&
+printf '%b' "http://otto:test@www.intel.com/~otto/file1.txt" > corpus/1 &&
+printf '%b' "file://localhost/c/mnt/cd/file2.txt" > corpus/2 &&
+printf '%b' "ftp://otto%40yahoo.com:abcd%3B1234@www.intel.com:30/xyz.php?a=1&t=3" > corpus/3 &&
+printf '%b' "gopher://otto@hostname1.intel.com:8080/file3.zyx" > corpus/4 &&
+printf '%b' "www.intel.com" > corpus/5 &&
+printf '%b' "http://www.blah.org/file.html#firstmark" > corpus/6 &&
+printf '%b' "http://www.blah.org/file.html#firstmark%21%23" > corpus/7 &&
+printf '%b' "localhost" > corpus/8 &&
+printf '%b' "https://www.intel.com" > corpus/9 &&
+printf '%b' "://google.com/" > corpus/10 &&
+printf '%b' "https://intc.com/request?" > corpus/11 &&
+printf '%b' "htt:ps//www.intel.com" > corpus/12 &&
+printf '%b' "http://www.intel.com:66666/" > corpus/13 &&
+printf '%b' "http:///" > corpus/14 &&
+printf '%b' "http://[1234::1234::1234/" > corpus/15 &&
+printf '%b' "http://@www.intel.com" > corpus/16 &&
+printf '%b' "http://otto@:www.intel.com" > corpus/17 &&
+printf '%b' "https://:@www.intel.com" > corpus/18 &&
+printf '%b' "https://user:@www.intel.com" > corpus/19 &&
+printf '%b' "http:www.intel.com/" > corpus/20 &&
+printf '%b' "http://ww\x00\x00\x00rstmark\x0a" > corpus/21 &&
+LLVM_PROFILE_FILE="urltest.profraw" bin/tests/urltest-fuzz -max_total_time=$((10 * $factor)) corpus > /dev/null &&
+rm -rf corpus/* && LLVM_PROFILE_FILE="pcm.profraw" bin/tests/pcm-fuzz -max_total_time=$((5 * $factor)) corpus > /dev/null &&
+rm -rf corpus/* && LLVM_PROFILE_FILE="pcm.no_perf.profraw" PCM_NO_PERF=1 bin/tests/pcm-fuzz -max_total_time=$((5 * $factor)) corpus > /dev/null &&
+rm -rf corpus/* && LLVM_PROFILE_FILE="pcm.uncore_perf.profraw" PCM_USE_UNCORE_PERF=1 bin/tests/pcm-fuzz -max_total_time=$((5 * $factor)) corpus > /dev/null &&
+rm -rf corpus/* && LLVM_PROFILE_FILE="pcm.nmi_watchdog.profraw" PCM_KEEP_NMI_WATCHDOG=1 bin/tests/pcm-fuzz -max_total_time=$((1 * $factor)) corpus > /dev/null &&
+rm -rf corpus/* && LLVM_PROFILE_FILE="pcm-memory.profraw" bin/tests/pcm-memory-fuzz -max_total_time=$((10 * $factor)) corpus > /dev/null &&
+llvm-profdata merge -sparse \
+ urltest.profraw \
+ pcm.profraw \
+ pcm.no_perf.profraw \
+ pcm.uncore_perf.profraw \
+ pcm.nmi_watchdog.profraw \
+ pcm-memory.profraw \
+ pcm-sensor-server.profraw \
+ -o all.profdata &&
+llvm-cov report --summary-only \
+ -object ./bin/tests/pcm-fuzz \
+ -object ./bin/tests/urltest-fuzz \
+ -object ./bin/tests/pcm-memory-fuzz \
+ -object ./bin/tests/pcm-sensor-server-fuzz \
+ -instr-profile=all.profdata | tee report.txt
diff --git a/tests/pcm-memory-fuzz.cpp b/tests/pcm-memory-fuzz.cpp
index f91841c1..66ddb6f9 100644
--- a/tests/pcm-memory-fuzz.cpp
+++ b/tests/pcm-memory-fuzz.cpp
@@ -25,8 +25,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
bool print_update = data_int[pos++] % 2;
uint32 no_columns = DEFAULT_DISPLAY_COLUMNS; // Default number of columns is 2
int delay = data_int[pos++] % 4;
- int rankA = data_int[pos++];
- int rankB = data_int[pos++];
+ int rankA = data_int[pos++] % 11;
+ int rankB = data_int[pos++] % 11;
bool use_rank = data_int[pos++] % 2;
if (!use_rank)
{
@@ -90,6 +90,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
cerr << "Rank level output requires channel output\n";
return 0;
}
+ std::cerr << "programServerUncoreMemoryMetrics parameters:" << metrics << ";" << rankA << ";" << rankB << "\n";
PCM::ErrorCode status = m->programServerUncoreMemoryMetrics(metrics, rankA, rankB);
m->checkError(status);
diff --git a/tests/pcm-sensor-server-fuzz.cpp b/tests/pcm-sensor-server-fuzz.cpp
new file mode 100644
index 00000000..141a3887
--- /dev/null
+++ b/tests/pcm-sensor-server-fuzz.cpp
@@ -0,0 +1,179 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define UNIT_TEST 1
+
+#include "../src/pcm-sensor-server.cpp"
+
+#undef UNIT_TEST
+
+int port = 0;
+
+bool waitForPort(int port, int timeoutSeconds) {
+ int sockfd;
+ struct sockaddr_in address;
+ bool isBound = false;
+ time_t startTime = time(nullptr);
+
+ // Create a socket
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (sockfd < 0) {
+ std::cerr << "Error creating socket" << std::endl;
+ return false;
+ }
+
+ // Set up the address structure
+ memset(&address, 0, sizeof(address));
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = inet_addr("127.0.0.1");
+ address.sin_port = htons(port);
+
+ // Loop until the port is bound or the timeout is reached
+ while (!isBound && (time(nullptr) - startTime) < timeoutSeconds) {
+ // Attempt to connect to the port
+ if (connect(sockfd, (struct sockaddr *)&address, sizeof(address)) < 0) {
+ // Connection failed, wait a bit before retrying
+ sleep(1);
+ } else {
+ // Connection succeeded, the port is bound
+ isBound = true;
+ }
+ }
+
+ // Clean up the socket
+ close(sockfd);
+ return isBound;
+}
+
+HTTPServer * httpServer;
+std::thread * serverThread;
+
+void cleanup()
+{
+ std::cerr << "Stopping HTTPServer\n";
+ httpServer->stop();
+ std::cerr << "Cleaning up PMU:\n";
+ PCM::getInstance()->cleanup();
+}
+
+bool init()
+{
+ port = (rand() % 100) + 10000; // to be able to restart the fuzzer quickly without waiting for the port to be released
+ serverThread = new std::thread([]() {
+ PCM::ErrorCode status;
+ PCM * pcmInstance = PCM::getInstance();
+ assert(pcmInstance);
+ pcmInstance->resetPMU();
+ status = pcmInstance->program();
+ if (status != PCM::Success) {
+ std::cerr << "Error in program() function" << std::endl;
+ exit(1);
+ }
+ debug::dyn_debug_level(0);
+ std::cerr << "Starting plain HTTP server on http://localhost:" << port << "/\n";
+ httpServer = new HTTPServer( "", port );
+ // HEAD is GET without body, we will remove the body in execute()
+ httpServer->registerCallback( HTTPRequestMethod::GET, my_get_callback );
+ httpServer->registerCallback( HTTPRequestMethod::HEAD, my_get_callback );
+ httpServer->run();
+ });
+ int timeout = 60; // Timeout in seconds
+ if (waitForPort(port, timeout)) {
+ std::cout << "Port " << port << " is now bound." << std::endl;
+ } else {
+ std::cout << "Port " << port << " is not bound after " << timeout << " seconds." << std::endl;
+ exit(1);
+ }
+ atexit(cleanup);
+ return true;
+}
+
+
+std::vector buffer(1024*1024*16);
+
+std::string make_request(const std::string& request) {
+ std::string server = "127.0.0.1";
+ // Resolve the host
+ struct hostent* host = gethostbyname(server.c_str());
+ if (!host) {
+ std::cerr << "Failed to resolve host. Error: " << strerror(errno) << std::endl;
+ throw std::runtime_error("Failed to resolve host: " + server);
+ }
+
+ // Create socket
+ int sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0) {
+ std::cerr << "Failed to create socket. Error: " << strerror(errno) << std::endl;
+ throw std::runtime_error("Failed to create socket");
+ }
+
+ // Create server address structure
+ struct sockaddr_in server_addr;
+ std::memset(&server_addr, 0, sizeof(server_addr));
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(port);
+ std::memcpy(&server_addr.sin_addr, host->h_addr, host->h_length);
+
+ // Connect to server
+ if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
+ std::cerr << "Failed to connect to server. Error: " << strerror(errno) << std::endl;
+ close(sock);
+ throw std::runtime_error("Failed to connect to server");
+ }
+
+ // Form the request
+ std::cout << "Sending request: " << request << "\n=====\n";
+
+ // Send the request
+ if (send(sock, request.c_str(), request.length(), 0) < 0) {
+ std::cerr << "Failed to send request. Error: " << strerror(errno) << std::endl;
+ close(sock);
+ return "Failed to send request, no response"; // not sure why it happens relatively often
+ // throw std::runtime_error("Failed to send request");
+ }
+
+ // Receive the response
+ std::string response;
+ ssize_t bytes_received;
+ bytes_received = recv(sock, &(buffer[0]), buffer.size(), 0);
+ if (bytes_received > 0)
+ {
+ response.append(&(buffer[0]), bytes_received);
+ }
+
+ if (bytes_received < 0) {
+ std::cerr << "Failed to receive response. Error: " << strerror(errno) << std::endl;
+ close(sock);
+ // throw std::runtime_error("Failed to receive response");
+ return "Failed to receive response"; // expected to happen sometimes
+ }
+
+ // Close the socket
+ close(sock);
+
+ return response;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ static bool initialized = false;
+ if (!initialized) {
+ initialized = init();
+ }
+ try {
+ std::string request = std::string((const char*)data, size);
+ std::string response = make_request(request);
+ std::cout << response << std::endl;
+ } catch (const std::exception& e) {
+ std::cerr << "LLVMFuzzerTestOneInput Exception: \"" << e.what() << "\"" << std::endl;
+ exit(1);
+ }
+ return 0;
+}
diff --git a/tests/test.sh b/tests/test.sh
index ba1c8935..5496fe8a 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -132,7 +132,8 @@ if [ "$?" -ne "0" ]; then
fi
echo Testing c_example
-./examples/c_example
+# see https://github.com/google/sanitizers/issues/934
+LD_PRELOAD="$(realpath "$(gcc -print-file-name=libasan.so)") $(realpath "$(gcc -print-file-name=libstdc++.so)")" LD_LIBRARY_PATH=../lib/ ./examples/c_example
if [ "$?" -ne "0" ]; then
echo "Error in c_example"
exit 1
@@ -159,6 +160,9 @@ if [ "$?" -ne "0" ]; then
exit 1
fi
+echo "/sys/fs/cgroup/cpuset/cpuset.cpus:"
+cat /sys/fs/cgroup/cpuset/cpuset.cpus
+
echo Testing pcm-pcie
./pcm-pcie -- sleep 1
if [ "$?" -ne "0" ]; then