Skip to content

Commit

Permalink
[BUGFIX] Fix corrupted JavaScript assets loaded by website users
Browse files Browse the repository at this point in the history
Website users loaded corrupted JavaScript assets for files generated by
EXT:vhs when EXT:vhs was in the middle of re-writing the contents of the
requested asset file. This happens because EXT:core
`GeneralUtility::writeFile()` isn't implemented in an atomic style
causing observers (such as visiting website users) to read incomplete
asset file contents. Incomplete JavaScript files likely cause syntax
errors when interpreted by the user's user-agent rendering front end
sites unable to reach JavaScript-based interactivity.

Fix the issue by (non-atomically) writing into a temporary file and
replacing the destination asset file with a single atomic `rename()`
operation instead. This ensures that observers of the destination asset
file either see the complete old contents or the complete new contents
but never any intermediate state of the asset content.

See: https://man7.org/linux/man-pages/man2/rename.2.html
See: https://github.com/TYPO3/typo3/blob/v10.4.37/typo3/sysext/core/Classes/Utility/GeneralUtility.php#L1835-L1861
  • Loading branch information
adamkoppede authored and NamelessCoder committed Dec 4, 2024
1 parent 3a4514f commit 0b648d4
Showing 1 changed file with 18 additions and 1 deletion.
19 changes: 18 additions & 1 deletion Classes/Service/AssetService.php
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,24 @@ protected function writeFile(string $file, string $contents): void
$signalSlotDispatcher->dispatch(__CLASS__, static::ASSET_SIGNAL, [&$file, &$contents]);
*/

GeneralUtility::writeFile($file, $contents, true);
$tmpFile = @tempnam(dirname($file), basename($file));
if ($tmpFile === false) {
$error = error_get_last();
$details = $error !== null ? ": {$error['message']}" : ".";
throw new \RuntimeException(
"Failed to create temporary file for writing asset {$file}{$details}",
1733258066
);
}
GeneralUtility::writeFile($tmpFile, $contents, true);
if (@rename($tmpFile, $file) === false) {
$error = error_get_last();
$details = $error !== null ? ": {$error['message']}" : ".";
throw new \RuntimeException(
"Failed to move asset-backing file {$file} into final destination{$details}",
1733258156
);
}
}

protected function mergeArrays(array $array1, array $array2): array
Expand Down

0 comments on commit 0b648d4

Please sign in to comment.