Die Flagge des Marasek

Dekostreifen

English

Aktuell Texte Der Comic Impressum Kalender Suche PHP-Klassen Container-Wizard main.s21

Kategorien

Buch
Computer
Computerspiele
Film
Geschichte
Gesellschaft
Idee
Kunst
Natur
Persönlich
Politik
Programmieren
Religion & Philosophie
Weblog
Weltpolitik
Weltsicht
{{login}}

Hilfsfunktion zur Typenkonversion

Permalink
Vorheriger: HäuserzeileNächster: Spass mit Pflanzen
Eingeordnet in: Programmieren

An anderer Stelle habe ich mich ja schon über die etwas undurchsichtige Typenkonversion von PHP beklagt. Einige Eigenheiten kann man sich zwar merken und entsprechend berücksichtigen, in anderen Fällen ist die implizit-automatische Typenkonversion schlicht zu undurchsichtig.

Nehme ich einmal an, ich übergebe den $_GET-Parameter "id" an ein Skript, der für einen Primärschlüssel in der Datenbank steht. Da ich weiss, dass es sich bei "id" um eine Zahl handeln muss, kann ich den Wert zu int casten, bevor ich ihn verwende:

$id = (int)$_GET["id"];

Damit stelle ich sicher, dass kein Angreifer id verwenden kann, um z. B. meine Datenbank per SQL-Injection zu schädigen.

Das Vorgehen von (int) bleibt aber unvorhersehbar und hängt von dem übergebenen Wert ab. "2" wird 2. "idiot" wird 0. "2'0" wird 2. Den Originalwert mit der konvertierten Form zu vergleichen, bringt nichts:

$id==$_GET["id"]

Denn in diesem Fall wird PHP für den Vergleich eine implizite Konversion vornehmen, die das gleiche ergibt wie meine eigene, also ergibt dieser Vergleich TRUE.

$id===$_GET["id"]

Der typentreue Vergleich ergibt jedoch auf jeden Fall FALSE, da der Originalwert ja "string" geblieben ist.
Der Trick liegt darin, den neuen Wert doppelt zu konvertieren, zunächst zu int, und dann wieder zu string.
"idiot"=> wird zu int 0 => wird zu string "0". Wenn dann der Originalwert mit dem doppelt konvertierten Wert verglichen wird, stimmen sie nicht mehr überein, sofern die Konvertierung einen Informationsverlust mit sich gebracht hat.

$double = (int)$_GET["id"];
$double = (string)$double;
$double==$_GET["id"]; // FALSE

Nachfolgend eine Funktion, die die Arbeit übernimmt. Bitte einige Besonderheiten berücksichtigen:

  • cast zu array liefert immer FALSE, es sei denn, die Variable ist bereits ein array
  • cast zu resource oder object wurde nicht berücksichtigt (woher soll cast auch die ressource herzaubern?)
  • Die Behandlung von NULL, 0 etc. ist strenger als in PHP: NULL zu int ergibt falsch, da ich NULL und 0 als unterschiedliche Werte ansehe.
<?php

function is_castable($var$type)
{
// These types cannot be cast to or from without getting erratic results
$uncastable = array("array""object""resource");
    if(
in_array($type$uncastable) and gettype($var)!=$type)
    {return 
false;}
    if(
in_array($type$uncastable) and gettype($var)==$type)
    {return 
true;}
    
$types = array("int""integer""double""float""null""bool""string""array");
    if(!
in_array($type$types))
    {
trigger_error("Invalid type"E_USER_ERROR);}
$double $var;
// doublecast $var - to type, then back to string
$double = (string)settype($double$type);
    
// TRUE if $var and $double still have the same content, regardless of type
    
if($var==$double)
    {return 
true;}
return 
false;
}


    if(
is_castable(1"string"))
    {echo 
"yes<br />n";} // yes
    
else
    {echo 
"no<br />n";}

    if(
is_castable(1.5"integer"))
    {echo 
"yes<br />n";} 
    else
    {echo 
"no<br />n";} // no

    
if(is_castable(1"float"))
    {echo 
"yes<br />n";} // yes
    
else
    {echo 
"no<br />n";}

    
    if(
is_castable(0"null"))
    {echo 
"yes<br />n";}
    else
    {echo 
"no<br />n";} // no

    
if(is_castable(array(1,2), "array"))
    {echo 
"yes<br />n";} // yes
    
else
    {echo 
"no<br />n";}

    if(
is_castable(array(1,2), "string"))
    {echo 
"yes<br />n";} 
    else
    {echo 
"no<br />n";} // no

?>

Kommentieren

Bitte beachten: Kommentare sind nicht sofort sichtbar, sondern werden erst nach einer kurzen Prüfung freigegeben, sofern keine rechtliche Beanstandung vorliegt.
Rechtlich bedenkliche Inhalte werden entweder entschärft oder nicht veröffentlicht.

* Titel  
* Nickname  
* Kommentar