From 29a396fe4e65882a8f7f2fe65a8039d3265aa5f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mudr=C3=A1k?= Date: Thu, 17 Sep 2020 11:37:54 +0200 Subject: [PATCH] MDL-69355 file: Do not attempt to set headers after output started It was found out that in certain situations there may be some content in to output handlers buffers. Let's allow that to happen given that: * default handler's buffer is not sent as a part of the file and an error is reported into the server log. * other handlers' buffer is sent with the assumption that it is required for the correct serving of the file. --- lib/filelib.php | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/filelib.php b/lib/filelib.php index fd0c43e4afd..ba2a4019134 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -2234,23 +2234,27 @@ function readfile_accel($file, $mimetype, $accelerate) { } } - if ($filesize > 10000000) { - // for large files try to flush and close all buffers to conserve memory - while(@ob_get_level()) { - if (!@ob_end_flush()) { - break; - } - } - } - - // Send this header after we have flushed the buffers so that if we fail - // later can remove this because it wasn't sent. header('Content-Length: ' . $filesize); if (!empty($_SERVER['REQUEST_METHOD']) and $_SERVER['REQUEST_METHOD'] === 'HEAD') { exit; } + while (ob_get_level()) { + $handlerstack = ob_list_handlers(); + $activehandler = array_pop($handlerstack); + if ($activehandler === 'default output handler') { + // We do not expect any content in the buffer when we are serving files. + $buffercontents = ob_get_clean(); + if ($buffercontents !== '') { + error_log('Non-empty default output handler buffer detected while serving the file ' . $file); + } + } else { + // Some handlers such as zlib output compression may have file signature buffered - flush it. + ob_end_flush(); + } + } + // send the whole file content if (is_object($file)) { $file->readfile();