Czy PHP wykonuje parsowanie pliku php.ini?

24

Uruchamianie PHP w wersji 7.1.30 pod RHEL 7.7.

Chcę podnieść limit pamięci, ale nie byłem pewien, czy mam poprawną składnię (tj. 256 MB lub 256 MB). Na początek wstawiłem złą wartość „Hugo” jako ustawienie memory_limit. Problem polega na tym, że phpinfo () (działający pod httpd) dosłownie ma łańcuch „Hugo” na swoim miejscu, tj .:

wprowadź opis zdjęcia tutaj

To mnie trochę martwi, że PHP tak naprawdę nie sprawdza poprawności wartości. (Jeśli podana wartość była zła, oczekiwałbym, że przywróci wartość domyślną, np.)

Czy ktoś może komentować na ten temat - w szczególności, skąd wiesz, czy PHP będzie wymuszać różne rzeczy (jeśli można podać dowolny ciąg znaków).

Patrick Rynhart
źródło
4
Doskonałe pytanie.
zadzwonić
3
Z tego: php.net/manual/en/faq.using.php#faq.using.shorthandbytes Zakładam, że jest taki sam jak (int) 'HUGO'; // => 0. Który zaczyna się nie powieść na moim komputerze przy 2 MB użytej pamięci.
Yoshi
@Yoshi Myślę, że powinieneś opublikować swoją odpowiedź. To dobre wytłumaczenie
Maksym Fiodorow
@MaksymFedorov Waham się, ponieważ nie mam prawdziwego odniesienia do mojego założenia. Na razie to tylko obserwacja.
Yoshi

Odpowiedzi:

19

Mylące jest tutaj to, że ustawienie wygląda jak liczba całkowita ze specjalną składnią, ale jest wewnętrznie zdefiniowane jako ciąg. Ciąg jest następnie analizowany w oddzielnej zmiennej globalnej za każdym razem, gdy wartość jest zmieniana. Co najważniejsze, wynik parsowania ciągu na liczbę całkowitą nie jest zapisywany z powrotem w tabeli ustawień, więc po wywołaniu phpinfo()zobaczysz oryginalne wejście, a nie przeanalizowaną wartość.

Możesz to zobaczyć w źródle:

Obsługiwana składnia jest ostatecznie zdefiniowana w zend_atol:

  1. analizuje ciąg znaków pod kątem wartości liczbowej, ignorując dodatkowy tekst
  2. patrzy na ostatniego znaku łańcucha, i mnoży wartość poprzedzający jeśli jest g, G, m, M, k, lubK

Wartość bez cyfr na początku zostanie przeanalizowana jako zero. Podczas ustawiania zmiennej globalnej ustawi to limit pamięci na minimum dozwolone, w oparciu o stałą ZEND_MM_CHUNK_SIZE.

Możesz zobaczyć efekt, ustawiając limit pamięci, a następnie uruchamiając pętlę, która szybko przydziela dużą ilość pamięci i sprawdzając, co pojawia się w komunikacie o błędzie. Na przykład:

# Invalid string; sets to compiled minimum
php -r 'ini_set("memory_limit", "HUGO"); while(true) $a[]=$a;'
# -> PHP Fatal error:  Allowed memory size of 2097152 bytes exhausted

# Number followed by a string; takes the number
php -r 'ini_set("memory_limit", "4000000 HUGO"); while(true) $a[]=$a;'
# -> PHP Fatal error:  Allowed memory size of 4000000 bytes exhausted

# Number followed by a string, but ending in one of the recognised suffixes
# This finds both the number and the suffix, so is equivalent to "4M", i.e. 4MiB
php -r 'ini_set("memory_limit", "4 HUGO M"); while(true) $a[]=$a;'
# -> PHP Fatal error:  Allowed memory size of 4194304 bytes exhausted
IMSoP
źródło
Dziękuję @IMSoP za tę wspaniałą ocenę. Czy należy zgłaszać tego rodzaju rzeczy w jakimkolwiek programie do wykrywania błędów? Uważam, że odpowiedź generowana przez phpinfo () jest wysoce sprzeczna z intuicją. I niektóre wyniki debugowania tego, co robi php, gdy napotka nieoczekiwane wartości, również nie pójdą nie tak.
zadzwonił
1
@tink Wydaje mi się, że możesz zgłosić żądanie funkcji na stronie bugs.php.net lub wysłać wiadomość na listę mailingową firmy Internals, gdzie odbywa się większość koordynacji. Znalazłem podobną prośbę sprzed kilku lat , ale wydaje się, że nie otrzymała żadnej odpowiedzi.
IMSoP
Jeszcze raz dziękuję, zajrzę do tego! :)
zadzwoń
0

Po pierwsze, najpierw musimy zrozumieć, jak działa PHP.ini w przepływie pracy interpretacji. memory_limit to wytyczne dla PHP.

używając funkcji PHP musisz zrobić coś takiego ini_set(‘memory_limit’,’256MB’). Ta funkcja tymczasowo ustawi wartość na zmienną interpretera. Jeśli przyjrzysz się bliżej, możesz uzyskać dwie kolumny. Jedna jest lokalna, a druga globalna. To pokazuje zdolność wartości odpowiednio do jednostki.

Ale jeśli zdefiniowałeś dla globalnego, musisz ustawić jako przyrostek odpowiednio K, M, G. Jeśli przekroczymy tę wartość za pomocą apache .htaccess, wymaga to tego samego dla PHP fpm.

Pranav Bhatt
źródło
3
Chciałbym zauważyć, że OP nie pyta, jak ustawić limit pamięci :)
Karolis