Commit e0c0b982 authored by Tizian Schmidlin's avatar Tizian Schmidlin Committed by Christian Kuhn
Browse files

[BUGFIX] Ensure uniqid calls use more_entropy

Precision of `uniqid()` on Windows systems without passing
`$more_entropy=true` has only single-second-resolution which will
lead to non-unique ids on subsequent calls.

In order to mitigate this issue TYPO3 provides the function
`StringUtility::getUniqueId($prefix = '')` which calls
`uniqid()` with parameter `$more_entropy` always set to true.

Using `uniqid()`, especially with `$more_entropy` set to true,
is quite slow, but for the purposes TYPO3 is using it
(i.e. creating unique field names for backend forms, path
identifiers in some modules etc.) it is good enough and
another solution would not provide any measurable benefit.

Resolves: #91553
Releases: master, 10.4
Change-Id: Ib4443e72621eee6df2daf5bf23054e1a01325783
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/64652


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: default avatarJörg Bösche <typo3@joergboesche.de>
Tested-by: default avatarAlexander Schnitzler <git@alexanderschnitzler.de>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: default avatarJörg Bösche <typo3@joergboesche.de>
Reviewed-by: default avatarAlexander Schnitzler <git@alexanderschnitzler.de>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent d2d11699
......@@ -24,6 +24,7 @@ use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Adminpanel\Controller\MainController;
use TYPO3\CMS\Adminpanel\Utility\StateUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
/**
* PSR-15 Middleware to initialize the admin panel
......@@ -45,7 +46,7 @@ class AdminPanelInitiator implements MiddlewareInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if (StateUtility::isActivatedForUser() && StateUtility::isOpen()) {
$request = $request->withAttribute('adminPanelRequestId', substr(md5(uniqid('', true)), 0, 13));
$request = $request->withAttribute('adminPanelRequestId', substr(md5(StringUtility::getUniqueId()), 0, 13));
$adminPanelController = GeneralUtility::makeInstance(
MainController::class
);
......
......@@ -33,6 +33,7 @@ use TYPO3\CMS\Core\Service\DependencyOrderingService;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\HttpUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
/**
......@@ -264,7 +265,7 @@ class NewContentElementController
// Go to DataHandler directly instead of FormEngine
if ($wInfo['saveAndClose'] ?? false) {
$urlParams = [];
$id = uniqid('NEW');
$id = StringUtility::getUniqueId('NEW');
parse_str($wInfo['params'], $urlParams);
$urlParams['data']['tt_content'][$id] = $urlParams['defVals']['tt_content'] ?? [];
$urlParams['data']['tt_content'][$id]['colPos'] = $this->colPos;
......
......@@ -46,6 +46,7 @@ use TYPO3\CMS\Core\Site\Entity\Site;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3Fluid\Fluid\View\ViewInterface;
......@@ -364,7 +365,7 @@ class SiteConfigurationController
$this->siteFinder->getSiteByIdentifier($identifier);
// Force this identifier to be unique
$originalIdentifier = $identifier;
$identifier = $identifier . '-' . str_replace('.', '', uniqid((string)random_int(0, mt_getrandmax()), true));
$identifier = StringUtility::getUniqueId($identifier . '-');
$message = sprintf(
$languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:validation.identifierRenamed.message'),
$originalIdentifier,
......
......@@ -223,7 +223,7 @@ class SelectCheckBoxElement extends AbstractFormElement
if (is_array($group['header'])) {
$html[] = '<div id="' . $groupIdCollapsible . '" class="panel-collapse collapse" role="tabpanel">';
}
$checkboxId = uniqid($groupId);
$checkboxId = StringUtility::getUniqueId($groupId);
$title = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.toggleall'));
$html[] = '<div class="table-responsive">';
$html[] = '<table class="table table-transparent table-hover">';
......
......@@ -19,6 +19,7 @@ use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException;
use TYPO3\CMS\Backend\Routing\Route;
use TYPO3\CMS\Backend\Routing\Router;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
/**
......@@ -107,6 +108,6 @@ class UriBuilderTest extends UnitTestCase
$this->expectException(RouteNotFoundException::class);
$this->expectExceptionCode(1476050190);
$subject = new UriBuilder(new Router());
$subject->buildUriFromRoute(uniqid('any'));
$subject->buildUriFromRoute(StringUtility::getUniqueId('any'));
}
}
......@@ -44,6 +44,7 @@ use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Service\DependencyOrderingService;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\PharStreamWrapper\Behavior;
use TYPO3\PharStreamWrapper\Interceptor\ConjunctionInterceptor;
use TYPO3\PharStreamWrapper\Interceptor\PharMetaDataInterceptor;
......@@ -75,7 +76,7 @@ class Bootstrap
ClassLoader $classLoader,
bool $failsafe = false
): ContainerInterface {
$requestId = substr(md5(uniqid('', true)), 0, 13);
$requestId = substr(md5(StringUtility::getUniqueId()), 0, 13);
static::initializeClassLoader($classLoader);
if (!Environment::isComposerMode() && ClassLoadingInformation::isClassLoadingInformationAvailable()) {
......
......@@ -25,6 +25,7 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
/**
* Standard graphical functions
......@@ -1934,7 +1935,7 @@ class GraphicalFunctions
public function randomName()
{
GeneralUtility::mkdir_deep(Environment::getVarPath() . '/transient/');
return Environment::getVarPath() . '/transient/' . md5(uniqid('', true));
return Environment::getVarPath() . '/transient/' . md5(StringUtility::getUniqueId());
}
/**
......@@ -2556,7 +2557,7 @@ class GraphicalFunctions
if (($type === 'IM' || !$type) && $gfxConf['processor_enabled'] && $gfxConf['processor_path_lzw']) {
// Use temporary file to prevent problems with read and write lock on same file on network file systems
$temporaryName = PathUtility::dirname($theFile) . '/' . md5(uniqid('', true)) . '.gif';
$temporaryName = PathUtility::dirname($theFile) . '/' . md5(StringUtility::getUniqueId()) . '.gif';
// Rename could fail, if a simultaneous thread is currently working on the same thing
if (@rename($theFile, $temporaryName)) {
$cmd = CommandUtility::imageMagickCommand(
......
......@@ -83,6 +83,7 @@ use TYPO3\CMS\Core\Resource\Service\FileProcessingService;
use TYPO3\CMS\Core\Utility\Exception\NotImplementedMethodException;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
/**
* A "mount point" inside the TYPO3 file handling.
......@@ -2624,7 +2625,7 @@ class ResourceStorage implements ResourceStorageInterface
if ($a <= $maxNumber) {
$insert = '_' . sprintf('%02d', $a);
} else {
$insert = '_' . substr(md5(uniqid('', true)), 0, 6);
$insert = '_' . substr(md5(StringUtility::getUniqueId()), 0, 6);
}
$theTestFile = $theTempFileBody . $insert . $theOrigExt;
// The destinations file
......
......@@ -26,6 +26,7 @@ use TYPO3\CMS\Core\Resource\Search\QueryRestrictions\FolderMountsRestriction;
use TYPO3\CMS\Core\Resource\Search\QueryRestrictions\FolderRestriction;
use TYPO3\CMS\Core\Resource\Search\QueryRestrictions\SearchTermRestriction;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
/**
* Represents an SQL query to search for files.
......@@ -116,7 +117,7 @@ class FileSearchQuery
. preg_replace(
'/[^a-z0-9]/',
'',
uniqid($tableName . $fieldName, true)
StringUtility::getUniqueId($tableName . $fieldName)
)
]),
true
......
......@@ -18,6 +18,7 @@ namespace TYPO3\CMS\Core\Utility\File;
use TYPO3\CMS\Core\Charset\CharsetConverter;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
/**
* Contains class with basic file management functions
......@@ -107,7 +108,7 @@ class BasicFileUtility
$insert = '_' . sprintf('%02d', $a);
} else {
// .. then we try unique-strings...
$insert = '_' . substr(md5(uniqid('', true)), 0, $this->uniquePrecision);
$insert = '_' . substr(md5(StringUtility::getUniqueId()), 0, $this->uniquePrecision);
}
$theTestFile = $theTempFileBody . $insert . $theOrigExt;
$theDestFile = $theDest . '/' . $theTestFile;
......
......@@ -79,11 +79,11 @@ class SvgIconProviderTest extends UnitTestCase
*/
public function getIconWithInlineOptionReturnsCleanSvgMarkup()
{
$testFile = GeneralUtility::tempnam(uniqid('svg_') . '.svg');
$testFile = GeneralUtility::tempnam('svg_', '.svg');
$this->testFilesToDelete[] = $testFile;
$svgTestFileContent = '<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#CD201F" d="M11 12l3-2v6H2v-6l3 2 3-2 3 2z"></path><script><![CDATA[ function alertMe() {} ]]></script></svg>';
file_put_contents($testFile, $svgTestFileContent);
$this->testFilesToDelete[] = GeneralUtility::tempnam(uniqid('svg_') . '.svg');
$this->testFilesToDelete[] = GeneralUtility::tempnam('svg_', '.svg');
$this->subject->prepareIconMarkup($this->icon, ['source' => $testFile]);
self::assertEquals('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#CD201F" d="M11 12l3-2v6H2v-6l3 2 3-2 3 2z"/></svg>', $this->icon->getMarkup(SvgIconProvider::MARKUP_IDENTIFIER_INLINE));
}
......
......@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Fluid\Core\Widget;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\CMS\Extbase\Security\Cryptography\HashService;
use TYPO3\CMS\Fluid\Core\Widget\Exception\WidgetContextNotFoundException;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
......@@ -92,7 +93,7 @@ class AjaxWidgetContextHolder implements SingletonInterface
*/
public function store(WidgetContext $widgetContext)
{
$ajaxWidgetId = md5(uniqid(random_int(0, mt_getrandmax()), true));
$ajaxWidgetId = md5(StringUtility::getUniqueId());
$widgetContext->setAjaxWidgetIdentifier($ajaxWidgetId);
$this->widgetContexts[$ajaxWidgetId] = $widgetContext;
$this->storeWidgetContexts();
......
......@@ -23,6 +23,7 @@ use TYPO3\CMS\Core\Resource\FileReference as CoreFileReference;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Resource\Security\FileNameValidator;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\CMS\Extbase\Domain\Model\AbstractFileFolder;
use TYPO3\CMS\Extbase\Domain\Model\FileReference as ExtbaseFileReference;
use TYPO3\CMS\Extbase\Error\Error;
......@@ -243,8 +244,8 @@ class UploadedFileReferenceConverter extends AbstractTypeConverter
$fileReference = $this->resourceFactory->createFileReferenceObject(
[
'uid_local' => $file->getUid(),
'uid_foreign' => uniqid('NEW_'),
'uid' => uniqid('NEW_'),
'uid_foreign' => StringUtility::getUniqueId('NEW_'),
'uid' => StringUtility::getUniqueId('NEW_'),
'crop' => null,
]
);
......
......@@ -23,6 +23,7 @@ namespace TYPO3\CMS\Form\ViewHelpers\Form;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\CMS\Extbase\Property\PropertyMapper;
use TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper;
use TYPO3\CMS\Form\Domain\Runtime\FormRuntime;
......@@ -94,7 +95,7 @@ class DatePickerViewHelper extends AbstractFormFieldViewHelper
if ($this->hasArgument('id')) {
$id = $this->arguments['id'];
} else {
$id = 'field' . md5(uniqid());
$id = 'field' . md5(StringUtility::getUniqueId());
}
if (empty($placeholder)) {
......
......@@ -39,6 +39,7 @@ use TYPO3\CMS\Core\Registry;
use TYPO3\CMS\Core\Service\OpcodeCacheService;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\CMS\Install\ExtensionScanner\Php\CodeStatistics;
use TYPO3\CMS\Install\ExtensionScanner\Php\GeneratorClassesResolver;
use TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\ArrayDimensionMatcher;
......@@ -738,7 +739,7 @@ class UpgradeController extends AbstractController
$preparedMatches = [];
foreach ($matches as $match) {
$preparedHit = [];
$preparedHit['uniqueId'] = str_replace('.', '', uniqid((string)random_int(0, mt_getrandmax()), true));
$preparedHit['uniqueId'] = StringUtility::getUniqueId();
$preparedHit['message'] = $match['message'];
$preparedHit['line'] = $match['line'];
$preparedHit['indicator'] = $match['indicator'];
......@@ -767,7 +768,7 @@ class UpgradeController extends AbstractController
array_pop($version);
// something like "8.2" .. "8.7" .. "master"
$parsedRestFile['version'] = array_pop($version);
$parsedRestFile['uniqueId'] = str_replace('.', '', uniqid((string)random_int(0, mt_getrandmax()), true));
$parsedRestFile['uniqueId'] = StringUtility::getUniqueId();
$preparedHit['restFiles'][] = $parsedRestFile;
}
$preparedMatches[] = $preparedHit;
......
......@@ -20,6 +20,7 @@ namespace TYPO3\CMS\Install\Tests\Functional\Service;
use TYPO3\CMS\Core\Resource\ProcessedFileRepository;
use TYPO3\CMS\Core\Resource\StorageRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\CMS\Install\Service\Typo3tempFileService;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
......@@ -41,7 +42,7 @@ class Typo3tempFileServiceTest extends FunctionalTestCase
protected function setUp(): void
{
parent::setUp();
$this->directoryName = uniqid('test');
$this->directoryName = StringUtility::getUniqueId('test');
$this->directoryPath = $this->instancePath . '/typo3temp/assets/' . $this->directoryName;
}
......
......@@ -27,6 +27,7 @@ use TYPO3\CMS\Core\Resource\ProcessedFile;
use TYPO3\CMS\Core\Utility\DiffUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\CMS\Workspaces\Domain\Model\CombinedRecord;
use TYPO3\CMS\Workspaces\Service\GridDataService;
use TYPO3\CMS\Workspaces\Service\HistoryService;
......@@ -295,7 +296,7 @@ class RemoteServer
*/
protected function prepareFileReferenceDifferences(array $liveFileReferences, array $versionFileReferences, $useThumbnails = false)
{
$randomValue = uniqid('file');
$randomValue = StringUtility::getUniqueId('file');
$liveValues = [];
$versionValues = [];
......
......@@ -30,6 +30,7 @@ use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException;
use TYPO3\CMS\Core\Routing\UnableToLinkToPageException;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\CMS\Core\Versioning\VersionState;
use TYPO3\CMS\Workspaces\Service\WorkspaceService;
......@@ -213,7 +214,7 @@ class PreviewUriBuilder
*/
protected function compilePreviewKeyword(int $ttl = 172800, int $workspaceId = null): string
{
$keyword = md5(uniqid(microtime(), true));
$keyword = md5(StringUtility::getUniqueId());
GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable('sys_preview')
->insert(
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment