Skip to content

Epic: ALERT w PHP i niespodziewane białe ekrany śmierci

by Mistrz Wu on Grudzień 22nd, 2008 Blip Facebook Flaker Twitter Wykop

Zacznę od tego, że problemu nie zdołałem rozwiązać, gdyż zwyczajnie brakowało mi czasu i nerwów. Zamiast tego, zrobiłem obejścia, które… no, działają. A dlaczego? Nie wiem. Może jakiś doświadczony czytelnik zostawi odpowiedź w komentarzu…

Tak więc onegdaj, podczas wesołej pracy z PHP, zdarzyło się kilka razy, że przy prostej i klarownej operacji na dobrze określonych wartościach, PHP rzucał białym ekranem śmierci, a w logach pojawiało się niejasne:

ALERT - canary mismatch on efree() - heap overflow detected (attacker '127.0.0.1', file '/home/mcv/htdocs/cośtam/dispatch.php')

Czasami tylko zamiast efree było erealloc.

Chwila kombinowania wykazała, że taki efekt daje następująca linia:

$ids = array_merge ($this->f1(), $this->f2(), $this->f3());

Nazwy metod zostały zmienione dla większej czytelności. Wartości zwracane przez metody były najzwyklejszymi, PHP-owymi tablicami zawierającymi jedynie liczby całkowite. Liczba? Na pewno nie większa niż około 5800 w sumie. 5800 intów to dużo czy jak?

Po straceniu stosownej ilości nerwów, wpadłem na to, żeby trochę PHP-a oszukać. Dodałem zmienne pomocniczne:

$a = $this->f1();
$b = $this->f2();
$c = $this->f3();
$ids = array_merge ($a, $b, $c);

Magia! Wszystko zaczęło działać. Czy PHP znowu coś przede mną ukrywa?

W międzyczasie Pan Google pomógł skojarzyć dziwne wpisy w logach z „utwardzaczem” PHP, tj. Suhosinem, który ma za zadanie uodparniać dziurawego PHP na różne ataki włamywaczy. I niestety tylko tyle. Trop się urwał, a ja nie wnikałem, skoro obejście zadziałało. Pewnie coś z parserem PHP nie tak (jak zwykle), albo Suhosin narobił jakiegoś bałaganu. Łorewer.

Kilka dni później, po dodaniu nowego argumentu do zupełnie innej metody:

ALERT - canary mismatch on efree() - heap overflow detected (attacker '127.0.0.1', file '/home/mcv/htdocs/cośtam/dispatch.php')

Co? Że jak? Niniejszy kod:

public function render ($partial_name, array $locals = array())
{ … }

zastąpiłem nastepującym:

public function render ($partial_name, array $locals = array(), array $options = array())
{ … }

Od tej pory biały ekran śmierci (+wpis w logu) powodowały wszelkie możliwe rodzaje wywołań:

$this->render ('xyz');
$this->render ('xyz', array ('var' => 'value'));
$this->render ('xyz', array ('var' => 'value'), array());
# itp.

Znów zacząłem tracić czas i nerwy, aż w końcu dobra dusza Zergu zasugerował, żebym zrobił to samo co ostatnio. Chwila szukania w pamięci dała poniższy efekt.

function render ($partial_name, array $locals = array(), array $options = array())
{
    $this->render_old ($partial_name, $locals, $options);
}

function render_old ($partial_name, array $locals = array(), array $options = array())
{ … }

Magia, proszę Państwa! Działa! Nigdy nie lekceważcie potęgi nic-nie-robiącej funkcji opakowującej. Ani niepotrzebnych zmiennych tymczasowych. Bo mogą jednak okazać się potrzebne. A może ktoś zna wytłumaczenie dla tego bezsensownego zachowania PHP? Bo ja tego zupełnie nie rozumiem. Ale wiem już, że gdy zobaczę czyjś kod podobny do powyższego, to wcale nie z programisty będę się śmiał, a z czego innego… :^)

Dobranoc państwu i Wesołych Świąt.

Brak podobnych wpisów.

From → PHP

One Comment
  1. prodeus permalink

    ten kod, ktory zmieniales wcale nie musial powodowac tych nadpisan buforow, to moze dziac sie juz gdzies wczesniej – komunikaty do logow zostaja wyswietlone w momencie gdy funkcja sprawdzajaca canary wykryje jakas nieprawidlowosc, czyli np. jakis bufor jest alokowany a wczesniej struktura heap (np. naglowek chunku) zostala czyms nadpisana i uszkodzona. proponuje zainstalowac nowsza wersje php jesli to nie pomoze pronouje zainstalowac starsza.

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS

Notify me of followup comments via e-mail. You can also subscribe without commenting.