From c77a3b5adc0ace19da2c29788f756c9e9ca3251d Mon Sep 17 00:00:00 2001 From: Hitesh Ahuja <108540135+hahuja2@users.noreply.github.com> Date: Thu, 15 Feb 2024 15:25:27 -0800 Subject: [PATCH] fix(agent): ensure package version retrieval does not error out (#833) This PR does the following: - For Drupal the `Drupal::VERSION` class constant is retrieved using zend calls from C and does not require using `zend_eval_string`. The retrieval is robust against the this constant not being defined. - For Wordpress, the presence of the `wp_version` value in `$GLOBAL` is verified before trying to retrieve the value. --------- Co-authored-by: Michael Fulbright Co-authored-by: Michal Nowacki Co-authored-by: Michael Fulbright <89205663+mfulb@users.noreply.github.com> --- agent/fw_drupal8.c | 40 +++++++++++++++++++++++++++++----------- agent/fw_wordpress.c | 25 +++++++++++++++++++------ 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/agent/fw_drupal8.c b/agent/fw_drupal8.c index 52f550868..5456cf390 100644 --- a/agent/fw_drupal8.c +++ b/agent/fw_drupal8.c @@ -533,20 +533,38 @@ NR_PHP_WRAPPER(nr_drupal8_name_the_wt_via_symfony) { } NR_PHP_WRAPPER_END +/* + * Drupal stores the version of the framework in the class constant + * Drupal::VERSION. This code first verifies the 'Drupal' class exists (note + * having to pass the lower case name of the class). If present then an attempt + * is made to retrieve the 'VERSION' class constant. Both of these checks rely + * on existing "nr_" routines that have been designed to be robust and will not + * cause an issue in user's application if either check were to fail. + */ void nr_drupal_version() { - char* string = "Drupal::VERSION;"; - zval retval; - int result - = zend_eval_string(string, &retval, "Retrieve Drupal Version"); - + zval* zval_version = NULL; + zend_class_entry* class_entry = NULL; + + class_entry = nr_php_find_class("drupal"); + if (NULL == class_entry) { + nrl_verbosedebug(NRL_INSTRUMENT, "%s: 'Drupal' class not found", __func__); + return; + } + + zval_version = nr_php_get_class_constant(class_entry, "VERSION"); + if (NULL == zval_version) { + nrl_verbosedebug(NRL_INSTRUMENT, "%s: Drupal does not have VERSION", + __func__); + return; + } + // Add php package to transaction - if (result == SUCCESS) { - if (Z_TYPE(retval) == IS_STRING) { - char* version = Z_STRVAL(retval); - nr_txn_add_php_package(NRPRG(txn), "drupal/core", version); - } - zval_dtor(&retval); + if (nr_php_is_zval_valid_string(zval_version)) { + char* version = Z_STRVAL_P(zval_version); + nr_txn_add_php_package(NRPRG(txn), "drupal/core", version); } + + nr_php_zval_free(&zval_version); } void nr_drupal8_enable(TSRMLS_D) { diff --git a/agent/fw_wordpress.c b/agent/fw_wordpress.c index 675360a49..32ce1fdc1 100644 --- a/agent/fw_wordpress.c +++ b/agent/fw_wordpress.c @@ -658,14 +658,27 @@ NR_PHP_WRAPPER_END #endif /* PHP 7.4+ */ void nr_wordpress_version() { - char* string = "$GLOBALS['wp_version'];"; + char* func_string + = "" + "(function() {" + " try {" + " if (array_key_exists('wp_version', $GLOBALS)) {" + " return $GLOBALS['wp_version'];" + " }" + " else {" + " return ' ';" + " }" + " } catch (Exception $e) {" + " return ' ';" + " }" + "})();"; + zval retval; - int result = zend_eval_string(string, &retval, - "Retrieve Wordpress Version"); - + int result + = zend_eval_string(func_string, &retval, "Get Wordpress Version"); // Add php package to transaction - if (result == SUCCESS) { - if (Z_TYPE(retval) == IS_STRING) { + if (SUCCESS == result) { + if (nr_php_is_zval_valid_string(&retval)) { char* version = Z_STRVAL(retval); nr_txn_add_php_package(NRPRG(txn), "wordpress", version); }