| PHP Developer Forum Hier habt ihr die Möglichkeit, eure Skriptprobleme mit anderen Anwendern zu diskutieren. Seid so fair und beantwortet auch Fragen von anderen Anwendern. Dieses Forum ist sowohl für ANFÄNGER als auch für PHP-Profis! Post your PHP questions here! |
 |

17-03-2011, 20:16
|
|
Truncate
Registrierter Benutzer
|
|
Registriert seit: Nov 2005
Beiträge: 321
|
|
Körpergröße prüfen mit preg_match("/[0-9]{3}$/",$groesse)
Hallo,
wie kann ich die Körpergröße in cm auf eine gültige Eingabe überprüfen?
preg_match("/[0-9]{3}$/",$groesse)
Das schränkt es zumindest auf eine 3-stellige Zahl ein, aber da sind ja dann trotzdem noch Zahlenkombis wie 000 und 999 möglich.
Wie füge ich also noch einen Bereich hinzu (z.B. 150 - 200 cm)?
Danke,
Truncate
|

17-03-2011, 20:22
|
wahsaga
 Moderator
|
|
Registriert seit: Sep 2001
Beiträge: 24.486
|
|
Zitat:
Zitat von Truncate
Wie füge ich also noch einen Bereich hinzu (z.B. 150 - 200 cm)?
|
Du könntest als erste Ziffer nur 1 oder 2 zulassen.
Aber generell sind reguläre Ausdrücke für sowas weniger geeignet, auch nicht gedacht.
Wandle den Wert in eine Zahl um, und prüfe dann auf den erlaubten Wertebereich.
__________________
I don't believe in rebirth. Actually, I never did in my whole lives.
|

17-03-2011, 20:36
|
|
Truncate
Registrierter Benutzer
|
|
Registriert seit: Nov 2005
Beiträge: 321
|
|
Zitat:
Zitat von wahsaga
Wandle den Wert in eine Zahl um, und prüfe dann auf den erlaubten Wertebereich.
|
Muss das zwingend sein?
Reicht das nicht aus:
if($_POST['groesse']>=145 && $_POST['groesse']<=210){...}
Oder ist da in irgendeiner Form noch Betrug (andere Zahlen, Injections) möglich?
|

17-03-2011, 22:34
|
 |
fireweasel
Registrierter Benutzer
|
|
Registriert seit: Sep 2008
Ort: At home
Beiträge: 680
|
|
Zitat:
Zitat von Truncate
Muss das zwingend sein?
Reicht das nicht aus:
if($_POST['groesse']>=145 && $_POST['groesse']<=210){...}
Oder ist da in irgendeiner Form noch Betrug (andere Zahlen, Injections) möglich?
|
Ja, ein älteres PHP könnte hier bei Benutzereingaben, die als Gleitkommazahl daherkommen, in eine Endlosschleife geraten. Der Bug wurde erst Anfang diesen Jahres entdeckt und behoben.
PHP-Code:
$groesse = isset ($_POST['groesse'][0])
? (int) $_POST['groesse']
: $defaultwert;
if ($groesse >= 145 && $groesse <= 210) {
// ...
}
Mit Regex sähe es für den Bereich 150 bis 210 (cm?) so aus:
PHP-Code:
if (preg_match(
'/\A\s*(1[5-9][0-9]|20[0-9]|210)\s*\z/',
$_POST['groesse']
)) {
// ...
}
Das wird aber je nach gewünschtem Bereich unterschiedlich komplex und ist daher nur was für Leute, denen sowas Spaß macht.
__________________
PHP-Code:
class Brick implements Throwable {
// ...
}
|

17-03-2011, 22:41
|
|
h3ll
Registrierter Benutzer
|
|
Registriert seit: Mar 2008
Beiträge: 2.328
|
|
Zitat:
Zitat von fireweasel
|
Eben, der Bug wurde behoben. Wo ist das Problem? Nur weil irgendwelche Gammel-Server noch mit Uralt-PHP laufen? Die sind dann selber schuld. Hier hat der Server-Admin seinen Beruf verfehlt.
|

17-03-2011, 22:55
|
|
sili
Registrierter Benutzer
|
|
Registriert seit: Feb 2004
Beiträge: 115
|
|
Du könntest auch filter_input() verwenden.
|

19-03-2011, 18:07
|
 |
fireweasel
Registrierter Benutzer
|
|
Registriert seit: Sep 2008
Ort: At home
Beiträge: 680
|
|
Zitat:
Zitat von h3ll
Eben, der Bug wurde behoben. Wo ist das Problem?
|
Du glaubst doch nicht ernsthaft, dass das der letzte Bug dieser Art war ...?
Zitat:
|
Nur weil irgendwelche Gammel-Server noch mit Uralt-PHP laufen?
|
Ja, toll. Das nützt jemandem, der ein Script schreiben muss, welches bei möglichst vielen Hostern fehlerfrei laufen soll, jetzt wieviel?
Stell dir vor, du wärst der Autor einer beliebten Scriptsammlung (Framework, Library, CMS, Blog, Board was auch immer). Als solcher bekämst du Bugreports, diesen Fehler betreffend. Selbstverständlich denken die User, es wäre deine Software, die fehlerhaft ist. Wie würdest du reagieren?
Zitat:
|
... Die sind dann selber schuld. Hier hat der Server-Admin seinen Beruf verfehlt.
|
Jeder Admin, der freiwillig PHP auf einem Server installiert, fällt in diese Kategorie.
__________________
PHP-Code:
class Brick implements Throwable {
// ...
}
Geändert von fireweasel (19-03-2011 um 18:22 Uhr)
Grund: typos
|

20-03-2011, 16:58
|
 |
mermshaus
Registrierter Benutzer
|
|
Registriert seit: Jun 2009
Beiträge: 165
|
|
Mal interessehalber: Was machen wir denn, wenn Floats als Eingaben akzeptiert werden müssen?
Immerzu auf Stringbasis prüfen, ob die Eingabe nicht "2.2250738585072011e-308" ist?
Was ist, wenn die Anwendung zum Beispiel zwei Eingaben multipliziert?
|

21-03-2011, 22:18
|
 |
fireweasel
Registrierter Benutzer
|
|
Registriert seit: Sep 2008
Ort: At home
Beiträge: 680
|
|
Zitat:
Zitat von mermshaus
Mal interessehalber: Was machen wir denn, wenn Floats als Eingaben akzeptiert werden müssen?
|
Wenn wirklich nur die ungepatchte PHP-Version zur Verfügung steht, kannst du verschiedenes versuchen:
- Die Eingaben auf bestimmte Werte zu begrenzen (maximale Länge und keine Exponenten). Das sollte bspw. bei der Auswertung von HTTP-Headern helfen, die Quality-Factors enthalten ("Accept" usw.).
- Das Muster zu erkennen und den Wert auf 0.0 setzen, da solche Zahlen der 0.0 wohl ausreichend nahe kommen.
- Unter Windows die COM-Extension verwenden. Deren Variant-Datentypen sind nicht von diesem Bug betroffen. Man kann ihnen auch Strings übergeben, die dann als Gleitkommazahl interpretiert werden. Allerdings ist die Interpetation anscheinend Locale-abhängig. Auf einer "deutsch eingestellten" Windows-Version werden nur Gleitkommazahlen mit richtigem Komma ',' als Trennzeichen akzeptiert. Mit dem Dezimalpunkt '.' klappt das nicht.
Zitat:
|
Immerzu auf Stringbasis prüfen, ob die Eingabe nicht "2.2250738585072011e-308" ist?
|
Das ist (leider) nicht die einzige Zahl und auch nicht die einzige Darstellung dieser Zahl, die Schwierigkeiten macht.
PHP Hangs On Numeric Value 2.2250738585072011e-308 - Exploring Binary
In den Benutzer-Kommentaren auf der Website des Bug-Entdeckers findet sich ein Ansatz das Muster zu erkennen: Die zu verarbeitende Variable wird serialisiert und dann auf das Ziffernmuster untersucht.
Eventuell lässt sich auch eine der Notlösungen für Java portieren.
Zitat:
|
Was ist, wenn die Anwendung zum Beispiel zwei Eingaben multipliziert?
|
PHP-Code:
$a = new variant($_GET['a'], VT_R8);
$b = new variant($_GET['b'], VT_R8);
$x = variant_mult($a, $b);
printf('%s * %s = %s', $a, $b, $x);
Da der Fehler nur in der Umwandlungsphase von String nach Double auftritt, sollte auch funktionieren.
==
Nachtrag:
Man kann die Umwandlung notfalls nachbauen, indem man den String in Mantissen- und Exponent-Teil zerlegt und anschließend die beiden Teile per pow() wieder zusammenbastelt:
PHP-Code:
/// COM-Variant-Variante
/// return double() | FALSE
function dpfloat_vt($str) {
try {
// strtr() wandelt Dezimalpunkt in Komma
$vt_dbl = (float) new variant(strtr($str, '.', ','), VT_R8);
}
catch (com_exception $ex) {
$vt_dbl = FALSE;
}
return $vt_dbl;
}
/// Hobbythek-Variante: Selberbasteln mit pow()
/// und Notfall-Laengenbegrenzung der Mantisse
/// return double() | FALSE
function dpfloat_val($str) {
$pcre = '/\A
((?:0\.0{0,306}(0)*|[0-9]*\.|)[0-9]+) # mantissa
(?:[eE]([+-]?[0-9]+))? # optional exponent
\z/x';
if (!preg_match($pcre, $str, $hits)) {
return FALSE;
}
$double = isset($hits[2][0])
// truncating mantissa which starts with 0.000..., but has too many 0
? (double) substr($hits[1], 0, -strlen($hits[2]))
: (double) $hits[1];
return isset ($hits[3])
? $double * pow(10, (int) $hits[3]) // has exponent
: $double;
}
// einige Beispielwerte:
// Extremfaelle mit "langer" Mantisse
// 0.22250738585072011e-307
$x = str_pad('0.', 309, '0') . '22250738585072011';
$y = str_pad('0.', 309, '0') . '2225073858507201';
$xe = $x . 'e0';
$test = array (
'0.333333333333333314829616256247390992939472198486328125', // 1/3
'1',
'3.14',
'1.23456789012345678901234567890',
'0.1e-10',
'0.1e10',
(string) pow(2, 52),
'2.2250738585072011e-308',
'22.250738585072011e-309',
'0.22250738585072011e-307',
'.22250738585072011e-307',
'2.22507385850721e-308',
'2.22507385850722e-308',
'2.22507385850725e-308',
'2.22507385850729e-308',
$x,
$y,
$xe,
'b',
);
foreach ($test as $input) {
$my_dbl = dpfloat_val($input);
$vt_dbl = dpfloat_vt($input);
$diff = abs($my_dbl - $vt_dbl);
printf('%s ?= %s diff: %s' . "<br />", $my_dbl, $vt_dbl, $diff);
}
Wie man sieht, gibt es ein paar Abweichungen bei sehr kleinen Zahlen. Aber wer genau mit Gleitkommazahlen rechnen möchte, wird höchstwahrscheinlich kein PHP einsetzen.
__________________
PHP-Code:
class Brick implements Throwable {
// ...
}
Geändert von fireweasel (22-03-2011 um 12:30 Uhr)
|

21-03-2011, 23:08
|
 |
mermshaus
Registrierter Benutzer
|
|
Registriert seit: Jun 2009
Beiträge: 165
|
|
Danke für die Infos.
Ein Regex-Check von Eingabe-Strings gegen etwa /\d+(?:\.\d{1,4})?/ (Zahl mit maximal vier Nachkommastellen) sollte es also tun, nehme ich an.
Ich finde die Frage, ob das anwendungsseitig behandelt werden sollte, auch nicht ganz leicht zu beantworten. In „Bibliothekscode“ kommt man wohl schwer drumrum.
|

22-03-2011, 12:44
|
 |
fireweasel
Registrierter Benutzer
|
|
Registriert seit: Sep 2008
Ort: At home
Beiträge: 680
|
|
Zitat:
|
Zitat von sili
Du könntest auch filter_input() verwenden.
|
Theoretisch ist die Filter-Erweiterung eine gute Idee.
Der Sanitize-Filter entfernt Zeichen, die nicht in einer Gleitkommazahl vorkommen dürfen. Nur wenn die Zeichenkette dann nach Float gewandelt wird, geht die Sache trotzdem schief.
Gleiches wird wohl beim Validate-Filter passieren: Das Muster '2.2250738585072011e-308' ist ja eine gültige Float-Darstellung. Das dürfte (und sollte) der Filter anstandslos durchlassen.
Wenn man aber konsequent mit den Filtern arbeitet und Daten nicht anderweitig ins Script lässt, könnte man per Callback-Filter eine Funktion einbauen, die das handhabt.
Zitat:
Zitat von mermshaus
Danke für die Infos.
Ein Regex-Check von Eingabe-Strings gegen etwa /\d+(?:\.\d{1,4})?/ (Zahl mit maximal vier Nachkommastellen) sollte es also tun, nehme ich an.
|
Für die typischen (oben erwähnten) Web-Anwendungen sollte das ausreichen. Wichtig ist hier die Längenbegrenzung.
Zitat:
|
Ich finde die Frage, ob das anwendungsseitig behandelt werden sollte, auch nicht ganz leicht zu beantworten. In „Bibliothekscode“ kommt man wohl schwer drumrum.
|
Klar sind das alles nur Workarounds, die die zwei darunterliegenden Probleme nicht beheben: Den Fehler selbst und die "Type-Coercion", die dafür sorgt, dass automatisch nach Float gewandelt wird. Aber wie schon gesagt: Wenn bspw. eine Blogsoftware (die nun nicht gerade unter "Bibliothekscode" fällt) überall laufen soll, kommt man nicht drumherum, den Fehler zu berücksichtigen. Die älteste PHP-Version, die ich bei einem großen Free-Hoster gesehen habe, ist derzeit 5.2.11. Es dürften aber auch noch einige ungepatchte 5.3.-er rumlaufen.
__________________
PHP-Code:
class Brick implements Throwable {
// ...
}
Geändert von fireweasel (22-03-2011 um 13:35 Uhr)
|

25-03-2011, 16:28
|
|
h3ll
Registrierter Benutzer
|
|
Registriert seit: Mar 2008
Beiträge: 2.328
|
|
Zitat:
Zitat von fireweasel
Du glaubst doch nicht ernsthaft, dass das der letzte Bug dieser Art war ...?
|
Wenn es nach dem geht, darfst du gar kein PHP verwenden, weil in jeder Funktion ein Bug stecken könnte, mit dem man Code einschleusen oder den Server blockieren könnte.
Zitat:
Zitat von fireweasel
Ja, toll. Das nützt jemandem, der ein Script schreiben muss, welches bei möglichst vielen Hostern fehlerfrei laufen soll, jetzt wieviel?
|
Irgendwo muss man Abstriche machen. Man kann nicht bis in alle Ewigkeit Gammel-Server supporten. Sonst müsste man heute immer noch PHP 3 programmieren.
Wofür gibt es Mindestvoraussetzungen? Wenn ich eine Software kaufe, die nur unter Windows Vista und Windows 7 läuft, dann hab ich eben Pech gehabt, wenn ich noch Windows XP verwende.
Zitat:
Zitat von fireweasel
Stell dir vor, du wärst der Autor einer beliebten Scriptsammlung (Framework, Library, CMS, Blog, Board was auch immer). Als solcher bekämst du Bugreports, diesen Fehler betreffend. Selbstverständlich denken die User, es wäre deine Software, die fehlerhaft ist. Wie würdest du reagieren?
|
Nicht wirklich. Oder sind auch automatisch alle Programmierer schuld, wenn eine Intel CPU einen Rechenfehler hat?
Geändert von h3ll (25-03-2011 um 16:34 Uhr)
|

25-03-2011, 17:59
|
 |
fireweasel
Registrierter Benutzer
|
|
Registriert seit: Sep 2008
Ort: At home
Beiträge: 680
|
|
Im Prinzip gebe ich dir ja recht. Warum freust du dich nicht einfach darüber, dass du in der glücklichen Lage bist, auf solchen Unfug keine Rücksicht nehmen zu müssen?
Zitat:
Zitat von h3ll
Wenn es nach dem geht, darfst du gar kein PHP verwenden, weil in jeder Funktion ein Bug stecken könnte, mit dem man Code einschleusen oder den Server blockieren könnte.
Irgendwo muss man Abstriche machen. Man kann nicht bis in alle Ewigkeit Gammel-Server supporten. Sonst müsste man heute immer noch PHP 3 programmieren.
Wofür gibt es Mindestvoraussetzungen? Wenn ich eine Software kaufe, die nur unter Windows Vista und Windows 7 läuft, dann hab ich eben Pech gehabt, wenn ich noch Windows XP verwende.
|
Hast du dir die Geschichte dieses speziellen Bugs mal näher angesehen? In der Originalroutine war der 1997 schon gefixt (per #ifdef "ausgeklammert"). Die PHP-Macher haben es trotzdem fertiggebracht, irgendwann danach genau die Teile zu kopieren (oder wieder zu aktivieren), die diesen Fehler hatten. Anfang 2011, schlappe 14 Jahre nach 1997, haben sie mitbekommen, dass da ein schwerwiegender Fehler drin ist. Aber sie ersetzen den fehlerhaften Code nicht durch den seit 1997 gefixten, sondern fummeln an den Speicherklassen rum. Kommt irgendwann mal ein neuer Compiler, der das nun erzwungene Zwischenspeichern wegoptimiert, können wir nur hoffen, dass dann entweder kein Prozessor mehr da ist, der noch x87-Mathematik kann, oder dass die Helden wenigstens einen passenden Test hinzugefügt haben, damit sie das mitbekommen.
Und da erzählst du mir was von alten Zöpfen, die man rechtzeitig abschneiden sollte ...?
Zitat:
|
Nicht wirklich. Oder sind auch automatisch alle Programmierer schuld, wenn eine Intel CPU einen Rechenfehler hat?
|
Darum geht es doch nicht. Du musst das aus Sicht des Endkunden betrachten: Wenn der feststellt, dass eine gerade von ihm gekaufte Anwendung nicht auf seinem Computer funktioniert, andere aber schon, wird er zuerst den Programmierer|Hersteller verantwortlich machen. Das liegt zum einen daran, dass er nicht erkennen kann, was die wirkliche Ursache ist und zum anderen am Hersteller der Software, weil nämlich die Konkurrenz sicher Workarounds in ihre Produkte eingebaut hat. Mag sein, dass der Prozessorhersteller die Kunden mit viel Aufwand und Medienrummel informiert und Rückrufaktionen gestartet hat. Vor den Endkunden hat er aber die Softwarehersteller informiert. Was glaubst du wohl warum?
Der Klassiker war hier der FDIV-Bug im Pentium (kann man in "Inside Intel" schön aufbereitet nachlesen"). Es gibt auch aktuelle Beispiele, wie das hier:
Glibc memcpy change exposing bugs : programming (und das "Improvement" dazu)
Mal abgesehen davon, sind heutzutage Prozessoren oft eingelötet. Die kannst du nur per Software-Workaround (BIOS, Betriebssystem, häufig benutzte Bibliothek, Anwendung) "fixen".
__________________
PHP-Code:
class Brick implements Throwable {
// ...
}
Geändert von fireweasel (27-03-2011 um 13:35 Uhr)
|
|
Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
|
|
|
| Themen-Optionen |
|
|
| Thema bewerten |
|
|
Forumregeln
|
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.
HTML-Code ist aus.
|
|
|
|
PHP News
|