Nový open source router Turris Omnia NG je v prodeji. Aktuálně na Allegro, Alternetivo, Discomp, i4wifi a WiFiShop.
Na YouTube a nově také na VHSky byly zveřejněny sestříhané videozáznamy přednášek z letošního OpenAltu.
Jednou za rok otevírá společnost SUSE dveře svých kanceláří široké veřejnosti. Vítáni jsou všichni, kdo se chtějí dozvědět více o naší práci, prostředí ve kterém pracujeme a o naší firemní kultuře. Letos se dveře otevřou 26. 11. 2025 v 16:00. Můžete se těšit na krátké prezentace, které vám přiblíží, na čem naši inženýři v Praze pracují, jak spolupracujeme se zákazníky, partnery i studenty, proč máme rádi open source a co pro nás skutečně
… více »Na čem pracují vývojáři webového prohlížeče Ladybird (GitHub)? Byl publikován přehled vývoje za říjen (YouTube).
Jeff Quast otestoval současné emulátory terminálu. Zaměřil se na podporu Unicode a výkon. Vítězným emulátorem terminálu je Ghostty.
Amazon bude poskytovat cloudové služby OpenAI. Cloudová divize Amazon Web Services (AWS) uzavřela s OpenAI víceletou smlouvu za 38 miliard USD (803,1 miliardy Kč), která poskytne majiteli chatovacího robota s umělou inteligencí (AI) ChatGPT přístup ke stovkám tisíc grafických procesů Nvidia. Ty bude moci využívat k trénování a provozování svých modelů AI. Firmy to oznámily v dnešní tiskové zprávě. Společnost OpenAI také nedávno
… více »Konference Prague PostgreSQL Developer Day 2026 (P2D2) se koná 27. a 28. ledna 2026. Konference je zaměřena na témata zajímavá pro uživatele a vývojáře. Příjem přednášek a workshopů je otevřen do 14. listopadu. Vítáme témata související s PostgreSQL či s databázemi obecně, a mohou být v češtině či angličtině.
Byl vydán Devuan 6 Excalibur. Přehled novinek v poznámkách k vydání. Kódové jméno Excalibur bylo vybráno podle planetky 9499 Excalibur. Devuan (Wikipedie) je fork Debianu bez systemd. Devuan 6 Excalibur vychází z Debianu 13 Trixie. Devuan 7 ponese kódové jméno Freia.
Společnost Valve aktualizovala přehled o hardwarovém a softwarovém vybavení uživatelů služby Steam. Podíl uživatelů Linuxu poprvé překročil 3 %, aktuálně 3,05 %. Nejčastěji používané linuxové distribuce jsou Arch Linux, Linux Mint a Ubuntu. Při výběru jenom Linuxu vede SteamOS Holo s 27,18 %. Procesor AMD používá 67,10 % hráčů na Linuxu.
Joel Severin v diskusním listu LKML představil svůj projekt linuxového jádra ve WebAssembly (Wasm). Linux tak "nativně" běží ve webovém prohlížeči. Potřebné skripty pro převod jsou k dispozici na GitHubu.
V dnešnej hádanke sa pozrieme na jednu vlastnosť spracovania POST v jazyku PHP.
Majme HTML formulár s niekoľkými inputmi:
<form action="/uloz.php" method="post" enctype="multipart/form-data"> Správa: <textarea name="sprava"></textarea><br /> Príloha: <input type="file" name="subor" /><br /> <input type="hidden" name="vec_id" value="1234" /> <input type="submit" value="Odoslať" /> </form>
Formulár sa metódou POST odosiela na server, kde ho PHP skript bez veľkých zmien uloží do databázy:
<?php $zaznam_id=uloz_zaznam(array( "vec_id"=>(int)$_POST["vec_id"], "sprava"=>$_POST["sprava"], )); uloz_prilohu($zaznam_id,$_FILES["subor"]);
Napriek tomu, že vec_id vo formulári je vždy predvyplnené správnym a validným číslom a používateľ ho nemá ako zmeniť, občas uloženie záznamu neprebehne:
INSERT INTO zaznamy (vec_id,sprava) VALUES (0,'Hotovo'); ERROR: insert or update on table "zaznamy" violates foreign key constraint "zaznamy_vec_id_fkey" DETAIL: Key (vec_id)=(0) is not present in table "veci".
Udeje sa teda to, že hodnota poľa vec_id niekde po ceste zmizne a formulár sa neuloží.
Kto prvý príde na to, čo sa tam naozaj deje? Nám to trvalo len desať rokov...
Update 6.4.2023 - doplnené hinty a riešenie:
Keď si na začiatku toho PHP skriptu nechám zalogovať $_POST, niekedy tam je len toto:
array(1) {
["sprava"]=>
string(5) "blaaa"
}
(tzn. vec_id sa tam vôbec nenachádza)
Ak nechám zalogovať aj $_FILES, v prípade chyby je tam vždy toto:
array(1) {
["subor"]=>
array(6) {
["name"]=>
string(11) "priloha.pdf"
["full_path"]=>
string(11) "priloha.pdf"
["type"]=>
string(0) ""
["tmp_name"]=>
string(0) ""
["error"]=>
int(3)
["size"]=>
int(0)
}
}
Dokumentácia k chybe uploadu číslo 3
Stane sa to, že sa upload preruší a PHP sa spustí nad nekompletnými dátami. Keďže parameter sprava ide ako prvý, ten prejde. Druhý parameter je upload súboru - ten je obvykle dlhší a dáva najviac priestoru na to, aby počas jeho prenosu došlo k ukončeniu spojenia. A skrytý parameter, ktorý má súbor zviazať s konkrétnym id v tabuľke (vec_id), sa pri prerušení spojenia už jednoducho neodošle.
Veľmi jednoducho - používateľ počas odosielania klikne niekam inam, prehliadač odosielanie zastaví a začne novú požiadavku. Alebo - a to je extra chrumkavé - nedočkavý používateľ znova klikne na tlačidlo "Odoslať". Tým sa prebiehajúci upload zastaví a začne odznova. To vysvetľuje, prečo sa pri skúmaní bugu zdalo, že uloženie prebehlo úspešne napriek chybe v logu. Uloženie naozaj prebehlo úspešne, ale na druhý pokus.
vec_id bolo na začiatku, dáta by sa uložili, aj keď bez súboru<form ...> ... <input type="hidden" name="naozaj_vsetko" value="1" /> </form>
<?php
if (!array_key_exists("naozaj_vsetko",$_POST)) {
http_response_code(400);
// nema ani zmysel posielat chybovu stranku, klient sa uz zo spojenia odpojil
die();
}
<input type="file" ... />, ale radšej nejakú javascriptovú knižnicu, ktorá upload spraví na pozadí metódou PUTNakoniec sa k riešeniu najbližšie dostal mirec (tu). Budem ho kontaktovať ohľadom vecnej ceny.
Tiskni
Sdílej:
CREATE TABLE veci ( id SERIAL NOT NULL, nazov VARCHAR NOT NULL, ... PRIMARY KEY (id) ); INSERT INTO veci (id, nazov) VALUES (1234, 'Divná chyba'); CREATE TABLE zaznamy ( id SERIAL NOT NULL, vec_id INT NOT NULL REFERENCES veci (id) ON UPDATE CASCADE ON DELETE CASCADE, sprava TEXT NOT NULL, ... PRIMARY KEY (id) ); CREATE INDEX zaznamy_vec_id ON zaznamy (vec_id); CREATE TABLE zaznam_prilohy ( id SERIAL NOT NULL, zaznam_id INT NOT NULL REFERENCES zaznamy (id) ON UPDATE CASCADE ON DELETE RESTRICT, nazov VARCHAR NOT NULL, cesta VARCHAR NOT NULL, ... PRIMARY KEY (id) ); CREATE INDEX zaznam_prilohy_zaznam_id ON zaznam_prilohy (zaznam_id);
$_POST["vec_id"] vraci prazdno, coz se pretypuje diky (int) na nulu?
Nicmene netusim, podeziram spis skript, co generuje HTML, ze uz tam ulozi spatnou hodnotu.
Pripadne se tam deji s _POST jeste jine operace, o kterych my ctenari nevime.
Škoda, že neviem čo obsahuje $_POST["vec_id"], takže neviem, či obsahuje garbage, je truncted, alebo nie je vôbec.
Možnosti, ktoré ma napadli:
Napriek tomu, že vec_id vo formulári je vždy predvyplnené správnym a validným číslom a používateľ ho nemá ako zmeniť
Jak nemá ako zmeniť? Tu hodnotu může v prohlížeči upravit (nebo poslat request jinak). Neposílá vám tam nějakej bot nějaký hovadiny?
array(1) {
["sprava"]=>
string(5) "blaaa"
}
(tzn. vec_id sa tam vôbec nenachádza)
Sekne všetko za uploadom pri chunked encodingu?
array(1) {
["subor"]=>
array(6) {
["name"]=>
string(11) "priloha.pdf"
["full_path"]=>
string(11) "priloha.pdf"
["type"]=>
string(0) ""
["tmp_name"]=>
string(0) ""
["error"]=>
int(3)
["size"]=>
int(0)
}
}
Odtiaľ už len treba dohľadať, čo znamená chyba číslo 3 a začne sa rozvidnievať...
/tmp?
Každopádně, ať už je ta chybá způsobená čímkoli, ten kód bych vyhodnotil jako nesprávný - neošetřuje chyby.
Tá hodnota chýba pretože je v requeste za súborom, takže pri postupnom čítaní sa už na ďalší argument nedostane. V tomto prípade by request nemal byť spracovaný vôbec.
Bingo! V jazyku PHP nie je kontrola, či prišiel celý POST request predtým, než sa začne vykonávať. Otázka je, či je to vôbec chyba a či to iné "webové" technológie majú inak.V zásadě to chyba není, ale jak říkám, tam je úplně špatně to API nad tím, kde data requestu taháš z nějakého globálního pole a musíš se dívat do nějakého jiného globálního pole, jestli tam náhodou není chyba... To je úplně blbě, správně by měl existovat nějaký objekt/struktura/whatever representující request a ten by měl zpřístupňovat různé vlastnosti, jako např. jestli request doběhl celý / nebyl přerušen a form data by zpřístupnil pouze, pokud je všechno v pořádku. IMO tvoje řešení v odstavci Ako proti tomu bojovať? je jenom takový hack, který neřeší podstatu problému, vůbec se mi to nelíbí, protože to zase spoléhá na nějaké řazení dat z HTML form. Je to pořadí vůbec garantované, nebo je to jenom nějaká konvence? Nehledě k tomu, že zas někdo může poslat request bez toho posledního políčka. Na to bych vůbec takhle nespoléhal. Měl bys IMO primárně především na začátku zkontrolovat proměnnou
$_FILES jestli tam není ta chyba. Ideálně bys měl napsat nějakou funkci nebo request API, které tuhle křehkou práci zabalí na jednom místě a poskytne bezpečné, chybově ošetřené API, k tomu případně připsat pořádně velký a strašidelný komentář varující člověka, aby si dobře rozmyslel změny v té funkci/API, protože jsou z toho pak tyhle blbě debugovatelný problémy.
A ve zbytku kódu už bys používal jen tuhle funkci/API a na ty debilní globální proměnný vůbec nešahal.
Nehledě k tomu, že zas někdo může poslat request bez toho posledního políčka.Oprava: Měl jsem na mysli, že může to pořadí přehodit.
Jaj prerušený upload
Inak sranda bola aj debugovanie password_verify keď pri zlom vstupe vracia true.
The documentation for `password_verify()` clearly states that the `$hash` has to be valid:
> hash
> A hash created by password_hash().
I fail to see how this is a bug if you feed it garbage; also the documentation to crypt states:
Crypt je inak tiež krásny modul ;)
Returns the hashed string or a string that is shorter than 13 characters and is guaranteed to differ from the salt on failure.
php var_dump(substr("a", 1));
bool(false)
Měli koule na to, aby i za cenu backward incompatibility to opravili už v Php 7 (poslední Php 5.6 ještě vrací false). Od Php 8 už vrací "" i index mimo rozsah, tedy třeba 2 na string délky 1. Což je s otazníkem - "normální" jazyky vyhodí exception, ale to je u Php nadstandard...
Ondřej Surý: "I fail to see how this is a bug if you feed it garbage"
Hackers everywhere: "Let's feed it garbage and see what happens..."
PHP: "Access granted."
Co jsem ti udělal, Ondřeji, že mě takhle trestáš? Pošlete ho někdo prosím na kurz základů počítačové bezpečnosti. Nebo radši na dva.
Z vtipných vlastností PHP typu to hádam nemôže byť pravda ešte vyberám:
Prečo majú PHP funkcie tak divné názvy?
Pretože hashovacia funkcia pre funkcie bola strlen. Preto aby boli hashe funkcí rozdelené rovnomerne museli mať názvy funkcií rovnomerné rozdelenie dĺžky.
Alebo vo verzii 7 a menej:
php > if (undefined) { echo "tadaa"; }
tadaa
Bez varovania iba s poznámkou. A teraz si predstavme kód plný niečoho takého:
define(ma_prava, array_key_exist(...)); ... if (ma_prava)
Všetko funguje krásne kým sa kódu nechytí niekto ďalší a nezabudne na define na vrchu.
Vo verzii 8 (3x hurá) to skončí aspoň chybou (alebo varovaním, že došlo k chybe? :D)
php > if (undefined) { echo "a"; }
PHP Warning: Uncaught Error: Undefined constant "undefined" in php shell code:1
Stack trace:
#0 {main}
thrown in php shell code on line 1
md5('240610708') == md5('QNKCDZO')
=> bool(true)
Ňuňuňu automatické pretypovanie na číslo.
Tu by som asi každému používateľovi PHP (programátorovi?) odporúčal všade používať ===. Problém je, že človek sa mýli a občas jeden znak zabudne.
Ako bývalého PHPčkára ma táto náchylnosť na chyby nesmierne unavovala. Skoro každá funkcia je nejakým spôsobom zle implementovaná z čoho vyplýva, že pri každom volaní si programátor musí prejsť corner casy a to neskutočne unavuje a je to náchylné na chyby.
$position=strpos($text, "something"); if($position=== false) return false;je asi programátorsky ľahšie ošetrenie podmienky ako:
errno=0; value=atoi(input); if(errno != 0) return -1;
Keď už tak tie príklady by mali byť aspoň ekvivalentné. Takže v C by to bolo:
char *found = strstr(text, "vyraz");
if (!found)
return ...
Alebo v druhom prípade ten prevod čísel:
if (!is_numeric($input)) {
return -1;
}
$value = (int)$input;
Bez explicitnej kontroly pretypovanie vráti 0 čo môže mať za následok neočakávané správanie aplikácie.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int number;
int result;
char buffer[100]={0};
fgets(buffer, 100, stdin);
result=sscanf(buffer, "%d", &number);
if(result == 1)
printf("Number %d.\n", number);
return 0;
}
Tu by som asi každému používateľovi PHP (programátorovi?) odporúčal všade používať ===. Problém je, že človek sa mýli a občas jeden znak zabudne.Já bych šel ještě dál a používal
====. Kdyby šlo do nejhoršího a bylo třeba porovnat extra těžké váhy, tak =====.