| @@ -60,8 +60,11 @@ | ||
| 60 | 60 | |
| 61 | 61 | /** @var mixed[][] */ |
| 62 | 62 | private array $props = []; |
| 63 | 63 | |
| 64 | + /** @var int[] */ | |
| 65 | + private array $possibleLoop = []; | |
| 66 | + | |
| 64 | 67 | /** |
| 65 | 68 | * Read the file. |
| 66 | 69 | */ |
| 67 | 70 | public function read(string $filename): void |
| @@ -136,9 +139,11 @@ | ||
| 136 | 139 | } |
| 137 | 140 | |
| 138 | 141 | $sbdBlock = $this->sbdStartBlock; |
| 139 | 142 | $this->smallBlockChain = ''; |
| 143 | + $this->possibleLoop = []; | |
| 140 | 144 | while ($sbdBlock != -2) { |
| 145 | + $this->catchLoop($sbdBlock); | |
| 141 | 146 | $pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE; |
| 142 | 147 | |
| 143 | 148 | $this->smallBlockChain .= substr($this->data, $pos, 4 * $bbs); |
| 144 | 149 | $pos += 4 * $bbs; |
| @@ -152,8 +157,16 @@ | ||
| 152 | 157 | |
| 153 | 158 | $this->readPropertySets(); |
| 154 | 159 | } |
| 155 | 160 | |
| 161 | + private function catchLoop(int $sbdBlock): void | |
| 162 | + { | |
| 163 | + if (in_array($sbdBlock, $this->possibleLoop, true)) { | |
| 164 | + throw new ReaderException('Detected loop while iterating blocks'); | |
| 165 | + } | |
| 166 | + $this->possibleLoop[] = $sbdBlock; | |
| 167 | + } | |
| 168 | + | |
| 156 | 169 | /** |
| 157 | 170 | * Extract binary stream data. |
| 158 | 171 | */ |
| 159 | 172 | public function getStream(?int $stream): ?string |
| @@ -171,9 +184,11 @@ | ||
| 171 | 184 | |
| 172 | 185 | /** @var int */ |
| 173 | 186 | $block = $this->props[$stream]['startBlock']; |
| 174 | 187 | |
| 188 | + $this->possibleLoop = []; | |
| 175 | 189 | while ($block != -2) { |
| 190 | + $this->catchLoop($block); | |
| 176 | 191 | $pos = $block * self::SMALL_BLOCK_SIZE; |
| 177 | 192 | $streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE); |
| 178 | 193 | |
| 179 | 194 | $block = self::getInt4d($this->smallBlockChain, $block * 4); |
| @@ -194,9 +209,11 @@ | ||
| 194 | 209 | |
| 195 | 210 | /** @var int */ |
| 196 | 211 | $block = $this->props[$stream]['startBlock']; |
| 197 | 212 | |
| 213 | + $this->possibleLoop = []; | |
| 198 | 214 | while ($block != -2) { |
| 215 | + $this->catchLoop($block); | |
| 199 | 216 | $pos = ($block + 1) * self::BIG_BLOCK_SIZE; |
| 200 | 217 | $streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); |
| 201 | 218 | $block = self::getInt4d($this->bigBlockChain, $block * 4); |
| 202 | 219 | } |
| @@ -214,9 +231,11 @@ | ||
| 214 | 231 | private function readData(int $block): string |
| 215 | 232 | { |
| 216 | 233 | $data = ''; |
| 217 | 234 | |
| 235 | + $this->possibleLoop = []; | |
| 218 | 236 | while ($block != -2) { |
| 237 | + $this->catchLoop($block); | |
| 219 | 238 | $pos = ($block + 1) * self::BIG_BLOCK_SIZE; |
| 220 | 239 | $data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); |
| 221 | 240 | $block = self::getInt4d($this->bigBlockChain, $block * 4); |
| 222 | 241 | } |