# Setting memory_limit Correctly

> Set PHP memory_limit correctly: what the value does, where it applies, what php.net advises for PHP2Shell for now and what should apply after the update.

Source: https://phpsos.de/en/blog/memory-limit-richtig-setzen/  
As of: 25/10/2026  
Provider: PHP SOS, PHP emergency help and server security. Immediate help via WhatsApp: https://wa.me/491736494914?text=Hello%20PHP%20SOS%2C%20we%20need%20help%20with%20our%20PHP%20server.%20Company%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**In short:** `memory_limit` defines how much memory a single PHP request may use; the default is 128M. In normal operation, set a finite value that suits the application and lock it with `php_admin_value`. As long as PHP2Shell is not patched, php.net temporarily advises `memory_limit=-1`, non-overridable and combined with a limit via container or cgroup, not via `RLIMIT_AS` or `RLIMIT_DATA`. After the update, a finite value applies again.

## A routine setting that is suddenly a security topic

For years, `memory_limit` was a tuning knob for developers. If a website reports “Allowed memory size exhausted”, the value is raised and the problem is solved. With PHP2Shell this has become a security question, and php.net's recommendation looks paradoxical at first glance: for the interim, PHP's own memory limit is to be dropped entirely.

The background is CVE-2026-109618. According to the PHP project, an out-of-memory condition can interrupt PHP while request data is only partially initialized. Cleaning up the request can then treat invalid data as valid. Technical details are under [CVE-2026-109618](https://phpsos.de/en/php2shell/cve-2026-109618/); what happens inside PHP when memory runs out is explained in [memory_limit and out-of-memory](https://phpsos.de/en/php/out-of-memory/). For operators, the question is: which value applies when, and where must it be set?

## What memory_limit does in normal operation

According to the PHP manual, `memory_limit` limits the memory a script may use and thus protects the server from badly written code. The default is `128M`; `-1` means no limit. Shorthand such as `256M` or `1G` is allowed.

Two properties matter for security. First, the value can be changed anywhere, even at runtime with `ini_set()`. Many CMS and shops raise it themselves, for example for imports or image processing. Anyone who wants to enforce a value must set it with `php_admin_value`; according to the manual, values set this way cannot be overridden with `ini_set()`. Second, the manual recommends that `memory_limit` be larger than `post_max_size`.

Which value fits depends on the application. A look at the error log shows whether messages about exhausted memory occur and on which requests. It has proven worthwhile to define the value per website in its own FPM pool: more generous for a shop with imports, tighter for a simple company site. A blanket very high value for all websites wastes the protective effect, because a single faulty or abused request can then tie up a lot of memory.

Since PHP 8.5 there is also `max_memory_limit`. This setting can only be set at startup and limits how high `memory_limit` may be set at all. Higher values are capped with a warning. The default `-1` means no upper limit.

## memory_limit after PHP2Shell: the interim measure from php.net

For servers not yet updated to 8.5.12, 8.4.27, 8.3.36 or 8.2.35 or a confirmed backport, php.net names the following steps in the security announcement of 21 October 2026. They reduce the risk of individual attack paths but, according to php.net, do not make an installation safe:

1. **Set `memory_limit=-1`,** if possible so that applications cannot override the value, for example with `php_admin_value` in the FPM pool or in the Apache configuration.
2. **Check that no finite limit is set again anywhere,** neither in another pool, nor in a directory configuration, nor in the application.
3. **Set a memory limit via container or cgroup,** to protect availability, if possible so that only the affected worker is terminated when it is exceeded.
4. **Do not use `RLIMIT_AS` or `RLIMIT_DATA`.** According to php.net, these limits can trigger exactly the vulnerable error during memory allocation.

php.net explains that `-1` removes the ability to trigger the PHP memory limit on purpose, but that a memory error at a lower level can still reach the vulnerable path. The overview of all interim measures is under [Immediate measures if you cannot patch yet](https://phpsos.de/en/php2shell/sofortmassnahmen-ohne-patch/).

```ini
; FPM pool, e.g. /etc/php/8.3/fpm/pool.d/www.conf (only until the update)
php_admin_value[memory_limit] = -1
```

```bash
# Everywhere memory_limit is set (read-only)
grep -rn 'memory_limit' /etc/php/ /etc/apache2/ 2>/dev/null
grep -rn --include='*.php' -E "ini_set\s*\(\s*['\"]memory_limit" /var/www | head -20
grep -rn --include='.user.ini' 'memory_limit' /var/www
```

How to set the cgroup limit for the FPM service is described in [Setting memory limits with systemd and cgroups](https://phpsos.de/en/blog/speichergrenzen-systemd-cgroups/). Without this outer limit, a single request can push the whole server into a memory shortage.

> **Important:**
> Restart all PHP workers after every change. A running worker keeps its old values.

## What applies after the update

With the fixed versions, the behavior of `memory_limit` has also changed according to the PHP manual. From 8.5.12, 8.4.27, 8.3.36 and 8.2.35 it is a soft limit: a memory request that exceeds it may in most cases still be completed before the error is triggered. A new setting, `memory_hard_limit_percent`, defines a hard limit that is never exceeded.

| Setting | Value | Effect according to the manual |
|---|---|---|
| `memory_hard_limit_percent` not set or `-1` | default | hard limit twice as high as `memory_limit` up to 1G, above that `memory_limit` plus 1G |
| `memory_hard_limit_percent = 150` | example | with `memory_limit=128M` hard limit 192M |
| `memory_limit = -1` | no limit | then there is no hard limit either |

The manual names a practical checkpoint: if `memory_hard_limit_percent` is not recognized, the PHP version in use is affected and must be updated. For distribution backports, additionally check the status via the package changelog.

```bash
# Does the FPM binary know the new setting? (adjust the version number)
php-fpm8.3 -i | grep -E 'memory_hard_limit_percent|memory_limit'
```

After the update, `memory_limit=-1` has served its purpose. Return to a finite value that suits the application, and lock it with `php_admin_value`. The cgroup limit can remain as an additional layer of protection.

## How does PHP SOS help?

- We determine where `memory_limit` is set and overridden on your server, including in applications.
- We implement php.net's interim measures in the right place and add a cgroup limit for the FPM service.
- Through the [PHP patch service](https://phpsos.de/en/leistungen/php-patch-service/) we bring PHP to a fixed version and restart all workers.
- Afterwards we set a suitable finite value again and document the settings.


## Frequently asked questions

**What is the default value of memory_limit?**  
According to the PHP manual, 128M. The value limits how much memory a single script may use. It can be changed in php.ini, in the server configuration, in the FPM pool and at runtime with ini_set(), unless it is locked with php_admin_value.

**Why does php.net advise memory_limit=-1 for PHP2Shell?**  
One of the vulnerabilities, CVE-2026-109618, is related to the state when memory runs out. According to php.net, memory_limit=-1 removes the ability to trigger the PHP memory limit on purpose, but not every memory error. The measure is not complete protection and must be combined with a memory limit via container or cgroup.

**May I set the limit with ulimit instead?**  
No. php.net expressly advises against using RLIMIT_AS or RLIMIT_DATA as a substitute, because these limits can trigger exactly the vulnerable error during memory allocation. A limit via container or cgroup is recommended.

**What applies after the update to a fixed PHP version?**  
According to the manual, in the fixed versions memory_limit is a soft limit, supplemented by a hard limit via memory_hard_limit_percent. The interim measure with -1 has then served its purpose, and a finite value that suits the application should apply again.

## Sources

- [php.net: Security announcement of 21 October 2026](https://www.php.net/)
- [PHP manual: Core settings (memory_limit)](https://www.php.net/manual/en/ini.core.php)
- [PHP manual: FPM configuration](https://www.php.net/manual/en/install.fpm.configuration.php)
