agent/native/loader/code/phpdetection.cpp (73 lines of code) (raw):

#include "phpdetection.h" #include <dlfcn.h> namespace elasticapm::loader { std::string_view getMajorMinorVersion(std::string_view version) { auto lastDot = version.find_last_of('.'); if (lastDot == std::string_view::npos) { return version; } return version.substr(0, lastDot); } std::string_view getZendVersionString() { using get_zend_version_t = char *(*)(void); get_zend_version_t get_zend_version = reinterpret_cast<get_zend_version_t>(dlsym(RTLD_DEFAULT, "get_zend_version")); if (!get_zend_version) { return {}; } const char *zendVersion = get_zend_version(); if (!zendVersion) { return {}; } return zendVersion; } std::string_view getZendVersion(std::string_view zendVersion) { using namespace std::string_view_literals; static constexpr std::string_view prefix = "Zend Engine v"sv; if (!zendVersion.starts_with(prefix)) { return {}; } std::string_view version = zendVersion.substr(prefix.length(), zendVersion.find_first_of(',') - prefix.length()); return version; } std::string_view getMajorMinorZendVersion() { auto zendVersion = getZendVersion(getZendVersionString()); if (zendVersion.empty()) { return {}; } return getMajorMinorVersion(zendVersion); } bool isThreadSafe() { void *coreGlobals = dlsym(RTLD_DEFAULT, "core_globals"); return !coreGlobals; } std::tuple<std::string_view, int, bool> getZendModuleApiVersion(std::string_view zendVersion) { using namespace std::string_view_literals; constexpr size_t knownVersionsCount = 17; constexpr std::array<std::tuple<std::string_view, int, bool>, knownVersionsCount> knownPhpVersions {{ {"4.4"sv, 20240924, true}, // PHP 8.4 {"4.3"sv, 20230831, true}, // PHP 8.3 {"4.2"sv, 20220829, true}, // PHP 8.2 {"4.1"sv, 20210902, true}, // PHP 8.1 {"4.0"sv, 20200930, true}, // PHP 8.0 {"3.4"sv, 20190902, true}, // PHP 7.4 {"3.3"sv, 20180731, true}, // PHP 7.3 {"3.2"sv, 20170718, true}, // PHP 7.2 {"3.1"sv, 20160303, false}, // PHP 7.1 {"3.0"sv, 20151012, false}, // PHP 7.0 {"2.6"sv, 20131226, false}, // PHP 5.6 {"2.5"sv, 20121212, false}, // PHP 5.5 {"2.4"sv, 20100525, false}, // PHP 5.4 {"2.3"sv, 20090626, false}, // PHP 5.3 {"2.2"sv, 20060613, false}, // PHP 5.2 {"2.1"sv, 20050922, false}, // PHP 5.1 {"2.0"sv, 20041030, false} // PHP 5.0 }}; auto foundPhpVersion = std::find_if(std::begin(knownPhpVersions), std::end(knownPhpVersions), [zendVersion](std::tuple<std::string_view, int, bool> const &entry) { return std::get<0>(entry) == zendVersion; }); if (foundPhpVersion == std::end(knownPhpVersions)) { return {zendVersion, 0, false}; } return *foundPhpVersion; } }