From e5fca6909eb89bffc71018e3cbab03d05799bb6f Mon Sep 17 00:00:00 2001 From: Jake Dallimore Date: Thu, 4 Apr 2024 11:44:32 +0800 Subject: [PATCH] MDL-81060 core: fix incorrect userquota usage in zip_packer This change reverts much of MDL-74641, removing the erroneous userquota checks from zip_packer. Now, during extraction, the zip_packer will exit with an error status when it encounters a file which is larger than its advertised size, and NOT when it determines the size of the extracted files have exceeded the userquota (which only applies to private files and which was used incorrectly here). It also reverts changes to the draftfiles_ajax.php file, restoring the original (pre-MDL-74641) error handling. --- lib/filestorage/zip_packer.php | 44 ++++++++++------------------------ repository/draftfiles_ajax.php | 6 +---- 2 files changed, 13 insertions(+), 37 deletions(-) diff --git a/lib/filestorage/zip_packer.php b/lib/filestorage/zip_packer.php index a982afae6a8..39cedfda4ae 100644 --- a/lib/filestorage/zip_packer.php +++ b/lib/filestorage/zip_packer.php @@ -451,17 +451,6 @@ class zip_packer extends file_packer { $done = 0; } - // Get user remaining space. - $areamaxbytes = FILE_AREA_MAX_BYTES_UNLIMITED; - $context = context::instance_by_id($contextid); - if (!has_capability('moodle/user:ignoreuserquota', $context)) { - // Get current used space for this user (private files only). - $fileareainfo = file_get_file_area_info($contextid, 'user', 'private'); - $usedspace = $fileareainfo['filesize_without_references']; - $areamaxbytes = (int) $CFG->userquota - $usedspace; - } - $totalsizebytes = 0; - foreach ($ziparch as $info) { // Notify progress. if ($progress) { @@ -472,8 +461,6 @@ class zip_packer extends file_packer { $size = $info->size; $name = $info->pathname; - $realfilesize = 0; - if ($name === '' or array_key_exists($name, $processed)) { //probably filename collisions caused by filename cleaning/conversion continue; @@ -500,18 +487,15 @@ class zip_packer extends file_packer { continue; } $content = ''; + $realfilesize = 0; while (!feof($fz)) { $content .= fread($fz, 262143); $realfilesize = strlen($content); // Current file size. - $totalsizebytes = strlen($content); - if ($realfilesize > $size || - ($areamaxbytes != FILE_AREA_MAX_BYTES_UNLIMITED && $totalsizebytes > $areamaxbytes)) { - $processed[0] = 'cannotunzipquotaexceeded'; - // Close and unset the stream and the content. - fclose($fz); - unset($content); - // Cancel all processes. - break(2); + + // More was read than was expected, which indicates a malformed/malicious archive. + // Break and let the error handling below take care of the file clean up. + if ($realfilesize > $size) { + break; } } fclose($fz); @@ -557,20 +541,16 @@ class zip_packer extends file_packer { $processed[$name] = 'Can not read file from zip archive'; // TODO: localise continue; } + $realfilesize = 0; while (!feof($fz)) { $content = fread($fz, 262143); $numofbytes = fwrite($fp, $content); $realfilesize += $numofbytes; // Current file size. - $totalsizebytes += $numofbytes; - if ($realfilesize > $size || - ($areamaxbytes != FILE_AREA_MAX_BYTES_UNLIMITED && $totalsizebytes > $areamaxbytes)) { - $processed[0] = 'cannotunzipquotaexceeded'; - // Close and remove the tmpfile. - fclose($fz); - fclose($fp); - unlink($tmpfile); - // Cancel all processes. - break(2); + + // More was read than was expected, which indicates a malformed/malicious archive. + // Break and let the error handling below take care of the file clean up. + if ($realfilesize > $size) { + break; } } fclose($fz); diff --git a/repository/draftfiles_ajax.php b/repository/draftfiles_ajax.php index e1c7a979a36..78e200d22ad 100644 --- a/repository/draftfiles_ajax.php +++ b/repository/draftfiles_ajax.php @@ -237,11 +237,7 @@ switch ($action) { return $result !== true; }); if (count($failed) > 0) { - if ($failed[0] == "cannotunzipquotaexceeded") { - $return->error = get_string($failed[0], 'repository'); - } else { - $return->error = get_string('cannotunzipextractfileerror', 'repository'); - } + $return->error = get_string('cannotunzipextractfileerror', 'repository'); die(json_encode($return)); }