Skip to content

Commit 26b2ee4

Browse files
committed
Merge branch 'master' into release-3.x
2 parents 4d98769 + 7c6a64e commit 26b2ee4

9 files changed

Lines changed: 186 additions & 20 deletions

File tree

‎.github/workflows/php.yml‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ jobs:
184184
with:
185185
# Should be the higest supported version, so we can use the newest tools
186186
php-version: '8.5'
187-
tools: composer, composer-require-checker, composer-unused
187+
tools: composer, composer-dependency-analyser
188188
extensions: ctype, date, dom, filter, intl, libxml, pcre, sodium, spl, xml
189189
coverage: none
190190

@@ -218,11 +218,8 @@ jobs:
218218
- name: Install Composer dependencies
219219
run: composer install --no-progress --prefer-dist --optimize-autoloader
220220

221-
- name: Check code for hard dependencies missing in composer.json
222-
run: composer-require-checker check --config-file=tools/composer-require-checker.json composer.json
223-
224-
- name: Check code for unused dependencies in composer.json
225-
run: composer-unused --excludePackage=simplesamlphp/composer-xmlprovider-installer
221+
- name: Check code for missing or unused dependencies
222+
run: composer-dependency-analyser --verbose --config=tools/composer-dependency-analyser.php
226223

227224
- name: PHP Code Sniffer
228225
run: vendor/bin/phpcs

‎composer.json‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
"ext-bcmath": "*",
3939
"ext-date": "*",
4040
"ext-dom": "*",
41-
"ext-filter": "*",
4241
"ext-libxml": "*",
4342
"ext-pcre": "*",
4443
"ext-spl": "*",
@@ -49,7 +48,10 @@
4948
"simplesamlphp/composer-xmlprovider-installer": "~1.3"
5049
},
5150
"require-dev": {
52-
"simplesamlphp/simplesamlphp-test-framework": "~2.0"
51+
"ext-mbstring": "*",
52+
53+
"phpunit/phpunit": "^13.3",
54+
"simplesamlphp/simplesamlphp-test-framework": "dev-release-2.x"
5355
},
5456
"support": {
5557
"issues": "https://github.com/simplesamlphp/xml-common/issues",

‎src/XML/Attribute.php‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use SimpleSAML\XML\Assert\Assert;
99
use SimpleSAML\XML\Constants as C;
1010
use SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface;
11+
use SimpleSAML\XMLSchema\Type\QNameValue;
1112
use SimpleSAML\XMLSchema\Type\StringValue;
1213

1314
use function array_keys;
@@ -116,12 +117,11 @@ public function toXML(Dom\Element $parent): Dom\Element
116117
$qName = $this->getAttrValue();
117118
if ($qName instanceof QNameValue) {
118119
$qNamePrefix = $qName->getNamespacePrefix();
119-
if ($qNamePrefix !== null && !$parent->lookupPrefix($qNamePrefix->getValue)) {
120+
if ($qNamePrefix !== null && !$parent->lookupPrefix($qNamePrefix->getValue())) {
120121
$parent->setAttributeNS(
122+
C::NS_XMLNS,
123+
'xmlns:' . $qNamePrefix->getValue(),
121124
$qName->getNamespaceURI()->getValue(),
122-
'xmlns',
123-
$qNamePrefix->getValue(),
124-
$qname->getNamespaceURI()->getValue(),
125125
);
126126
}
127127
}

‎src/XMLSchema/Type/IntegerValue.php‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,14 @@ public function toInteger(): int
5050
{
5151
$value = $this->getValue();
5252

53-
if (bccomp($value, strval(PHP_INT_MAX)) === 1) {
53+
try {
54+
$tooHigh = bccomp($value, (string)PHP_INT_MAX, 0) === 1;
55+
$tooLow = bccomp($value, (string)PHP_INT_MIN, 0) === -1;
56+
} catch (\ValueError $e) {
57+
throw new SchemaViolationException("Not a well-formed integer string.", previous: $e);
58+
}
59+
60+
if ($tooHigh || $tooLow) {
5461
throw new RuntimeException("Cannot convert to integer: out of bounds.");
5562
}
5663

‎tests/XML/DOMDocumentFactoryTest.php‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,12 @@ public function testExternalEntityCannotReadLocalFileUsingNonDefaultOptions(): v
9696
<foo>&xxe;</foo>
9797
XML;
9898

99-
$doc = Dom\XMLDocument::createFromString($payload, DOMDocumentFactory::getDefaultOptions() | \LIBXML_NOENT);
99+
$options = DOMDocumentFactory::getDefaultOptions();
100+
if (defined('LIBXML_NO_XXE')) {
101+
$options &= ~\LIBXML_NO_XXE;
102+
}
103+
104+
$doc = Dom\XMLDocument::createFromString($payload, $options | \LIBXML_NOENT);
100105
// Check that the secret did leak into the document.
101106
$xml = $doc->saveXml();
102107
$this->assertStringContainsString(
@@ -154,7 +159,12 @@ public function testUtf16ExternalEntityCannotReadLocalFileUsingNonDefaultOptions
154159

155160
$payload = "\xFF\xFE" . mb_convert_encoding($utf8, 'UTF-16LE', 'UTF-8');
156161

157-
$doc = Dom\XMLDocument::createFromString($payload, DOMDocumentFactory::getDefaultOptions() | \LIBXML_NOENT);
162+
$options = DOMDocumentFactory::getDefaultOptions();
163+
if (defined('LIBXML_NO_XXE')) {
164+
$options &= ~\LIBXML_NO_XXE;
165+
}
166+
167+
$doc = Dom\XMLDocument::createFromString($payload, $options | \LIBXML_NOENT);
158168
// Check that the secret did leak into the document.
159169
$xml = mb_convert_encoding((string)$doc->saveXml(), 'UTF-8', 'UTF-16LE');
160170
$this->assertStringContainsString(
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\Test\XMLSchema\Type;
6+
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use PHPUnit\Framework\TestCase;
10+
use SimpleSAML\XMLSchema\Type\IntegerValue;
11+
12+
/**
13+
* Class \SimpleSAML\Test\XMLSchema\Type\IntegerFromIntegerTest
14+
*
15+
* @package simplesamlphp/xml-common
16+
*/
17+
#[CoversClass(IntegerValue::class)]
18+
final class IntegerFromIntegerTest extends TestCase
19+
{
20+
/**
21+
* @param int $integer
22+
*/
23+
#[DataProvider('provideIntegers')]
24+
public function testFromInteger(int $integer): void
25+
{
26+
$value = IntegerValue::fromInteger($integer);
27+
28+
$this->assertSame((string) $integer, $value->getValue());
29+
$this->assertSame($integer, $value->toInteger());
30+
}
31+
32+
33+
/**
34+
* @return array<string, array{0: int}>
35+
*/
36+
public static function provideIntegers(): array
37+
{
38+
return [
39+
'negative integer' => [-1234],
40+
'zero' => [0],
41+
'positive integer' => [1234],
42+
'minimum integer' => [PHP_INT_MIN],
43+
'maximum integer' => [PHP_INT_MAX],
44+
];
45+
}
46+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\Test\XMLSchema\Type;
6+
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use PHPUnit\Framework\Attributes\DataProviderExternal;
10+
use PHPUnit\Framework\TestCase;
11+
use SimpleSAML\Test\XML\Assert\IntegerTest;
12+
use SimpleSAML\XMLSchema\Exception\RuntimeException;
13+
use SimpleSAML\XMLSchema\Exception\SchemaViolationException;
14+
use SimpleSAML\XMLSchema\Type\IntegerValue;
15+
16+
/**
17+
* Class \SimpleSAML\Test\XMLSchema\Type\IntegerOverflowTest
18+
*
19+
* @package simplesamlphp/xml-common
20+
*/
21+
#[CoversClass(IntegerValue::class)]
22+
final class IntegerOverflowTest extends TestCase
23+
{
24+
/**
25+
* @param boolean|class-string<\Throwable> $shouldPass
26+
* @param string $integer
27+
* @param string|null $message
28+
*/
29+
#[DataProvider('provideInvalidInteger')]
30+
#[DataProvider('provideValidInteger')]
31+
#[DataProviderExternal(IntegerTest::class, 'provideValidInteger')]
32+
public function testInteger(bool|string $shouldPass, string $integer, ?string $message = null): void
33+
{
34+
try {
35+
IntegerValue::fromString($integer)->toInteger();
36+
$this->assertTrue($shouldPass);
37+
} catch (RuntimeException | SchemaViolationException $e) {
38+
$this->assertSame($shouldPass, $e::class);
39+
if ($message !== null) {
40+
$this->assertSame($message, $e->getMessage());
41+
}
42+
}
43+
}
44+
45+
46+
/**
47+
* @return array<string, array{0: true, 1: string}>
48+
*/
49+
public static function provideValidInteger(): array
50+
{
51+
return [
52+
'valid with whitespace collapse' => [true, " 1234 \n "],
53+
];
54+
}
55+
56+
57+
/**
58+
* @return array<string, array{0: class-string<\Throwable>, 1: string, 2?: string}>
59+
*/
60+
public static function provideInvalidInteger(): array
61+
{
62+
return [
63+
'empty' => [SchemaViolationException::class, ''],
64+
'invalid positive signed out-of-bounds' => [
65+
RuntimeException::class,
66+
'+9223372036854775808',
67+
'Cannot convert to integer: out of bounds.',
68+
],
69+
'invalid negative signed out-of-bounds' => [
70+
RuntimeException::class,
71+
'-9223372036854775809',
72+
'Cannot convert to integer: out of bounds.',
73+
],
74+
'invalid' => [SchemaViolationException::class, '0x123'],
75+
'invalid with fractional' => [SchemaViolationException::class, '1234.'],
76+
'invalid with thousands-delimiter' => [SchemaViolationException::class, '+1,234'],
77+
];
78+
}
79+
80+
81+
public function testToIntegerWithNonWellFormedIntegerStringThrowsException(): void
82+
{
83+
$this->expectException(SchemaViolationException::class);
84+
$this->expectExceptionMessageMatches('/^Not a well-formed integer string\.$/');
85+
86+
/* mock the internal rawValue to test the exception handling within IntegerValue::toInteger() */
87+
$value = $this->createPartialMock(IntegerValue::class, ['getRawValue']);
88+
$value->expects($this->once())->method('getRawValue')->willReturn('0x42');
89+
$value->toInteger();
90+
}
91+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use ShipMonk\ComposerDependencyAnalyser\Config\Configuration;
6+
use ShipMonk\ComposerDependencyAnalyser\Config\ErrorType;
7+
8+
return (new Configuration())
9+
// Constant from libxml (PHP 8.4+ / libxml ≥ 2.13); not a real class
10+
->ignoreUnknownClasses([
11+
'LIBXML_NO_XXE',
12+
])
13+
14+
// Composer plugin – never referenced from PHP source
15+
->ignoreErrorsOnPackage(
16+
'simplesamlphp/composer-xmlprovider-installer',
17+
[ErrorType::UNUSED_DEPENDENCY]
18+
);

‎tools/composer-require-checker.json‎

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)