Artificial truth

The more you see, the less you believe.

[archives] [latest] | [homepage] | [atom/rss/twitter]

Debugging an issue between Snuffleupagus and Composer
Thu 04 February 2021 — download

The 17th of November 2020, someone reported that composer didn't work with Snuffleupagus, even with an empty configuration file:

$ composer
Fatal error: Uncaught TypeError: ini_set() expects parameter 2 to be string, int given in phar:///usr/local/bin/composer/bin/composer:26
Stack trace:
#0 phar:///usr/local/bin/composer/bin/composer(26): ini_set('display_errors', 1)
#1 /usr/local/bin/composer(24): require('phar:///usr/loc...')
#2 {main}
  thrown in phar:///usr/local/bin/composer/bin/composer on line 26

This looked like a strict_mode issue. PHP's documentation about ini_set shows that there is indeed a type-related disparity: ini_set(string, string) : string, called like ini_set(string, int) by composer.

So is must likely be something going on with the strict mode. Fortunately, this feature is pretty contained:

$ git grep -i strict_ -- '*.c'
src/snuffleupagus.c:28:    op->fn_flags |= ZEND_ACC_STRICT_TYPES;
$
static inline void sp_op_array_handler(zend_op_array *op) {
  if (NULL == op->filename) {
    return;
  } else {
    op->fn_flags |= ZEND_ACC_STRICT_TYPES;
  }
}

With sp_op_array_handler being set as op_array_handler_func_t in the zend_extension_entry. It looks like the strict type flag is set no matter what the administrator wrote in their configuration.

The fix is simple: just add a check for the corresponding configuration option:

static inline void sp_op_array_handler(zend_op_array *op) {
    // We need a filename, and strict mode not already enabled on this op
    if (NULL == op->filename || op->fn_flags & ZEND_ACC_STRICT_TYPES) {
        return;
    } else {
        if (true == SNUFFLEUPAGUS_G(config).config_global_strict->enable) {
            op->fn_flags |= ZEND_ACC_STRICT_TYPES;
        }
    }
}

Which is exactly what was done, along with tests and an upstream fix.