Konec v regulárním výrazu

Školení, která pořádám

Pokud v regulárním výrazu chcete strefit konec řetězce, použijete výraz $. Osobně jsem až donedávna nevěděl, že preg_match('~a$~', "a\n") platí také. V HTTP nebo SMTP hlavičkách má znak konce řádku speciální význam, takže pokud na tomto místě kontrolujete data (např. e-mailovou adresu nebo adresu pro HTTP přesměrování) funkcí preg_match, může dojít k problémům. Netvrdím, že přímo bezpečnostním, protože za znak konce řádku už nemůžete nic přidat, ale přesun části hlaviček do těla zprávy nemusí být také dvakrát příjemný. Tedy teoreticky by mohlo dojít i k bezpečnostním problémům – odsunutím hlavičky Content-Type by se klientovi nepředala informace o kódování a pokud by klient v tom případě použil jiné kódování, byl by kód náchylný ke XSS i pokud by všechna data byla ošetřena funkcí htmlspecialchars, ovšem s jiným kódováním.

Uvedené chování je možno potlačit modifikátorem D nebo použitím \z místo $. Připomínám, že modifikátor m způsobí, že $ strefí kromě konce řetězce také každý konec řádku.

Jakub Vrána, Výuka, 9.5.2007, diskuse: 10 (nové: 0)

Diskuse

ikona error414:

Ja cetl "Konec regularnich vyrazu". Az na konci jsm si uvedomil spravny nazev. HUH

Dero:

V Perlových regulárech (nevím, jak v POSIX) existuje vychytávka, u které modifikátor D není třeba využít.

Pro skutečný konec řetězce lze využít metaznak \z (inverzní funkci má \Z), pro jeho skutečný začátek (neboť ^ taky není úplně bezpečné) zase \a (inverzní fce \A).

Pak můžeš testovat zečátek/konec řetězce bez ohledu na znak nového řádku nebo na modifikátor m.

ikona Jakub Vrána OpenID:

Díky za tip, doplnil jsem to do článku. Co myslíš tím, že "^ taky není úplně bezpečné"? Jenom chování s modifikátorem m?

Dero:

Ano, s modifikátorem m strefí ^ i začátek nového řádku, \a nikoliv.

Gringo:

Inverzní fce? Kde se to používá, tohle neznám...

Dero:

To je jednoduché, tento metaznak bude vyhodnocen kladně jen pokud nenastal konec/začátek celého řetězce.

Takže RegExpu /test\Z/ vyhoví třeba řetězec "test lidské hlouposti", ale už ne "to je mi tedy test".

Marek:

Uvedený příklad nefunguje (testu vyhovuji oba, se "z" i "Z"). V manuálu se píše:

\Z - end of subject or newline at end (independent of multiline mode)
\z - end of subject (independent of multiline mode)

Tedy až pokud by za řetězcem "to je mi tedy test" nasledoval novy radek, "z" neprojde, ale "Z" ano.

ikona Jakub Vrána OpenID:

Dero to trochu popletl. Ve skutečnosti to je takhle:

\a znak 0x07
\A začátek řetězce
\z konec řetězce
\Z konec řetězce nebo \n před koncem

Dero:

Ano, omlouvám se, nějak se mi to v hlavě pomíchalo. Specifikace mluví jasně, totiž přesně tak, jak píše Jakub.

Ondrej Ivanic:

Este dalsie info k teme: http://www.php-security.org/MOPB/PMOPB-45-2007.html

Ja este pouzivam pred validaciou trim() a az nasledne preg_match() s modifikatorom D. S \z a \a som este nepouzil, mozno sa mi zapacia. trim() som sa naucil pouzivat az potom ked som cistil jednu rozsiahlu databazu od zbytocnych whitespaces... :)

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2018 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.