Aktuel situation: PHP2Shell. To kritiske PHP-sårbarheder (CVSS 9,2) tillader skadelig kode uden login. Rettelser siden 21.10.2026.Hvad der skal gøres nu →

memory_limit og out-of-memory: Hvad der sker indeni

Hvad sker der, når et PHP-script når memory_limit? Mekanikken, den nye hårde hukommelsesgrænse siden oktober-patchene og sammenhængen med CVE-2026-109618.

Status 5 min. læsetidPHP-viden

Kort sagt: En PHP out-of-memory-fejl opstår, når et script vil anmode om mere hukommelse, end indstillingen memory_limit tillader (standard: 128 MB pr. forespørgsel). PHP afbryder så forespørgslen med en fatal fejl og rydder op. Netop denne afbrydelses- og oprydningsvej var fejlbehæftet ved CVE-2026-109618, en af de to PHP2Shell-sårbarheder. Siden PHP 8.5.12, 8.4.27, 8.3.36 og 8.2.35 er memory_limit en blød grænse, suppleret af den hårde grænse memory_hard_limit_percent.

Hvad betyder »Allowed memory size exhausted«?

Den kendte fejlmeddelelse lyder i meningen: »Allowed memory size of 134217728 bytes exhausted (tried to allocate …)«. Det første tal er den indstillede grænse i bytes, her 128 MB. Et script har altså forsøgt at optage hukommelse ud over denne grænse, f.eks. ved indlæsning af en stor fil, en enorm databaseforespørgsel eller på grund af en uendelig løkke.

Vigtigt for beslutningstagere: Grænsen gælder pr. PHP-proces og pr. forespørgsel, ikke for hele serveren. Den beskytter serveren mod, at et enkelt fejlbehæftet script bruger al hukommelsen. Den samlede belastning fremkommer først af antallet af samtidigt kørende workers. Ved 20 PHP-FPM-workers med hver 256 MB grænse er det regnet ud over 5 GB.

Sådan tæller PHP hukommelse

PHP administrerer hukommelse til forespørgsler via en egen hukommelsesmanager, Zend Memory Manager. Den henter større blokke fra operativsystemet og fordeler dem internt til variabler, arrays og objekter. Mod denne reserverede værdi kontrollerer PHP memory_limit. Hukommelse, som en udvidelse anmoder om direkte hos operativsystemet, optræder ifølge manualen ikke i denne optælling.

I kan gøre værdierne synlige i koden:

<?php
echo memory_get_usage(), PHP_EOL;       // hukommelse, der aktuelt er optaget af scriptet
echo memory_get_usage(true), PHP_EOL;   // reserveret af hukommelsesmanageren; mod den kontrollerer memory_limit
$liste = range(1, 200000);
echo memory_get_peak_usage(), PHP_EOL;  // hidtidig spidsværdi
unset($liste);
memory_reset_peak_usage();              // nulstil spidsværdien, fra PHP 8.2

Hvordan referencetælling og garbage collection frigiver hukommelsen igen, forklarer siden Hukommelsesstyring i PHP.

Hvad der sker indeni ved out-of-memory

Forenklet forløber en hukommelsesafbrydelse i disse trin:

  1. Scriptet anmoder om hukommelse, for eksempel til et nyt array-element eller ved indlæsning af forespørgselsdata.
  2. Hukommelsesmanageren kontrollerer, om anmodningen overskrider grænsen.
  3. Er det tilfældet, udløser PHP en fatal fejl og forlader den igangværende behandling straks, også midt i en halvt udført opgave.
  4. Registrerede shutdown-funktioner kører endnu; med dem logger mange applikationer fejlen.
  5. Til sidst rydder PHP op efter forespørgslen og frigiver dens hukommelse. Workeren står derefter klar til den næste forespørgsel.

Det ømtålelige punkt er trin 5. Oprydningen skal kunne håndtere datastrukturer, der kun var halvt oprettet ved afbrydelsen. En almindelig hukommelsesafbrydelse gælder ifølge PHP-projektets sikkerhedspolitik ikke som sårbarhed, så længe grænsen afviser anmodningen, og kun den aktuelle forespørgsel slutter. Ved CVE-2026-109618 var netop denne forudsætning brudt: Ifølge php.net kunne out-of-memory-tilstanden afbryde PHP, mens interne forespørgselsdata kun var delvist initialiseret, og oprydningen behandlede så ugyldige data som gyldige. Detaljer om udnyttelsen offentliggør vi ikke; vurderingen af sårbarheden står under CVE-2026-109618.

Den nye bløde og hårde hukommelsesgrænse

Med sikkerhedsudgivelserne af 21.10.2026 har PHP-projektet ændret adfærden. Ifølge manualen er memory_limit siden da en blød grænse: En anmodning, der overskrider den, må i de fleste tilfælde stadig afsluttes, før den fatale fejl følger. En separat hård grænse begrænser, hvor langt det må gå.

Direktiv Standard Kan ændres Betydning
memory_limit 128M INI_ALL Hukommelsesgrænse pr. forespørgsel, -1 = ingen grænse
memory_hard_limit_percent ikke sat INI_ALL Hård grænse i procent af memory_limit, ny siden 8.5.12, 8.4.27, 8.3.36, 8.2.35
post_max_size 8M INI_PERDIR Maksimal størrelse af POST-data
upload_max_filesize 2M INI_PERDIR Maksimal størrelse af en uploadet fil

Et eksempel fra manualen: Ved memory_limit=128M og memory_hard_limit_percent=150 ligger den hårde grænse på 192 MB. Manualen nævner samtidig direktivet som kendetegn: Kender en PHP-version det ikke, er den berørt af CVE-2026-109618 og CVE-2026-109619. En hurtig test for hver installeret PHP-version:

php -r 'var_dump(ini_get("memory_hard_limit_percent"));'
# bool(false) betyder: direktivet er ukendt

Ved pakker fra distributioner med backport forbliver pakkens changelog det afgørende bevis, som beskrevet under Kontrollér PHP-version og patch-status rigtigt. Kontrollér desuden PHP-FPM-binæren separat, for den kan have en anden version end kommandolinjen.

Hukommelsesgrænser og PHP2Shell: Hvad administratorer nu skal være opmærksomme på

php.nets midlertidige foranstaltninger til CVE-2026-109618 drejer sig næsten alle om hukommelse og forespørgselsstørrelser. De mindsker risikoen, men erstatter ikke opdateringen:

; FPM-pool, f.eks. /etc/php/8.3/fpm/pool.d/www.conf
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M        ; 32M, hvis der er brug for uploads
php_admin_value[upload_max_filesize] = 6M  ; hold under post_max_size

Tre punkter er afgørende. For det første må ingen applikation, ingen mappe og ingen anden pool igen sætte en endelig grænse; php.net kræver udtrykkeligt denne kontrol. For det andet har en tjeneste med memory_limit=-1 brug for en grænse udefra, via container eller cgroup, ifølge php.net bedst sådan, at kun den berørte worker afsluttes. RLIMIT_AS og RLIMIT_DATA er ifølge php.net uegnede. For det tredje anbefaler php.net grænser ved webserveren eller proxyen for forespørgselsstørrelse, antal felter, multipart-dele, headere og indlejringsdybde.

Vigtigt

memory_limit=-1 uden hukommelsesgrænse udefra kan lægge en server fuldstændigt ned ved høj belastning. Sæt de midlertidige foranstaltninger kun som en samlet pakke og kun indtil opdateringen.

Hvordan I sætter grænsen med systemd, står under Sæt hukommelsesgrænser med systemd og cgroups; den varige løsning til hverdagen beskriver Sæt memory_limit rigtigt.

Hvordan hjælper PHP SOS konkret?

Via PHP-patchservicen går vi frem på denne måde:

  • Kontrollere beholdningen: Vi registrerer hver PHP-version på serveren, adskilt efter CLI, FPM og Apache-modul, og tester, om rettelsesversionen kører.
  • Ordne hukommelsesgrænser: Vi undersøger, hvor memory_limit overalt sættes, og indretter pool- og systemgrænser, så de passer sammen.
  • Sikre overgangen: Hvor opdateringen endnu er blokeret, sætter vi php.nets foranstaltninger fuldstændigt og spærret mod overskrivning.
  • Levere dokumentation: I får versioner, pakkestatus og konfiguration før og efter indgrebet skriftligt.

Ofte stillede spørgsmål

Hvad betyder meldingen »Allowed memory size exhausted«?

Et script ville anmode om mere hukommelse, end memory_limit tillader. PHP afbryder så den igangværende forespørgsel med en fatal fejl. Andre forespørgsler og selve serveren kører videre.

Gælder memory_limit for hele serveren?

Nej, grænsen gælder pr. PHP-proces og forespørgsel. Kører der 20 FPM-workers med hver 256 MB grænse, kan de teoretisk optage over 5 GB tilsammen. Den samlede grænse skal derfor sættes via poolstørrelse, systemd eller container.

Hvad er memory_hard_limit_percent?

Et nyt direktiv, som kom med PHP 8.5.12, 8.4.27, 8.3.36 og 8.2.35. Det sætter en hård grænse som procentværdi af memory_limit, der aldrig overskrides. memory_limit selv er siden da en blød grænse.

Beskytter memory_limit=-1 mod PHP2Shell?

Kun delvist. php.net nævner indstillingen som midlertidig foranstaltning mod CVE-2026-109618, udtrykkeligt uden fuldstændig beskyttelse. Den kræver ubetinget en hukommelsesgrænse udefra, og opdateringen forbliver et must.

Kilder

Akut kontakt

Hver time tæller. Skriv til os nu.

Beskriv kort system, PHP-version og observation. Vi vender tilbage, afklarer situationen og arbejder på afstand, indtil hændelsen er afsluttet og dokumenteret.

Akut hjælp