Release 2.60 (#5971)
This commit is contained in:
@@ -35,6 +35,7 @@ class InvoiceModelActivityHydratorTest extends TestCase
|
||||
$keys = [
|
||||
'activity.id',
|
||||
'activity.name',
|
||||
'activity.counter',
|
||||
'activity.comment',
|
||||
'activity.number',
|
||||
'activity.invoice_text',
|
||||
|
||||
@@ -33,10 +33,10 @@ class InvoiceModelProjectHydratorTest extends TestCase
|
||||
public function assertModelStructure(array $model): void
|
||||
{
|
||||
$keys = [
|
||||
'project._counter',
|
||||
'project.id',
|
||||
'project.name',
|
||||
'project.comment',
|
||||
'project.counter',
|
||||
'project.number',
|
||||
'project.invoice_text',
|
||||
'project.order_date',
|
||||
|
||||
@@ -215,7 +215,8 @@ class DebugRendererTest extends TestCase
|
||||
'user.meta.hello',
|
||||
'user.meta.kitty',
|
||||
'testFromModelHydrator',
|
||||
'project._counter',
|
||||
'project.counter',
|
||||
'activity.counter',
|
||||
];
|
||||
|
||||
if ($activityCounter === 1) {
|
||||
|
||||
@@ -23,6 +23,7 @@ use Doctrine\ORM\Query\Expr\Orx;
|
||||
use Doctrine\ORM\Query\Parameter;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
#[CoversClass(SearchHelper::class)]
|
||||
@@ -198,4 +199,57 @@ class SearchHelperTest extends TestCase
|
||||
|
||||
$sut->addSearchTerm($qb, $query);
|
||||
}
|
||||
|
||||
public static function provideMaliciousMetaFieldPayloads(): array
|
||||
{
|
||||
$exploitPayload = "metaNotExists1\tFROM\tApp\\Entity\\User\tmetaNotExists1\tWHERE\tmetaNotExists1.id=1)--";
|
||||
|
||||
return [
|
||||
'dot and parenthesis characters' => ['x.y:~ x):""', ['x.y', 'x)']],
|
||||
'tab and comment injection payloads' => [$exploitPayload . ':~ ' . $exploitPayload . ':""', ['metaNotExists1.id=1)--', 'metaNotExists1.id=1)--']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Regression test for GHSA-9cxw-hp3c-637x
|
||||
*/
|
||||
#[DataProvider('provideMaliciousMetaFieldPayloads')]
|
||||
public function testMaliciousMetaFieldNamesCannotInfluenceSubqueryDql(string $term, array $expectedMetaNames): void
|
||||
{
|
||||
$em = $this->createMock(EntityManagerInterface::class);
|
||||
$em->method('getExpressionBuilder')->willReturn(new Expr());
|
||||
$qb = new QueryBuilder($em);
|
||||
$qb->from(Timesheet::class, 'testFoo');
|
||||
|
||||
$query = new BaseQuery();
|
||||
$query->setSearchTerm(new SearchTerm($term));
|
||||
$configuration = new SearchConfiguration(['bar'], 'MetaFieldClass', 'metaFieldName');
|
||||
$configuration->setEntityFieldName('entityFieldName');
|
||||
|
||||
$sut = new SearchHelper($configuration);
|
||||
|
||||
$sut->addSearchTerm($qb, $query);
|
||||
|
||||
$wherePart = $qb->getDQLPart('where');
|
||||
self::assertInstanceOf(Andx::class, $wherePart);
|
||||
$where = (string) $wherePart;
|
||||
|
||||
self::assertStringContainsString('metaNotExists0', $where);
|
||||
self::assertStringContainsString('metaNotExists1', $where);
|
||||
self::assertStringNotContainsString('App\\Entity\\User', $where);
|
||||
self::assertStringNotContainsString('--', $where);
|
||||
self::assertStringNotContainsString("\tFROM\t", $where);
|
||||
|
||||
$metaNames = [];
|
||||
/** @var Parameter $parameter */
|
||||
foreach ($qb->getParameters() as $parameter) {
|
||||
if (str_starts_with($parameter->getName(), 'metaName')) {
|
||||
$metaNames[] = $parameter->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
self::assertCount(2, $metaNames);
|
||||
self::assertEquals($expectedMetaNames[0], $metaNames[0]);
|
||||
self::assertEquals($expectedMetaNames[1], $metaNames[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,4 +170,39 @@ class SearchTermTest extends TestCase
|
||||
self::assertEquals($expected[2], $part->isExcluded());
|
||||
}
|
||||
}
|
||||
|
||||
public function testWhitespaceIsNormalizedWhenTokenizing(): void
|
||||
{
|
||||
$sut = new SearchTerm(" \tfoo\tbar:baz\nhello world\t ");
|
||||
|
||||
self::assertTrue($sut->hasSearchTerm());
|
||||
self::assertEquals('foo hello world', $sut->getSearchTerm());
|
||||
self::assertEquals(['bar' => 'baz'], $sut->getSearchFields());
|
||||
self::assertEquals(" \tfoo\tbar:baz\nhello world\t ", $sut->getOriginalSearch());
|
||||
self::assertCount(4, $sut->getParts());
|
||||
|
||||
$expectedParts = [
|
||||
['foo', null, false],
|
||||
['baz', 'bar', false],
|
||||
['hello', null, false],
|
||||
['world', null, false],
|
||||
];
|
||||
$i = 0;
|
||||
foreach ($sut->getParts() as $part) {
|
||||
$expected = $expectedParts[$i++];
|
||||
self::assertEquals($expected[0], $part->getTerm());
|
||||
self::assertEquals($expected[1], $part->getField());
|
||||
self::assertEquals($expected[2], $part->isExcluded());
|
||||
}
|
||||
}
|
||||
|
||||
public function testWhitespaceOnlySearchTermCreatesNoParts(): void
|
||||
{
|
||||
$sut = new SearchTerm(" \t \n ");
|
||||
|
||||
self::assertFalse($sut->hasSearchTerm());
|
||||
self::assertEquals('', $sut->getSearchTerm());
|
||||
self::assertEquals([], $sut->getSearchFields());
|
||||
self::assertCount(0, $sut->getParts());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user