Issues (25)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/LZX/Inflater.php (1 issue)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace CHMLib\LZX;
4
5
use Exception;
6
use CHMLib\Reader\BitReader;
7
8
/**
9
 * Decompressor of LXZ-compressed data.
10
 */
11
class Inflater
12
{
13
    /**
14
     * The smallest allowable match length.
15
     *
16
     * @var int
17
     */
18
    const MIN_MATCH = 2;
19
20
    /**
21
     * The number of uncompressed character types.
22
     *
23
     * @var int
24
     */
25
    const NUM_CHARS = 256;
26
27
    /**
28
     * Block type: verbatim.
29
     *
30
     * @var int
31
     */
32
    const BLOCKTYPE_VERBATIM = 1;
33
34
    /**
35
     * Block type: aligned offset.
36
     *
37
     * @var int
38
     */
39
    const BLOCKTYPE_ALIGNED = 2;
40
41
    /**
42
     * Block type: uncompressed.
43
     *
44
     * @var int
45
     */
46
    const BLOCKTYPE_UNCOMPRESSED = 3;
47
48
    /**
49
     * The number of elements in the aligned offset tree.
50
     *
51
     * @var int
52
     */
53
    const ALIGNED_NUM_ELEMENTS = 8;
54
55
    /**
56
     * Unknown.
57
     *
58
     * @var int
59
     */
60
    const NUM_PRIMARY_LENGTHS = 7;
61
62
    /**
63
     * The number of elements in the length tree.
64
     *
65
     * @var int
66
     */
67
    const NUM_SECONDARY_LENGTHS = 249;
68
69
    /**
70
     * The index matrix of the position slot bases.
71
     *
72
     * @var int[]
73
     */
74
    protected static $POSITION_BASE = array(
75
              0,       1,       2,      3,      4,      6,      8,     12,     16,     24,     32,       48,      64,      96,     128,     192,
76
            256,     384,     512,    768,   1024,   1536,   2048,   3072,   4096,   6144,   8192,    12288,   16384,   24576,   32768,   49152,
77
          65536,   98304,  131072, 196608, 262144, 393216, 524288, 655360, 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
78
        1835008, 1966080, 2097152,
79
    );
80
81
    /**
82
     * Number of needed bits for offset-from-base data.
83
     *
84
     * @var int
85
     */
86
    protected static $EXTRA_BITS = array(
87
         0,  0,  0,  0,  1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,
88
         7,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
89
        15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
90
        17, 17, 17,
91
    );
92
93
    /**
94
     * The size of the actual decoding window.
95
     *
96
     * @var int
97
     */
98
    protected $windowSize;
99
100
    /**
101
     * The actual decoding window.
102
     *
103
     * @var int[]
104
     */
105
    protected $window;
106
107
    /**
108
     * The current offset within the window.
109
     *
110
     * @var int
111
     */
112
    protected $windowPosition;
113
114
    /**
115
     * The most recent non-repeated offset (LRU offset system).
116
     *
117
     * @var int
118
     */
119
    protected $r0;
120
121
    /**
122
     * The second most recent non-repeated offset (LRU offset system).
123
     *
124
     * @var int
125
     */
126
    protected $r1;
127
128
    /**
129
     * The third most recent non-repeated offset (LRU offset system).
130
     *
131
     * @var int
132
     */
133
    protected $r2;
134
135
    /**
136
     * The number of main tree elements.
137
     *
138
     * @var int
139
     */
140
    protected $mainElements;
141
142
    /**
143
     * Decoding has already been started?
144
     *
145
     * @var bool
146
     */
147
    protected $headerRead;
148
149
    /**
150
     * The type of the current block.
151
     *
152
     * @var int
153
     */
154
    protected $blockType;
155
156
    /**
157
     * The uncompressed length of the current block.
158
     *
159
     * @var int
160
     */
161
    protected $blockLength;
162
163
    /**
164
     * The number of ncompressed bytes still left to decode in the current block.
165
     *
166
     * @var int
167
     */
168
    protected $remainingInBlock;
169
170
    /**
171
     * The number of CFDATA blocks processed.
172
     *
173
     * @var int
174
     */
175
    protected $framesRead;
176
177
    /**
178
     * The magic header value used for transform (0 if not encoded).
179
     *
180
     * @var int
181
     */
182
    protected $intelFilesize;
183
184
    /**
185
     * The current offset in transform space.
186
     *
187
     * @var int
188
     */
189
    protected $intelCurrentPosition;
190
191
    /**
192
     * Have we seen any translatable data yet?
193
     *
194
     * @var bool
195
     */
196
    protected $intelStarted;
197
198
    /**
199
     * The main Huffman tree.
200
     *
201
     * @var \CHMLib\LZX\Tree
202
     */
203
    protected $mainTree;
204
205
    /**
206
     * The length Huffman tree.
207
     *
208
     * @var \CHMLib\LZX\Tree
209
     */
210
    protected $lengthTree;
211
212
    /**
213
     * The aligned offset Huffman tree.
214
     *
215
     * @var \CHMLib\LZX\Tree
216
     */
217
    protected $alignedTree;
218
219
    /**
220
     * Initializes the instance.
221
     *
222
     * @param int $windowSize The window size (determines the number of window subdivisions, or "position slots"),
223
     *
224
     * @throws \Exception Throws an Exception in case of errors.
225
     */
226 483
    public function __construct($windowSize)
227
    {
228 483
        $this->windowSize = (int) $windowSize;
229 483
        if ($this->windowSize < 0x8000 || $this->windowSize > 0x200000) {
230
            throw new Exception("Unsupported window size: $windowSize");
231
        }
232 483
        $this->mainTree = new Tree(12, static::NUM_CHARS + 50 * 8);
233 483
        $this->lengthTree = new Tree(12, static::NUM_SECONDARY_LENGTHS + 1);
234 483
        $this->alignedTree = new Tree(7, static::ALIGNED_NUM_ELEMENTS);
235 483
        $this->window = array_fill(0, $this->windowSize, 0);
236 483
        $this->intelFilesize = 0;
237 483
        $numPositionSlots = 0;
238 483
        $windowSize = $this->windowSize;
239 483
        while ($windowSize > 1) {
240 483
            $windowSize >>= 1;
241 483
            $numPositionSlots += 2;
242
        }
243
        switch ($numPositionSlots) {
244 483
            case 40:
245
                $numPositionSlots = 42;
246
                break;
247 483
            case 42:
248
                $numPositionSlots = 50;
249
                break;
250
        }
251 483
        $this->mainElements = static::NUM_CHARS + ($numPositionSlots << 3);
252 483
    }
253
254
    /**
255
     * Uncompress bytes.
256
     *
257
     * @param bool $reset Reset the LXZ state?
258
     * @param \CHMLib\Reader\BitReader $reader The reader that provides the data.
259
     * @param int $numberOfBytes The number of decompressed bytes to retrieve.
260
     *
261
     * @throws \Exception Throws an Exception in case of errors.
262
     *
263
     * @return string
264
     */
265 26
    public function inflate($reset, BitReader $reader, $numberOfBytes)
266
    {
267 26
        if ($reset) {
268 26
            $this->r2 = $this->r1 = $this->r0 = 1;
269 26
            $this->headerRead = false;
270 26
            $this->framesRead = 0;
271 26
            $this->remainingInBlock = 0;
272 26
            $this->blockType = null;
273 26
            $this->intelCurrentPosition = 0;
274 26
            $this->intelStarted = false;
275 26
            $this->windowPosition = 0;
276 26
            $this->mainTree->clear();
277 26
            $this->lengthTree->clear();
278
        }
279
280 26
        if ($this->headerRead === false) {
281 26
            if ($reader->readLE(1) > 0) {
282
                $this->intelFilesize = ($reader->readLE(16) << 16) | $reader->readLE(16);
283
            }
284 26
            $this->headerRead = true;
285
        }
286
287 26
        $togo = $numberOfBytes;
288 26
        while ($togo > 0) {
289 26
            if ($this->remainingInBlock === 0) {
290 26
                if ($this->blockType === static::BLOCKTYPE_UNCOMPRESSED) {
291
                    if (($this->blockLength & 1) !== 0) {
292
                        $reader->skip(1);
293
                    }
294
                }
295 26
                $this->blockType = $reader->readLE(3);
296 26
                $this->remainingInBlock = $this->blockLength = $reader->readLE(16) << 8 | $reader->readLE(8);
297 26
                switch ($this->blockType) {
298 26
                    case static::BLOCKTYPE_ALIGNED:
299 6
                        $this->alignedTree->readAlignLengthTable($reader);
300 6
                        $this->alignedTree->makeSymbolTable();
301
                        /* @noinspection PhpMissingBreakStatementInspection */
302 22
                    case static::BLOCKTYPE_VERBATIM:
303 26
                        $this->mainTree->readLengthTable($reader, 0, static::NUM_CHARS);
304 26
                        $this->mainTree->readLengthTable($reader, static::NUM_CHARS, $this->mainElements);
305 26
                        $this->mainTree->makeSymbolTable();
306 26
                        if ($this->mainTree->isIntel()) {
307 6
                            $this->intelStarted = true;
308
                        }
309 26
                        $this->lengthTree->readLengthTable($reader, 0, static::NUM_SECONDARY_LENGTHS);
310 26
                        $this->lengthTree->makeSymbolTable();
311 26
                        break;
312
                    case static::BLOCKTYPE_UNCOMPRESSED:
313
                        $this->intelStarted = true;
314
                        if ($reader->ensure(16) > 16) {
315
                            $reader->skip(-2);
316
                        }
317
                        $this->r0 = $reader->readUInt32();
318
                        $this->r1 = $reader->readUInt32();
319
                        $this->r2 = $reader->readUInt32();
320
                        break;
321
                    default:
322
                        throw new Exception('Unexpected block type '.$this->blockType);
323
                }
324
            }
325 26
            while (($thisRun = $this->remainingInBlock) > 0 && $togo > 0) {
326 26
                if ($thisRun > $togo) {
327 23
                    $thisRun = $togo;
328
                }
329 26
                $togo -= $thisRun;
330 26
                $this->remainingInBlock -= $thisRun;
331 26
                $this->windowPosition %= $this->windowSize;
332 26
                if ($this->windowPosition + $thisRun > $this->windowSize) {
333
                    throw new Exception('Trying to read more that window size bytes');
334
                }
335 26
                if ($this->blockType === static::BLOCKTYPE_UNCOMPRESSED) {
336
                    $this->window = $reader->readFully($this->window, $this->windowPosition, $thisRun);
337
                    $this->windowPosition += $thisRun;
338
                } else {
339 26
                    while ($thisRun > 0) {
340 26
                        $mainElement = $this->mainTree->readHuffmanSymbol($reader);
341 26
                        if ($mainElement < static::NUM_CHARS) {
342 26
                            $this->window[$this->windowPosition++] = $mainElement;
343 26
                            --$thisRun;
344
                        } else {
345 26
                            $mainElement -= static::NUM_CHARS;
346 26
                            $matchLength = $mainElement & static::NUM_PRIMARY_LENGTHS;
347 26
                            if ($matchLength === static::NUM_PRIMARY_LENGTHS) {
348 26
                                $matchLength += $this->lengthTree->readHuffmanSymbol($reader);
349
                            }
350 26
                            $matchLength += static::MIN_MATCH;
351 26
                            $matchOffset = $mainElement >> 3;
352
                            switch ($matchOffset) {
353 26
                                case 0:
354 26
                                    $matchOffset = $this->r0;
355 26
                                    break;
356 26
                                case 1:
357 26
                                    $matchOffset = $this->r1;
358 26
                                    $this->r1 = $this->r0;
359 26
                                    $this->r0 = $matchOffset;
360 26
                                    break;
361 26
                                case 2:
362 26
                                    $matchOffset = $this->r2;
363 26
                                    $this->r2 = $this->r0;
364 26
                                    $this->r0 = $matchOffset;
365 26
                                    break;
366
                                default:
367 26
                                    switch ($this->blockType) {
368 26
                                        case static::BLOCKTYPE_VERBATIM:
369 22
                                            if ($matchOffset !== 3) {
370 22
                                                $extra = static::$EXTRA_BITS[$matchOffset];
371 22
                                                $matchOffset = static::$POSITION_BASE[$matchOffset] - 2 + $reader->readLE($extra);
372
                                            } else {
373 21
                                                $matchOffset = 1;
374
                                            }
375 22
                                            break;
376 6
                                        case static::BLOCKTYPE_ALIGNED:
377 6
                                            $extra = static::$EXTRA_BITS[$matchOffset];
378 6
                                            $matchOffset = static::$POSITION_BASE[$matchOffset] - 2;
379 6
                                            switch ($extra) {
380 6
                                                case 0:
381 6
                                                    $matchOffset = 1;
382 6
                                                    break;
383 6
                                                case 1:
384 6
                                                case 2:
385
                                                    // verbatim bits only
386 6
                                                    $matchOffset += $reader->readLE($extra);
387 6
                                                    break;
388 6
                                                case 3:
389
                                                    // aligned bits only
390 6
                                                    $matchOffset += $this->alignedTree->readHuffmanSymbol($reader);
391 6
                                                    break;
392
                                                default:
393
                                                    // verbatim and aligned bits
394 6
                                                    $extra -= 3;
395 6
                                                    $matchOffset += ($reader->readLE($extra) << 3);
396 6
                                                    $matchOffset += $this->alignedTree->readHuffmanSymbol($reader);
397 6
                                                    break;
398
                                            }
399 6
                                            break;
400
                                        default:
401
                                            throw new Exception('Unexpected block type ' + $this->blockType);
402
                                    }
403 26
                                    $this->r2 = $this->r1;
404 26
                                    $this->r1 = $this->r0;
405 26
                                    $this->r0 = $matchOffset;
406 26
                                    break;
407
                            }
408 26
                            $runSrc = 0;
0 ignored issues
show
$runSrc is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
409 26
                            $runDest = $this->windowPosition;
410 26
                            $thisRun -= $matchLength;
411
                            // copy any wrapped around source data
412 26
                            if ($this->windowPosition >= $matchOffset) {
413
                                // no wrap
414 26
                                $runSrc = $runDest - $matchOffset;
415
                            } else {
416
                                // wrap around
417
                                $runSrc = $runDest + ($this->windowSize - $matchOffset);
418
                                $copyLength = $matchOffset - $this->windowPosition;
419
                                if ($copyLength < $matchLength) {
420
                                    $matchLength -= $copyLength;
421
                                    $this->windowPosition += $copyLength;
422
                                    while ($copyLength-- > 0) {
423
                                        $this->window[$runDest++] = $this->window[$runSrc++];
424
                                    }
425
                                    $runSrc = 0;
426
                                }
427
                            }
428 26
                            $this->windowPosition += $matchLength;
429
                            // copy match data - no worries about destination wraps
430 26
                            while ($matchLength-- > 0) {
431 26
                                $this->window[$runDest++] = $this->window[$runSrc++];
432
                            }
433
                        }
434
                    }
435
                }
436
            }
437
        }
438
439 26
        if ($togo !== 0) {
440
            throw new Exception('should never happens');
441
        }
442
443 26
        $result = array_slice($this->window, ($this->windowPosition === 0 ? $this->windowSize : $this->windowPosition) - $numberOfBytes, $numberOfBytes);
444
445
        // Intel E8 decoding
446 26
        if (($this->intelFilesize !== 0)) {
447
            if ($this->framesRead++ < 32768) {
448
                if ($numberOfBytes <= 6 || $this->intelStarted === false) {
449
                    $this->intelCurrentPosition += $numberOfBytes;
450
                } else {
451
                    $currentPosition = $this->intelCurrentPosition;
452
                    $this->intelCurrentPosition += $numberOfBytes;
453
                    for ($i = 0; $i < $numberOfBytes - 10;) {
454
                        if ($result[$i++] !== 0xe8) {
455
                            ++$currentPosition;
456
                        } else {
457
                            $absoluteOffset = ($result[$i] & 0xff) | (($result[$i + 1] & 0xff) << 8) | (($result[$i + 2] & 0xff) << 16) | (($result[$i + 3] & 0xff) << 24);
458
                            if (($absoluteOffset >= -$currentPosition) && ($absoluteOffset < $this->intelFilesize)) {
459
                                $referenceOffset = ($absoluteOffset >= 0) ? $absoluteOffset - $currentPosition : $absoluteOffset + $this->intelFilesize;
460
                                $result[$i] = $referenceOffset;
461
                                $result[$i + 1] = $referenceOffset >> 8;
462
                                $result[$i + 2] = $referenceOffset >> 16;
463
                                $result[$i + 3] = $referenceOffset >> 24;
464
                            }
465
                            $i += 4;
466
                            $currentPosition += 5;
467
                        }
468
                    }
469
                }
470
            }
471
        }
472
473 26
        return implode('', array_map('chr', $result));
474
    }
475
}
476