Можно ли исправить эту очень полезную функцию PHP?
Если уже переписываете, то переписывайте нормально. Избавляйтесь от глобального массива $CONF, рекурсии и функций без неймспейсов. Также у вас функция как записывает так и читает значения, что немного выносит мозг. Также считаю что исключению там не место, лучше заменить на значение по умолчанию

class Config {

	protected static array $register = [];

	public static function get(string $name, $default = null) {
		$keys = explode('.', $name);

		$pointer = self::$register;

		foreach ($keys as $key) {
			if (!array_key_exists($key, $pointer)) {
				/*Если ключа нет, выставить его*/
				//self::set($name, $default);

				/*Бросить исключение*/
				//throw new Exception("No such key: {$name}");

				/*Вернуть значение по умолчанию*/
				return $default;
			}

			$pointer = &$pointer[$key];
		}

		return $pointer;
	}

	public static function set(string $name, $value = null) {
		$arr = &self::$register;
		$keys = explode('.', $name);

		foreach ($keys as $key) {
			$arr = &$arr[$key];
		}

		if (is_array($arr) && is_array($value)) {
			$arr = array_replace_recursive($arr, $value);
		} else {
			$arr = $value;
		}
	}

	public static function getTree() {
		return self::$register;
	}
}

Config::set("config", [
	"name" => "test",
]);
print_r(Config::get("config"));
echo "(config)\n\n";

Config::set("config.class.name", "A");
print_r(Config::get("config.class.name"));
echo "\n(config.class.name)\n\n";

Config::set("config", [
	"class" => [
		"test" => "B",
	],
]);
print_r(Config::get("config.class"));
echo "\n(config.class)\n\n";

Config::set("config.class", null);
print_r(Config::get("config.class"));
echo "\n(config.class)\n\n";

print_r(Config::get("config.fake.key.without.value", "UNDEFINED"));
echo "\n(config.fake.key.without.value)\n\n";

Config::set("config.nullable", null);
print_r(Config::get("config.nullable", "NULL"));
echo "\n(config.nullable)\n\n";

print_r(Config::getTree());
echo "\n(all)\n";

Работает в PHP7.4
Исходный вариант кода, но исправленный:
$CONF = array('category' => array('name' => "Hello", 'data' => array()));

function aGetByKey(&$array, $index, $value = null) {
    if (strpos($index, "."))
        list($index, $key) = explode('.', $index, 2);
    if (!isset($index) OR !isset($array[$index]))
        throw new Exception("No such key: " . $index);

    if(!empty($key))
        return aGetByKey($array[$index], $key, $value);

    $old = $array[$index];
    if ($value !== null)
        $array[$index] = $value;

    return $old;
}

function conf($key, $value = null) {
    global $CONF;
    return aGetByKey($CONF, $key, $value);
}

//Хотелось-бы чтобы она работала так:
echo conf('category.name'); //Hello
echo conf('category.name', 'World'); //Hello, потому что возвращается предыдущее значение $old
echo conf('category.name'); // World

conf('category.data', ['amount' => 158, 'kind' => 36]); // echo() нельзя, потому что вернётся массив
echo conf('category.data')['amount']; //158