← All changes
|
libraries/vendor/PhpSpreadsheet/Shared/OLE/PPS/Root.php
+33
-23
3.3.2
→
3.4
View file →
| @@ -19,8 +19,9 @@ | ||
| 19 | 19 | // | Author: Xavier Noguer <[email protected]> | |
| 20 | 20 | // | Based on OLE::Storage_Lite by Kawai, Takanori | |
| 21 | 21 | // +----------------------------------------------------------------------+ |
| 22 | 22 | // |
| 23 | +use TablePress\PhpOffice\PhpSpreadsheet\Exception; | |
| 23 | 24 | use TablePress\PhpOffice\PhpSpreadsheet\Shared\OLE; |
| 24 | 25 | use TablePress\PhpOffice\PhpSpreadsheet\Shared\OLE\PPS; |
| 25 | 26 | |
| 26 | 27 | /** |
| @@ -29,16 +30,24 @@ | ||
| 29 | 30 | * @author Xavier Noguer <[email protected]> |
| 30 | 31 | */ |
| 31 | 32 | class Root extends PPS |
| 32 | 33 | { |
| 34 | + private const BIG_BLOCK_SIZE = 512; | |
| 35 | + | |
| 36 | + private const SMALL_BLOCK_SIZE = 64; | |
| 37 | + | |
| 38 | + private const MAX_VERSION_3_STREAM_SIZE = 0x80000000; | |
| 39 | + | |
| 40 | + private const MAX_REGULAR_SECTOR_COUNT = 0xFFFFFFFB; | |
| 41 | + | |
| 33 | 42 | /** |
| 34 | 43 | * @var resource |
| 35 | 44 | */ |
| 36 | 45 | private $fileHandle; |
| 37 | 46 | |
| 38 | - private ?int $smallBlockSize = null; | |
| 47 | + private int $smallBlockSize = self::SMALL_BLOCK_SIZE; | |
| 39 | 48 | |
| 40 | - private ?int $bigBlockSize = null; | |
| 49 | + private int $bigBlockSize = self::BIG_BLOCK_SIZE; | |
| 41 | 50 | |
| 42 | 51 | /** |
| 43 | 52 | * @param null|float|int $time_1st A timestamp |
| 44 | 53 | * @param null|float|int $time_2nd A timestamp |
| @@ -63,15 +72,11 @@ | ||
| 63 | 72 | public function save($fileHandle): bool |
| 64 | 73 | { |
| 65 | 74 | $this->fileHandle = $fileHandle; |
| 66 | 75 | |
| 67 | - // Initial Setting for saving | |
| 68 | - $this->bigBlockSize = (int) (2 ** ( | |
| 69 | - (isset($this->bigBlockSize)) ? self::adjust2($this->bigBlockSize) : 9 | |
| 70 | - )); | |
| 71 | - $this->smallBlockSize = (int) (2 ** ( | |
| 72 | - (isset($this->smallBlockSize)) ? self::adjust2($this->smallBlockSize) : 6 | |
| 73 | - )); | |
| 76 | + // This writer implements the version-3 CFB profile only. | |
| 77 | + $this->bigBlockSize = self::BIG_BLOCK_SIZE; | |
| 78 | + $this->smallBlockSize = self::SMALL_BLOCK_SIZE; | |
| 74 | 79 | |
| 75 | 80 | // Make an array of PPS's (for Save) |
| 76 | 81 | $aList = []; |
| 77 | 82 | PPS::savePpsSetPnt($aList, [$this]); |
| @@ -81,8 +86,9 @@ | ||
| 81 | 86 | $this->saveHeader((int) $iSBDcnt, (int) $iBBcnt, (int) $iPPScnt); |
| 82 | 87 | |
| 83 | 88 | // Make Small Data string (write SBD) |
| 84 | 89 | $this->_data = $this->makeSmallData($aList); |
| 90 | + $this->assertVersion3StreamSize(strlen($this->_data)); | |
| 85 | 91 | |
| 86 | 92 | // Write BB |
| 87 | 93 | $this->saveBigData((int) $iSBDcnt, $aList); |
| 88 | 94 | // Write PPS |
| @@ -108,8 +114,9 @@ | ||
| 108 | 114 | $iCount = count($raList); |
| 109 | 115 | for ($i = 0; $i < $iCount; ++$i) { |
| 110 | 116 | if ($raList[$i]->Type == OLE::OLE_PPS_TYPE_FILE) { |
| 111 | 117 | $raList[$i]->Size = $raList[$i]->getDataLen(); |
| 118 | + $this->assertVersion3StreamSize($raList[$i]->Size); | |
| 112 | 119 | if ($raList[$i]->Size < OLE::OLE_DATA_SIZE_SMALL) { |
| 113 | 120 | $iSBcnt += floor($raList[$i]->Size / $this->smallBlockSize) |
| 114 | 121 | + (($raList[$i]->Size % $this->smallBlockSize) ? 1 : 0); |
| 115 | 122 | } else { |
| @@ -117,8 +124,9 @@ | ||
| 117 | 124 | + (($raList[$i]->Size % $this->bigBlockSize) ? 1 : 0)); |
| 118 | 125 | } |
| 119 | 126 | } |
| 120 | 127 | } |
| 128 | + $this->assertVersion3MiniStreamSize((int) $iSBcnt); | |
| 121 | 129 | $iSmallLen = $iSBcnt * $this->smallBlockSize; |
| 122 | 130 | $iSlCnt = floor($this->bigBlockSize / OLE::OLE_LONG_INT_SIZE); |
| 123 | 131 | $iSBDcnt = floor($iSBcnt / $iSlCnt) + (($iSBcnt % $iSlCnt) ? 1 : 0); |
| 124 | 132 | $iBBcnt += (floor($iSmallLen / $this->bigBlockSize) |
| @@ -129,20 +137,18 @@ | ||
| 129 | 137 | |
| 130 | 138 | return [$iSBDcnt, $iBBcnt, $iPPScnt]; |
| 131 | 139 | } |
| 132 | 140 | |
| 133 | - /** | |
| 134 | - * Helper function for calculating a magic value for block sizes. | |
| 135 | - * | |
| 136 | - * @param int $i2 The argument | |
| 137 | - * | |
| 138 | - * @see save() | |
| 139 | - */ | |
| 140 | - private static function adjust2(int $i2): float | |
| 141 | + private function assertVersion3StreamSize(int $size): void | |
| 141 | 142 | { |
| 142 | - $iWk = log($i2) / log(2); | |
| 143 | + if ($size > self::MAX_VERSION_3_STREAM_SIZE) { | |
| 144 | + throw new Exception('OLE version-3 streams cannot exceed 2 GiB.'); | |
| 145 | + } | |
| 146 | + } | |
| 143 | 147 | |
| 144 | - return ($iWk > floor($iWk)) ? floor($iWk) + 1 : $iWk; | |
| 148 | + private function assertVersion3MiniStreamSize(int $smallBlockCount): void | |
| 149 | + { | |
| 150 | + $this->assertVersion3StreamSize($smallBlockCount * self::SMALL_BLOCK_SIZE); | |
| 145 | 151 | } |
| 146 | 152 | |
| 147 | 153 | /** |
| 148 | 154 | * Save OLE header. |
| @@ -167,14 +173,18 @@ | ||
| 167 | 173 | ++$iBdExL; |
| 168 | 174 | ++$iAllW; |
| 169 | 175 | $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0); |
| 170 | 176 | $iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW + $iBdCntW) % $iBlCnt) ? 1 : 0); |
| 171 | - if ($iBdCnt <= ($iBdExL * $iBlCnt + $i1stBdL)) { | |
| 177 | + if ($iBdCnt <= ($iBdExL * ($iBlCnt - 1) + $i1stBdL)) { | |
| 172 | 178 | break; |
| 173 | 179 | } |
| 174 | 180 | } |
| 175 | 181 | } |
| 176 | 182 | |
| 183 | + if ($iAllW + $iBdCnt > self::MAX_REGULAR_SECTOR_COUNT) { | |
| 184 | + throw new Exception('OLE version-3 output exceeds the maximum sector count.'); | |
| 185 | + } | |
| 186 | + | |
| 177 | 187 | // Save Header |
| 178 | 188 | fwrite( |
| 179 | 189 | $FILE, |
| 180 | 190 | "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" |
| @@ -181,9 +191,9 @@ | ||
| 181 | 191 | . "\x00\x00\x00\x00" |
| 182 | 192 | . "\x00\x00\x00\x00" |
| 183 | 193 | . "\x00\x00\x00\x00" |
| 184 | 194 | . "\x00\x00\x00\x00" |
| 185 | - . pack('v', 0x3B) | |
| 195 | + . pack('v', 0x3E) | |
| 186 | 196 | . pack('v', 0x03) |
| 187 | 197 | . pack('v', -2) |
| 188 | 198 | . pack('v', 9) |
| 189 | 199 | . pack('v', 6) |
| @@ -197,9 +207,9 @@ | ||
| 197 | 207 | . pack('V', $iSBDcnt ? 0 : -2) //Small Block Depot |
| 198 | 208 | . pack('V', $iSBDcnt) |
| 199 | 209 | ); |
| 200 | 210 | // Extra BDList Start, Count |
| 201 | - if ($iBdCnt < $i1stBdL) { | |
| 211 | + if ($iBdCnt <= $i1stBdL) { | |
| 202 | 212 | fwrite( |
| 203 | 213 | $FILE, |
| 204 | 214 | pack('V', -2) // Extra BDList Start |
| 205 | 215 | . pack('V', 0)// Extra BDList Count |
| @@ -341,9 +351,9 @@ | ||
| 341 | 351 | ++$iBdExL; |
| 342 | 352 | ++$iAllW; |
| 343 | 353 | $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0); |
| 344 | 354 | $iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW + $iBdCntW) % $iBbCnt) ? 1 : 0); |
| 345 | - if ($iBdCnt <= ($iBdExL * $iBbCnt + $i1stBdL)) { | |
| 355 | + if ($iBdCnt <= ($iBdExL * ($iBbCnt - 1) + $i1stBdL)) { | |
| 346 | 356 | break; |
| 347 | 357 | } |
| 348 | 358 | } |
| 349 | 359 | } |