-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
Bug
The function readfileLowMemory() in htdocs/core/lib/functions.lib.php (line ~14464) flushes output buffers before
sending binary file content:
// Be sure we don't have output buffering enabled to have readfile working correctly
while (ob_get_level()) {
ob_end_flush();
}
ob_end_flush() sends any buffered content to the browser before the binary file data. If any PHP file loaded during
the request (module, conf, hook, etc.) has produced even a single byte of output (e.g., a space after a closing ?>
tag), that byte is prepended to the downloaded file, silently corrupting it.
Impact
- All binary file downloads via document.php are affected (images, PDFs, etc.)
- The corruption is silent: no error is shown, the file size appears correct (Content-Length is set from the original
file, but the browser receives extra bytes before the actual content) - A single stray whitespace in any included PHP file (custom module, conf.php, etc.) breaks every file download
- Images appear broken, PDFs won't open
Root cause example
A PHP file ending with ?>\x20 (closing tag + space) produces one byte of output. When document.php serves a file,
readfileLowMemory() flushes this byte before the binary content, shifting the entire file by one byte.
Suggested fix
Replace ob_end_flush() with ob_end_clean() to discard any stray buffered output instead of sending it:
while (ob_get_level()) {
ob_end_clean();
}
When serving a binary file, any previous PHP output is never intentional and should be discarded. This makes
document.php resilient to stray whitespace in third-party modules or configuration files.
Environment
- Dolibarr version: 22.0.0
- PHP version: 8.x
Dolibarr Version
22.0.4
Environment PHP
8.2
Environment Database
mariadb
Steps to reproduce the behavior and expected behavior
No response
Attached files
No response