Die EDV-Stein­zeit mel­det sich

Neu­lich bin ich bei der Por­tie­rung eines PHP-Scripts von mei­nem Ent­wick­lungs-PC auf den Raspi fast ver­zwei­felt. Eine Ajax-Rou­ti­ne woll­te ein­fach nicht mehr funktionieren.

Nach län­ge­rem Debug­ging fand ich her­aus, dass es an einem schein­bar feh­len­den POST-Para­me­ter lag. Nur: auf dem PC funk­tio­nier­te die­ses Script ein­wand­frei, nur auf dem Raspi war der Para­me­ter leer.

Inhalt des frag­li­chen Para­me­ters ist eine EAN-Num­mer, die 8- oder 13-stel­lig ist, also theo­re­tisch zwi­schen 0 und 9.999.999.999.999 liegt.

Natür­lich vali­die­re ich alle Ajax-Para­me­ter brav mit der fil­ter_in­put-Funk­ti­on. Die EAN-Num­mer über­prü­fe ich mit dem FILTER_VALIDATE_INT Flag, also

$ean = filter_input(INPUT_POST, 'ean', FILTER_VALIDATE_INT);

Auf dem PC funk­tio­nier­te das pro­blem­los, nur auf dem Raspi lie­fer­te die Funk­ti­on immer fal­se zurück.

Auf die Spur des Pro­blems brach­ten mich die Optio­nen des Fil­ters, in denen man auch einen Min und Max Wert für die Fest­kom­ma­zahl set­zen kann.

Der Raspi selbst ist zwar seit Ver­si­on 3 auch 64-bit­tig, aber das Sys­tem läuft noch immer mit 32 bit,wenn man nicht aus­drück­lich das bis vor kur­zen noch im Beta-Sta­di­um befind­li­che 64bit-Sys­tem aus­wählt. Und damit sind für Inte­ger-Zah­len die Gren­zen anders als bei mei­nem PC, der natür­lich mit einem 64bit-Linux läuft.

PHP lie­fert selbst den Beweis mit den Kon­stan­ten PHP_INT_SIZE und PHP_INT_MAX. So sieht das bei einem 64bit-Sys­tem aus:

$ php -r "echo PHP_INT_SIZE;"
8
$ php -r "echo PHP_INT_MAX;"
9223372036854775807

Und so beim 32-bit­ti­gen Raspi-System:

$ php -r "echo PHP_INT_SIZE;"
4
$ php -r "echo PHP_INT_MAX;"
2147483647

PHP_INT_SIZE lie­fert die Grö­ße von Inte­ger-Zah­len in Byte, also 4 Byte beim 32- und 8 Byte beim 64bit-Sys­tem. PHP_INT_MAX gibt die größ­te dar­stell­ba­re Inte­ger-Zahl zurück, näm­lich 9.223.372.036.854.775.807 (also knapp zehn Tril­lio­nen) bei 64bit und nur 2.147.483.647 oder gut zwei Mil­li­ar­den bei 32 bit.

Da PHP kei­ne Unsi­gned Inte­ger kennt, fällt das Vozei­chen-Bit weg und der theo­re­tisch mit 32 bit dar­stell­ba­re Ganz­zahl-Wer­te­be­reich hal­biert sich sogar noch­mals um die Hälf­te, näm­lich von 4.294.967.295 (2³²-1) auf 2.147.483.647 (2³¹-1). Und das reicht für mei­ne 13-stel­li­gen EAN-Num­mer eben nicht mehr aus.

Nach­dem ich das erkannt hat­te, war die Abhil­fe rela­tiv ein­fach: die EAN-Num­mern müs­sen als String behan­delt wer­den. Wird das Fil­ter-Flag von FILTER_VALIDATE_INT auf FILTER_SANITIZE_SPECIAL_CHARS geän­dert, erscheint der Wert magi­scher­wei­se auch auf dem Raspi.

Da ich mit den EAN-Num­mer nicht rech­nen will, macht das String-For­mat kei­ne Pro­ble­me. Für die Vali­die­rung muss man sich aber eige­ne Gedan­ken machen, wenn man den String zum Bei­spiel in einem SQL-Befehl ver­wen­den will (pre­pa­re ist Pflicht!).

Pro­gram­mie­rer, die oft mit 8, 16 oder 32 bit­ti­gen SOCs zu tun haben, sind von die­sen Ein­schrän­kun­gen wenig über­rascht. Mich hat die­ser Rück­fall in die Com­pu­ter-Stein­zeit aber kalt erwischt und mich eini­ge Stun­den Lebens­zeit gekostet.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

drei × drei =