|
| 1 | +--TEST-- |
| 2 | +GH-22887 (heap out-of-bounds read while decoding an array with an empty arraySize) |
| 3 | +--EXTENSIONS-- |
| 4 | +soap |
| 5 | +--FILE-- |
| 6 | +<?php |
| 7 | +class TestSoapClient extends SoapClient { |
| 8 | + public string $response = ''; |
| 9 | + public string $request = ''; |
| 10 | + |
| 11 | + public function __doRequest(string $request, string $location, string $action, int $version, bool $oneWay = false): ?string { |
| 12 | + $this->request = $request; |
| 13 | + return $this->response; |
| 14 | + } |
| 15 | +} |
| 16 | + |
| 17 | +function soap_response(int $version, string $attributes): string { |
| 18 | + $envelope = $version === SOAP_1_2 |
| 19 | + ? 'http://www.w3.org/2003/05/soap-envelope' |
| 20 | + : 'http://schemas.xmlsoap.org/soap/envelope/'; |
| 21 | + $encoding = $version === SOAP_1_2 |
| 22 | + ? 'http://www.w3.org/2003/05/soap-encoding' |
| 23 | + : 'http://schemas.xmlsoap.org/soap/encoding/'; |
| 24 | + |
| 25 | + return <<<XML |
| 26 | + <?xml version="1.0" encoding="UTF-8"?> |
| 27 | + <SOAP-ENV:Envelope xmlns:SOAP-ENV="$envelope" |
| 28 | + xmlns:SOAP-ENC="$encoding" |
| 29 | + xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
| 30 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| 31 | + xmlns:ns1="http://example.org/"> |
| 32 | + <SOAP-ENV:Body> |
| 33 | + <ns1:testResponse SOAP-ENV:encodingStyle="$encoding"> |
| 34 | + <return $attributes> |
| 35 | + <item xsi:type="xsd:string">first</item> |
| 36 | + <item xsi:type="xsd:string">second</item> |
| 37 | + </return> |
| 38 | + </ns1:testResponse> |
| 39 | + </SOAP-ENV:Body> |
| 40 | + </SOAP-ENV:Envelope> |
| 41 | + XML; |
| 42 | +} |
| 43 | + |
| 44 | +/* Decoding: an arraySize holding no dimension at all must not be trusted as a |
| 45 | + * zero-dimensional array. */ |
| 46 | +foreach ([SOAP_1_1 => '1.1', SOAP_1_2 => '1.2'] as $version => $label) { |
| 47 | + foreach ([ |
| 48 | + 'SOAP-ENC:arraySize=""', |
| 49 | + 'SOAP-ENC:arraySize=" "', |
| 50 | + 'SOAP-ENC:arraySize="abc"', |
| 51 | + 'SOAP-ENC:itemType="xsd:string" SOAP-ENC:arraySize=""', |
| 52 | + 'SOAP-ENC:arraySize="2"', |
| 53 | + ] as $attributes) { |
| 54 | + $client = new TestSoapClient(null, [ |
| 55 | + 'location' => 'test://', |
| 56 | + 'uri' => 'http://example.org/', |
| 57 | + 'soap_version' => $version, |
| 58 | + ]); |
| 59 | + $client->response = soap_response($version, $attributes); |
| 60 | + |
| 61 | + echo "SOAP $label, $attributes:", PHP_EOL; |
| 62 | + var_dump($client->test()); |
| 63 | + } |
| 64 | +} |
| 65 | + |
| 66 | +/* Encoding: same thing for an arraySize coming from a WSDL. */ |
| 67 | +$client = new TestSoapClient(__DIR__ . '/gh22887.wsdl', [ |
| 68 | + 'cache_wsdl' => WSDL_CACHE_NONE, |
| 69 | + 'soap_version' => SOAP_1_2, |
| 70 | +]); |
| 71 | +$client->test(['first', 'second']); |
| 72 | + |
| 73 | +$request = new DOMDocument(); |
| 74 | +$request->loadXML($client->request); |
| 75 | +$value = $request->getElementsByTagName('value')->item(0); |
| 76 | +echo 'arraySize: ', var_export($value->getAttribute('enc:arraySize'), true), PHP_EOL; |
| 77 | +echo 'items: ', $value->getElementsByTagName('item')->length, PHP_EOL; |
| 78 | +?> |
| 79 | +--EXPECT-- |
| 80 | +SOAP 1.1, SOAP-ENC:arraySize="": |
| 81 | +array(2) { |
| 82 | + [0]=> |
| 83 | + string(5) "first" |
| 84 | + [1]=> |
| 85 | + string(6) "second" |
| 86 | +} |
| 87 | +SOAP 1.1, SOAP-ENC:arraySize=" ": |
| 88 | +array(2) { |
| 89 | + [0]=> |
| 90 | + string(5) "first" |
| 91 | + [1]=> |
| 92 | + string(6) "second" |
| 93 | +} |
| 94 | +SOAP 1.1, SOAP-ENC:arraySize="abc": |
| 95 | +array(2) { |
| 96 | + [0]=> |
| 97 | + string(5) "first" |
| 98 | + [1]=> |
| 99 | + string(6) "second" |
| 100 | +} |
| 101 | +SOAP 1.1, SOAP-ENC:itemType="xsd:string" SOAP-ENC:arraySize="": |
| 102 | +array(2) { |
| 103 | + [0]=> |
| 104 | + string(5) "first" |
| 105 | + [1]=> |
| 106 | + string(6) "second" |
| 107 | +} |
| 108 | +SOAP 1.1, SOAP-ENC:arraySize="2": |
| 109 | +array(2) { |
| 110 | + [0]=> |
| 111 | + string(5) "first" |
| 112 | + [1]=> |
| 113 | + string(6) "second" |
| 114 | +} |
| 115 | +SOAP 1.2, SOAP-ENC:arraySize="": |
| 116 | +array(2) { |
| 117 | + [0]=> |
| 118 | + string(5) "first" |
| 119 | + [1]=> |
| 120 | + string(6) "second" |
| 121 | +} |
| 122 | +SOAP 1.2, SOAP-ENC:arraySize=" ": |
| 123 | +array(2) { |
| 124 | + [0]=> |
| 125 | + string(5) "first" |
| 126 | + [1]=> |
| 127 | + string(6) "second" |
| 128 | +} |
| 129 | +SOAP 1.2, SOAP-ENC:arraySize="abc": |
| 130 | +array(2) { |
| 131 | + [0]=> |
| 132 | + string(5) "first" |
| 133 | + [1]=> |
| 134 | + string(6) "second" |
| 135 | +} |
| 136 | +SOAP 1.2, SOAP-ENC:itemType="xsd:string" SOAP-ENC:arraySize="": |
| 137 | +array(2) { |
| 138 | + [0]=> |
| 139 | + string(5) "first" |
| 140 | + [1]=> |
| 141 | + string(6) "second" |
| 142 | +} |
| 143 | +SOAP 1.2, SOAP-ENC:arraySize="2": |
| 144 | +array(2) { |
| 145 | + [0]=> |
| 146 | + string(5) "first" |
| 147 | + [1]=> |
| 148 | + string(6) "second" |
| 149 | +} |
| 150 | +arraySize: '2' |
| 151 | +items: 2 |
0 commit comments