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