Einer der Gründe, warum es besser ist, Parameter zu binden
– eckes
8. Dezember 2017 um 17:33 Uhr
Michael Ekstrand
Du kannst es mit machen sprintf, aber nicht allein (sicher). Verwenden Sie auf einem vernünftigen System snprintf zweimal, einmal, um die zu verwendende Größe herauszufinden, und das zweite Mal, um es tatsächlich zu tun. Dies hängt davon ab snprintf Gibt die Anzahl der benötigten Zeichen zurück, wenn der Platz knapp wird. Linux-, BSD- und C99-kompatible Systeme tun dies; Windows normalerweise nicht. Im letzteren Fall müssen Sie einen anfänglichen Puffer zuweisen und einen größeren zuweisen, wenn snprintf fehlschlägt (in einer Schleife bis snprintf gelingt es). Aber auf C99 funktioniert Folgendes:
char *buf;
size_t sz;
sz = snprintf(NULL, 0, "select key from answer WHERE key = %s LIMIT 5;", tmp);
buf = (char *)malloc(sz + 1); /* make sure you check for != NULL in real code */
snprintf(buf, sz+1, "select key from answer WHERE key = %s LIMIT 5;", tmp);
Jedochzum Erstellen von SQL, ist es viel besser zu verwenden vorbereitete Erklärungen. Sie vermeiden SQL-Injection-Schwachstellen (und häufig die Notwendigkeit von sprintf). Damit würden Sie die Anweisung „select key from answer where key = ? limit 5;“ vorbereiten und dann mit dem Parameter ausführen tmp. Die SQL-Engine fügt die Zeichenfolge ein und macht es überflüssig, zuerst sicherzustellen, dass sie richtig maskiert ist.
@Noldorin, kaum eine vorbereitete Aussage, Sie könnten temp immer noch ‘3;–drop table answer’ zuweisen.
– Byron Whitlock
17. November 2009 um 0:18 Uhr
Gesund, ein C99-Standard-konformes System zu sein! Einige C89-Implementierungen bieten ihre eigenen an snprintf das verhält sich nicht wie C99 beschreibt (Rückgabewert ist nicht unbedingt die benötigte Länge).
– pmg
17. November 2009 um 0:18 Uhr
+1 für die richtige Antwort, vorbereitete Aussagen, Puffersicherheit und die eine positive Bewertung, die Sie für 2000 Wiederholungen benötigten. Gern geschehen.
– poundifdef
17. November 2009 um 0:39 Uhr
@Byron Whitlock: Der Text für die vorgeschlagene ‘vorbereitete Erklärung’ war sicher gegen einen Schlüssel von ‘3;drop table answer;--‘ sowie Ihre Version des versuchten (aber fehlgeschlagenen) SQL-Injection-Angriffs.
– Jonathan Leffler
17. November 2009 um 3:12 Uhr
Ich habe eine kleine Korrektur vorgenommen, benutze (char *) im Malloc, um den Typ zu casten
– Rodrigo
17. September 2013 um 1:50 Uhr
Sie wollen sprintf().
char *sqlAnswers = malloc(SIZE_TO_HOLD_FINAL_STRING);
sprintf(sqlAnswers, "select key from answer WHERE key = %s LIMIT 5;", tmp);
Verwenden Sie immer snprintf() Zur sicherheit.
– Greg Hewgill
17. November 2009 um 0:10 Uhr
Wenn Sie gnu oder BSD libc verwenden, können Sie möglicherweise verwenden asprintfdie automatisch einen Puffer der richtigen Größe zuweist.
#define _GNU_SOURCE
#include <stdio.h>
// ...
char *sqlAnswers = NULL;
int length = asprintf(&sqlAnswers,"select key from answer WHERE key = %s LIMIT 5;", tmp);
free(sqlAnswers);
asprintf ist eine bequeme Abkürzung für die sprintf(malloc(snprintf(...))) Trick – ich stimme dafür, ihn zu verwenden und einen Fallback bereitzustellen asprintf Definition, wenn Sie sich jemals mit einer traurigen, veralteten Plattform auseinandersetzen müssen, der diese fehlt.
– vergänglich
17. November 2009 um 15:52 Uhr
Ich verwende tatsächlich sqlite3_bind_text, um meinen Platzhalter einzugeben, anstatt über sprintf zu generieren:
Einer der Gründe, warum es besser ist, Parameter zu binden
– eckes
8. Dezember 2017 um 17:33 Uhr