Description
Description
Sorry this problem appears within a big application and I didn't find a short php code reproducing the problem.
So I try to put the maximum explanations here.
In some cases I get this message in error log :
[core:notice] [pid 910] AH00051: child pid 23361 exit signal Segmentation fault (11), possible coredump in /etc/apache2
I found this message always appears twice because, when I get it, the index.php is executed a second time.
To find that, I put an errog_log('deb') at the very beginning of the index.php and an error_log('fin') at the last instruction.
In the log, I got :
[Tue Jan 24 10:50:37.515447 2023] [php:notice] [pid 23488] [client 127.0.0.1:49088] deb, referer: http://localhost/wer/index.php
[Tue Jan 24 10:50:40.193277 2023] [php:notice] [pid 23488] [client 127.0.0.1:49088] fin, referer: http://localhost/wer/index.php
[Tue Jan 24 10:50:40.856392 2023] [php:notice] [pid 23835] [client 127.0.0.1:49102] deb, referer: http://localhost/wer/index.php
[Tue Jan 24 10:50:41.479629 2023] [core:notice] [pid 910] AH00051: child pid 23488 exit signal Segmentation fault (11), possible coredump in /etc/apache2
[Tue Jan 24 10:50:43.102831 2023] [php:notice] [pid 23835] [client 127.0.0.1:49102] fin, referer: http://localhost/wer/index.php
[Tue Jan 24 10:50:43.482049 2023] [core:notice] [pid 910] AH00051: child pid 23835 exit signal Segmentation fault (11), possible coredump in /etc/apache2
So, index.php seems to be executed twice.
However, if I error_log the expected HTML result in the log, it is totally correct. (and I get it twice...)
But nothing is sent to the navigator.
Bypass
Step by step, I found a bypass : the problem disappears when I put a print_r of some object at the right place.
For example :
This caused the problem :
$ret = SG_Operation::execFonctionSansParametre($this, $o, $nom, $p2, $p1, $contexte);
//print_r($ret, true);
And this works correctly :
$ret = SG_Operation::execFonctionSansParametre($this, $o, $nom, $p2, $p1, $contexte);
print_r($ret, true);
It works too if I add :
$ret = unserialize(serialize($ret);
If the dumps of the object before and after the problem are identical.
I tried some other features which don't work :
$obj = SG_Operation::execFonctionSansParametre($this, $o, $nom, $p2, $p1, $contexte);
$ret = $obj;
or
$obj = SG_Operation::execFonctionSansParametre($this, $o, $nom, $p2, $p1, $contexte);
$ret = clone $obj;
Research notes
I found that the bypass does work if I just add the '''print_r''' as the first line of the __construct function of one of my classes :
/** SynerGaia contient la classe SG_Nombre de traitement des nombres */
defined("SYNERGAIA_PATH_TO_ROOT") or die('403.14 - Directory listing denied.');
/** Pour ajouter les méthodes et propriétés spécifiques de l'application créées par le compilateur */
if (file_exists(SYNERGAIA_PATH_TO_VAR . 'SG_Nombre_trait.php')) {
include_once SYNERGAIA_PATH_TO_VAR . 'SG_Nombre_trait.php';
} else {
/** trait vide par défaut */
trait SG_Nombre_trait{};
}
/**
* SG_Nombre : Classe SynerGaia de gestion d'un nombre
* @since 0.0
* @version 2.9
*/
class SG_Nombre extends SG_Objet {
// complément de classe créée par compilation
use SG_Nombre_trait;
/** string Type SynerGaia '@Nombre' */
const TYPESG = '@Nombre';
/** string Type SynerGaia */
public $typeSG = self::TYPESG;
/** integer|float Valeur interne du nombre (null par défaut) */
public $valeur;
/** string Unité de mesure (pas encore géré) */
public $unite = '';
/**
* Construction de l'objet
* @since 1.0.7
* @version 2.4 si rien : 0
* @version 2.9.1 getTexte pour unité
* @param any $pQuelqueChose valeur à partir de laquelle le SG_Nombre est créé
* @param any $pUnite code unité ou ou objet @Unite de la quantité
*/
function __construct($pQuelqueChose = null, $pUnite = null)
{
print_r($this, true); // bypass bug #10430
$tmpTypeSG = SG_Objet::getTypeSG($pQuelqueChose);
switch ($tmpTypeSG) {
case 'integer' :
$this -> valeur = (double)$pQuelqueChose;
break;
case 'double' :
$this -> valeur = $pQuelqueChose;
break;
case 'string' :
if ($pQuelqueChose !== '') {
$floatString = $pQuelqueChose;
$floatString = str_replace(" ", "", $floatString);
$floatString = str_replace(",", ".", $floatString);
$this -> valeur = floatval($floatString);
} else {
$this -> valeur = null;
}
break;
case '@Formule' :
$tmpNombre = new SG_Nombre($pQuelqueChose -> getResult());
$this -> valeur = $tmpNombre -> valeur;
break;
case '@Nombre' :
$this -> valeur = $pQuelqueChose -> valeur;
$this -> unite = $pQuelqueChose -> unite;
break;
case 'NULL' :
$this -> valeur = 0; //null;
break;
default :
// Si objet SynerGaia
if (substr($tmpTypeSG, 0, 1) === '@') {
$this -> valeur = $pQuelqueChose -> toFloat();
}
}
if($pUnite) {
$this -> unite = SG_Texte::getTexte($pUnite);
}
}
I also remark when the bypass works, the new class has been called by an instruction like :
$class = "MyClass";
$obj = new $class();
But, I can't make a short PHP program reproducing the problem.
Environment
PHP 8.1.2-1ubuntu2.10 (cli) (built: Jan 16 2023 15:19:49) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.2, Copyright (c) Zend Technologies
with Zend OPcache v8.1.2-1ubuntu2.10, Copyright (c), by Zend Technologies
on Ubuntu 22.04.1 LTS
I hope I'm clear enough clear...
Pierre Frappé (France)
PHP Version
first PHP 8.1.2, and now 8.2.1 (no change)
JIT tracing
Operating System
Ubuntu 22.04.1 LTS