# memory_limit och Out-of-Memory: vad som händer inuti

> PHP Out of Memory begripligt förklarat: hur memory_limit räknar, vad som sker internt vid avbrott och vad det betyder för CVE-2026-109618 och era servrar.

Källa: https://phpsos.de/sv/php/out-of-memory/  
Aktualitet: 2026-10-25  
Leverantör: PHP SOS, PHP-nödhjälp och serversäkerhet. Omedelbar hjälp via WhatsApp: https://wa.me/491736494914?text=Hej%20PHP%20SOS%2C%20vi%20beh%C3%B6ver%20hj%C3%A4lp%20med%20v%C3%A5r%20PHP-server.%20F%C3%B6retag%3A%20%E2%80%A6%20Webbplats%3A%20%E2%80%A6

**Kort sagt:** Ett PHP-out-of-memory-fel uppstår när ett skript vill begära mer minne än inställningen `memory_limit` tillåter (standard: 128 MB per förfrågan). PHP avbryter då förfrågan med ett fatalt fel och städar upp. Just den här avbrotts- och städvägen var felaktig vid CVE-2026-109618, en av de två PHP2Shell-luckorna. Sedan PHP 8.5.12, 8.4.27, 8.3.36 och 8.2.35 är `memory_limit` en mjuk gräns, kompletterad med den hårda gränsen `memory_hard_limit_percent`.

## Vad betyder ”Allowed memory size exhausted”?

Det välkända felmeddelandet lyder ungefär: ”Allowed memory size of 134217728 bytes exhausted (tried to allocate …)”. Det första talet är den inställda gränsen i byte, här 128 MB. Ett skript har alltså försökt uppta minne utöver den gränsen, till exempel vid inläsning av en stor fil, en enorm databasfråga eller genom en oändlig loop.

Viktigt för beslutsfattare: Gränsen gäller per PHP-process och per förfrågan, inte för hela servern. Den skyddar servern från att ett enskilt felaktigt skript förbrukar allt minne. Totalbelastningen följer först av antalet workers som körs samtidigt. Med 20 PHP-FPM-workers med 256 MB gräns vardera blir det räknemässigt över 5 GB.

## Hur PHP räknar minne

PHP hanterar minne för förfrågningar via en egen minneshanterare, Zend Memory Manager. Den hämtar större block från operativsystemet och fördelar dem internt till variabler, arrayer och objekt. Mot det reserverade värdet kontrollerar PHP `memory_limit`. Minne som ett tillägg begär direkt från operativsystemet syns enligt manualen inte i den här räkningen.

Ni kan synliggöra värdena i koden:

```php
<?php
echo memory_get_usage(), PHP_EOL;       // minne som skriptet för tillfället har tagit
echo memory_get_usage(true), PHP_EOL;   // reserverat av minneshanteraren; mot detta kontrollerar memory_limit
$liste = range(1, 200000);
echo memory_get_peak_usage(), PHP_EOL;  // hittills högsta värde
unset($liste);
memory_reset_peak_usage();              // återställ högsta värdet, från PHP 8.2
```

Hur referensräkning och garbage collection frigör minnet igen förklarar sidan [Minneshantering i PHP](https://phpsos.de/sv/php/speicherverwaltung/).

## Vad som händer inuti vid out-of-memory

Förenklat går ett minnesavbrott till så här:

1. Skriptet begär minne, till exempel för ett nytt array-element eller vid inläsning av förfrågningsdata.
2. Minneshanteraren kontrollerar om begäran överskrider gränsen.
3. Är det fallet utlöser PHP ett fatalt fel och lämnar den pågående bearbetningen omedelbart, även mitt i en halvfärdig uppgift.
4. Registrerade shutdown-funktioner körs fortfarande; med dem loggar många applikationer felet.
5. I slutet städar PHP upp förfrågan och frigör dess minne. Workern står därefter redo för nästa förfrågan.

Den känsliga punkten är steg 5. Städningen måste kunna hantera datastrukturer som vid avbrottet bara var halvvägs uppbyggda. Ett vanligt minnesavbrott räknas enligt PHP-projektets säkerhetspolicy inte som säkerhetslucka så länge gränsen avvisar begäran och bara den aktuella förfrågan tar slut. Vid CVE-2026-109618 var just det antagandet brutet: Enligt php.net kunde out-of-memory-tillståndet avbryta PHP medan interna förfrågningsdata bara var delvis initialiserade, och städningen behandlade då ogiltiga data som giltiga. Detaljer om utnyttjandet publicerar vi inte; bedömningen av sårbarheten finns under [CVE-2026-109618](https://phpsos.de/sv/php2shell/cve-2026-109618/).

## Den nya mjuka och hårda minnesgränsen

Med säkerhetsreleaserna från den 21 oktober 2026 har PHP-projektet ändrat beteendet. Enligt manualen är `memory_limit` sedan dess en mjuk gräns: En begäran som överskrider den får i de flesta fall ändå slutföras innan det fatala felet följer. En separat hård gräns begränsar hur långt det får gå.

| Direktiv | Standard | Ändringsbar | Betydelse |
|---|---|---|---|
| `memory_limit` | 128M | INI_ALL | minnesgräns per förfrågan, `-1` = ingen gräns |
| `memory_hard_limit_percent` | inte satt | INI_ALL | hård gräns i procent av `memory_limit`, nytt sedan 8.5.12, 8.4.27, 8.3.36, 8.2.35 |
| `post_max_size` | 8M | INI_PERDIR | maximal storlek på POST-data |
| `upload_max_filesize` | 2M | INI_PERDIR | maximal storlek på en uppladdad fil |

Ett exempel från manualen: Med `memory_limit=128M` och `memory_hard_limit_percent=150` ligger den hårda gränsen på 192 MB. Manualen anger samtidigt direktivet som kännetecken: Känner en PHP-version inte till det är den drabbad av CVE-2026-109618 och CVE-2026-109619. Ett snabbt test för varje installerad PHP-version:

```bash
php -r 'var_dump(ini_get("memory_hard_limit_percent"));'
# bool(false) betyder: direktivet är okänt
```

För paket från distributioner med backport förblir paketets changelog det avgörande beviset, som beskrivet under [Kontrollera PHP-version och patchläge rätt](https://phpsos.de/sv/php2shell/php-version-pruefen/). Kontrollera dessutom PHP-FPM-binären separat, eftersom den kan ha en annan version än kommandoraden.

## Minnesgränser och PHP2Shell: vad administratörer bör tänka på nu

php.nets tillfälliga åtgärder för CVE-2026-109618 handlar nästan alla om minne och förfrågningsstorlekar. De minskar risken men ersätter inte uppdateringen:

```ini
; FPM-pool, t.ex. /etc/php/8.3/fpm/pool.d/www.conf
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M        ; 32M, om uppladdningar behövs
php_admin_value[upload_max_filesize] = 6M  ; håll under post_max_size
```

Tre punkter är avgörande. För det första får ingen applikation, ingen katalog och ingen annan pool sätta en ändlig gräns igen; php.net kräver uttryckligen den kontrollen. För det andra behöver en tjänst med `memory_limit=-1` en gräns utifrån, via container eller cgroup, enligt php.net bäst så att bara den drabbade workern avslutas. `RLIMIT_AS` och `RLIMIT_DATA` är enligt php.net olämpliga. För det tredje rekommenderar php.net gränser i webbservern eller proxyn för förfrågningsstorlek, antal fält, multipart-delar, headers och nästlingsdjup.

> **Viktigt:**
> `memory_limit=-1` utan minnesgräns utifrån kan lamslå en server helt vid hög belastning. Sätt de tillfälliga åtgärderna bara som paket och bara fram till uppdateringen.

Hur ni sätter gränsen med systemd står under [Minnesgränser med systemd och cgroups](https://phpsos.de/sv/blog/speichergrenzen-systemd-cgroups/); den varaktiga lösningen för vardagen beskriver [Sätt memory_limit rätt](https://phpsos.de/sv/blog/memory-limit-richtig-setzen/).

## Hur hjälper PHP SOS konkret?

Via [PHP-patchtjänsten](https://phpsos.de/sv/leistungen/php-patch-service/) går vi tillväga så här:

- **Kontrollera beståndet:** Vi registrerar varje PHP-version på servern, uppdelad på CLI, FPM och Apache-modul, och testar om den åtgärdade versionen körs.
- **Ordna minnesgränserna:** Vi kontrollerar var `memory_limit` sätts överallt och ställer in pool- och systemgränser så att de passar ihop.
- **Säkra övergången:** Där uppdateringen ännu är blockerad sätter vi php.nets åtgärder fullständigt och spärrade mot överskrivning.
- **Leverera bevis:** Ni får versioner, paketlägen och konfiguration före och efter ingreppet skriftligt.


## Vanliga frågor

**Vad betyder meddelandet ”Allowed memory size exhausted”?**  
Ett skript försökte begära mer minne än memory_limit tillåter. PHP avbryter då den pågående förfrågan med ett fatalt fel. Andra förfrågningar och själva servern fortsätter att köra.

**Gäller memory_limit för hela servern?**  
Nej, gränsen gäller per PHP-process och förfrågan. Kör 20 FPM-workers med 256 MB vardera kan de teoretiskt tillsammans uppta över 5 GB. Totalgränsen måste därför sättas via poolstorlek, systemd eller container.

**Vad är memory_hard_limit_percent?**  
Ett nytt direktiv som kom med PHP 8.5.12, 8.4.27, 8.3.36 och 8.2.35. Det sätter en hård gräns som procentvärde av memory_limit och som aldrig överskrids. memory_limit är sedan dess själv en mjuk gräns.

**Skyddar memory_limit=-1 mot PHP2Shell?**  
Bara delvis. php.net nämner inställningen som tillfällig åtgärd mot CVE-2026-109618, uttryckligen utan fullständigt skydd. Den kräver absolut en minnesgräns utifrån, och uppdateringen förblir ett krav.

## Källor

- [PHP-manualen: Core-inställningar (memory_limit, memory_hard_limit_percent)](https://www.php.net/manual/en/ini.core.php)
- [PHP-manualen: memory_get_usage()](https://www.php.net/manual/en/function.memory-get-usage.php)
- [php.net: Säkerhetsmeddelanden från 21 oktober 2026](https://www.php.net/)
