Problem mit einem SQL-Statement in Zusammenspiel mit der Funktion "sprintf"


Davicito

Erfahrenes Mitglied
Hallo liebe Gemeinde,

ich melde mich mal wieder, weil ich zur Zeit ein bisher unbekanntes Problem mit einem SQL-Statement besitze und ich erstmal nicht weiter komme.

Hintergrund:
Ich habe zum Absetzen eines SQL-Statements eine Methode namens runQuery() geschrieben, die ein formuliertes SQL-Statement, als String und ein Array mit Statement-variablen übergeben bekommt, welches in der Methode zu einem String zusammen gesetzt wird und anschließend mit der sprintf-Funktion konkadiniert wird um das Statement mit dem Query-Befehl an den MYSQL-Server abzusentzen.
Den Aufwand mache ich deswegen damit ich die im Array entghaltenen Variablen - die aus einem POST kommen, mit der "real_escape_string"-Funktion filtern kann um SQL-Injection zu umgehen.

Hier der Code dazu:

Formulierung des SQL-Statements:
PHP:
...
private function MAInput(HttpRequest $req){
...
  // %d oder %s dienen als Platzhalter für die im Array enthaltenen Variablen, die nachher die Funk. sprintf-Funktion interpretiert
  $sqlStatement = "INSERT INTO 
					mitarbeiter
				SET 
					Anrede_ID = %d,
					PersonalNummer = %d, 
					Vorname = %s,								
					PLZ = %d,							
					Telefon = %d,
					Handy = %d ";
								
  $parameter = array($req->getParameter('anr'), $req->getParameter('pn'), 
                     $req->getParameter('vn'), $req->getParameter('plz'), 
                     $req->getParameter('tel'), $req->getParameter('mobi'));

  $result = AuthModel::runQuery($sqlStatement, $parameter);
  var_dump($result);	
...
}

Model-Klasse:
PHP:
...
public static function runQuery($statement, $arrayOfVars = array()){						
	$connectState = self::connectDB(....);
				
	//Übergabeparameter auf Inhalt und Typ prüfen.
	if(!empty($statement) && !empty($arrayOfVars) && is_string($statement) && is_array($arrayOfVars) && $connectState == true){
								
		// Alle übergebenen Variablen, im Array, werden von evtl. angehängten Zeichen befreit (DB Injection)	
		$tempArray = array();
		foreach ($arrayOfVars as $key){
			array_push($tempArray, self::$resDB->real_escape_string($key));
		}
				
		//Konkadinieren des SQL-Statements und der Variablen, im Array
		array_unshift($tempArray, $statement);	
		// Füge den konkadinierten String nun mit der formatierten Ausgabefunktion "sprintf" aus. 
		$statement = call_user_func_array('sprintf',$tempArray);	

                try{	
			if($result = self::$resDB->query($statement)){
				//Verbindung zur Datenbank, nach Absetzen das Statements, schließen (LAZY-Pattern). 
				self::$resDB->close();					
			        return 'SQL-Statement erfolgreich! ';
			}else throw new \Exception('Fehler im Statement: "'.self::$resDB->error.'"');		
		}catch(\Exception $e){
				echo $e->getMessage();
		}			
	}
...

Leider bekomme ich folgende Fehlermeldung zu Gesicht:

Fehlerausgabe:
Code:
// Test ist der eingegebene Vorname 
Fehler im Statement: "Unknown column 'Test' in 'field list'"NULL

Der Ausgabe-String nach Verarbeitung durch "sprintf" sieht so aus:
SQL:
INSERT INTO mitarbeiter SET Anrede_ID = 2, PersonalNummer = 123456, Vorname = Test,	 PLZ = 12345,	 Telefon = 1234567, Handy = 2147483647

Ich habe auch geprüft, ob die Spalte in der Tabelle "Mitarbeiter" existiert. Die Spalten sind alle korrekt und vorhanden!
Wenn ich jetzt den Platzhalter "%s" vor dem Vornamen, im SQL-Statement in "%d" umändere, wird der Datensatz eingetragen, jedoch fehlt in der Tabelle der Namen. Stattdessen wird "0" als Namen in die Tabelle gespeichert.
Mir ist auch klar wofür %d steht, nur testhalber habe ich den für Vorname genommen um zu schauen, ob die Fehlermeldung weggeht!

Ist der Platzhalter %s für einen übergebenen String, aus einem Eingabeformular falsch gewählt? oder kommt die Funktion sprintf mit unterschiedlichen Platzhaltertypen, wie "%s" und "%d" nicht klar?


Bei einem ähnlichen Statement funktioniert die Eingabe einwandfrei!
Eingabe-Satement zum Anlegen eines Users
PHP:
...
$sqlStatement = "GRANT %s ON *.* TO '%s'@'localhost' IDENTIFIED BY '%s' WITH GRANT OPTION";

$parameter = array($req->getParameter('kontotype'), $req->getParameter('userName'), $req->getParameter('userPW'));

$result = AuthModel::runQuery($sqlStatement, $parameter);
...
 
Zuletzt bearbeitet:

Yaslaw

n/a
Moderator
Mal schnell dein SQL durch einen Formatter spühlen und schon ist es lesbar
SQL:
INSERT INTO mitarbeiter 
SET 
    anrede_id = 2, 
    personalnummer = 123456, 
    vorname = test, 
    plz = 12345, 
    telefon = 1234567, 
    handy = 2147483647
Die Meldung besagt, dass er das Feld test nicht kennt.
Ich geh mal davon aus, dass du kein Feld test hast sondern den String test übergeben willst.
Strings musst du in ' setzen
SQL:
INSERT INTO mitarbeiter 
SET 
    anrede_id = 2, 
    personalnummer = 123456, 
    vorname = 'test', 
    plz = 12345, 
    telefon = 1234567, 
    handy = 2147483647

Entweder du passt das bei dir an, oder su steigst auf PDO oder MySQLi mit preapred Statements um. Dort gibts auch kein mysql_string_escape mehr und du das Handeln von Strings ist auch viel einfacher
 

Davicito

Erfahrenes Mitglied
Jawohl... es hat geklappt! ^^ Das hab ich auch nicht gewusst ;-). Ich arbeite zwar bereits mit MySQLi aber ich hab die Preapred-Methode noch nicht ausprobiert. ich werde das dem Nächst noch integrieren.

Vielen Dank******
 
Zuletzt bearbeitet:

Neue Beiträge