Tom: Fehlerquellen aufspüren in PHP-Scripten

Hello,

so langsam kämpfe ich mich durch eine Latte von Hinweisen durch, wo in PHP-Scripten immer gerne Fehler gemacht werden. Habe selber ja auch schon eine Menge davon "geübt" *gg*

Hier ein kleines Testscript zum Thema "Type Override"

<?php    ### unserialize.php ###

Welchen Datentyp liefert unserialize() bei fehlerhaftem Argument?

Kann man einen Bool impliziz in ein Array umwandeln?

Kann man einen String implizit in ein Array umwandeln?

$arg = "scheisse";

$_data = unserialize($arg);

echo "<pre>";
echo "$_data:\n";
var_dump($_data);
echo "</pre>";

$_data["wert"] = "neuer Wert";

echo "<pre>";
echo "$_data:\n";
var_dump($_data);
echo "</pre>";

$_data = "noch ein String";
$_data["wert"] = "neuer Wert";

echo "<pre>";
echo "$_data:\n";
var_dump($_data);
echo "</pre>";

?>

<!-- Ausgabe

$_data:
bool(false)

$_data:
array(1) {
  ["wert"]=>
  string(10) "neuer Wert"
}

$_data:
string(15) "noch ein String"

-->

Jetzt die Frage: Ist das irgendwo verbrieft nachlesbar, dass man einen Bool implizit in ein Array umwandeln kann, oder ist das ein netter Seiteneffekt und von den PHP-Entwicklern nicht unbedingt so vorgesehen?

Liebe Grüße aus http://www.braunschweig.de

Tom

--
Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
  1. Hi Tom,

    [...]
    $_data = "noch ein String";
    $_data["wert"] = "neuer Wert";

    echo "<pre>";
    echo "$_data:\n";
    var_dump($_data);
    echo "</pre>";

    <!-- Ausgabe
    [...]
    $_data:
    string(15) "noch ein String"

    -->

    ich verstehe diesen Teil nicht so ganz. Hätte PHP hier nicht auch den String $_data durch das Array $_data ersetzen müssen? Schließlich definierst du es, nachdem du $_data einen String zuweist. Existiert zu diesem Zeitpunkt der Wert $_data["wert"] denn überhaupt? Wenn nicht, sehe ich eher hier die Merkwürdigkeit, nicht an dem Punkt, an dem du du den Boolean $_data durch ein Array $_data ersetzt (das hätte ich erwartet).

    Gruß.

    1. Hello,

      [...]
      $_data = "noch ein String";
      $_data["wert"] = "neuer Wert";

      echo "<pre>";
      echo "$_data:\n";
      var_dump($_data);
      echo "</pre>";

      <!-- Ausgabe
      [...]
      $_data:
      string(15) "noch ein String"

      -->

      ich verstehe diesen Teil nicht so ganz. Hätte PHP hier nicht auch den String $_data durch das Array $_data ersetzen müssen? Schließlich definierst du es, nachdem du $_data einen String zuweist. Existiert zu diesem Zeitpunkt der Wert $_data["wert"] denn überhaupt? Wenn nicht, sehe ich eher hier die Merkwürdigkeit, nicht an dem Punkt, an dem du du den Boolean $_data durch ein Array $_data ersetzt (das hätte ich erwartet).

      Das ist ja gerade die Krux. Einen Skalar in einem Array kann man definitionsgemäß nur mit einem Skalar überschreiben, nicht aber mit einem Array. Das zeigt auch der Versuch mit $_data["wert"] = ...

      Da in diesem Fall bereits $_data ein String ist, kann man nicht implizit ein Array() auf $_data anlegen. Man muss erst den Knoten selbst in ein Array umwandeln durch $_data = array(); Dann wird er neu definiert.

      Wenn nun $_data aber ein Bool ist, dann lässt PHP die implizite Deklaration zu.

      Wenn man ein neues Array deklariert, dann kann der Pfad sogar sogar bis in tiefste Tiefen angelegt werden.

      $_multidim["eins"]["zwei"]["drei"]["vier"] = "angekommen";

      In jeden der Knoten können nun auch weitere Elemente eingehängt werden, Egal ob Skalare oder Arrays.

      Da ganze hat Effekt beim Weiterreichen von Werten über Hidden-Fields. Dazu werden die Werte serialisiert und das Ergebnis dann umcodiert und im Value des Hidden-Fields weitergeben. Auf der nächsten Seite wieder decodiert, deserialisiert und verarbeitet.... wieder serialisiert, codiert und weitergegeben.

      Die Werte gehen aber immer durch den Einflusßbereich des Users. Er kann da im Prinzip alles reinschreiben und auch selber codieren.

      So muss man dann nach dem deserialisieren auf jeden fall danach fragen, ob dabei ein Array entstanden ist, denn unserialize() kann auch Integer, double, string, und object als Ergebnis haben.

      Dass man die erhaltenen Werte dann selbstverständlich auch noch auf Plausibilität prüfen muss, ist sowieso klar.

      Liebe Grüße aus http://www.braunschweig.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
  2. Moin!

    $arg = "scheisse";

    $_data = unserialize($arg);

    Diese Zeile liefert bei mir eine Notice über einen unzulässigen Parameterwert in $arg. War ja auch klar...

    $_data = "noch ein String";
    $_data["wert"] = "neuer Wert";

    echo "$_data:\n";
    var_dump($_data);

    Und an dieser Stelle hat deine unglückliche Auswahl an Teststrings einen sehr ungünstigen Effekt überdeckt.

    Teste mal so:

    $_data = "1 Million Euro";
    $_data['wert'] = 9;

    var_dump($_data);

    Da werden aus einer Million plötzlich 9 Millionen!

    Der erste Buchstabe des Strings wird jeweils überschrieben. Zumindest bei meiner Version 4.3.0 und 4.3.3.

    Merke: Das implizite Definieren von Arrays ist nicht die Methode, die man wirklich anwenden sollte.

    - Sven Rautenberg

    --
    "Habe den Mut, dich deines eigenen Verstandes zu bedienen!" (Immanuel Kant)
    1. Hello,

      $arg = "scheisse";

      $_data = unserialize($arg);

      Diese Zeile liefert bei mir eine Notice über einen unzulässigen Parameterwert in $arg. War ja auch klar...

      $_data = "noch ein String";
      $_data["wert"] = "neuer Wert";

      echo "$_data:\n";
      var_dump($_data);

      Und an dieser Stelle hat deine unglückliche Auswahl an Teststrings einen sehr ungünstigen Effekt überdeckt.

      Teste mal so:

      $_data = "1 Million Euro";
      $_data['wert'] = 9;

      var_dump($_data);

      Da werden aus einer Million plötzlich 9 Millionen!

      Der erste Buchstabe des Strings wird jeweils überschrieben. Zumindest bei meiner Version 4.3.0 und 4.3.3.

      Merke: Das implizite Definieren von Arrays ist nicht die Methode, die man wirklich anwenden sollte.

      Ja, genau darum geht es mir. Ich ahbe in diversen Shareware und Freeware-Programmen soviele merkwürdige Sachen gefunden, dass ich vor einiger Zeit einfach mal angefangen habe, die Fehlerquellen zu suchen und zu sortieren. das implizite Dekalrieren ist ja bei PHP ausdrücklich erlaubt, man muss nur vorher schauen, ob der Pfad auch frei ist.

      Dein Besipiel schau ich mir gelich noch an.

      Ich danke für den Input.

      Liebe Grüße aus http://www.braunschweig.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen