Issues (29)

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/OLE/PpsRoot.php (2 issues)

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 Xls\OLE;
4
5
class PpsRoot extends PPS
6
{
7
    /**
8
     * @var
9
     */
10
    protected $smallBlockSize;
11
12
    /**
13
     * @var
14
     */
15
    protected $bigBlockSize;
16
17
    /**
18
     * @var
19
     */
20
    protected $rootFilePointer;
21
22
    /**
23
     * @param integer $timestamp A timestamp
24
     * @param PpsFile[] $children
25
     */
26
    public function __construct(
27
        $timestamp = null,
28
        $children = array()
29
    ) {
30
        parent::__construct(
31
            null,
32
            OLE::asc2Ucs('Root Entry'),
33
            self::PPS_TYPE_ROOT,
34
            null,
35
            null,
36
            null,
37
            $timestamp,
38
            null,
39
            $children
40
        );
41
    }
42
43
    /**
44
     * Method for saving the whole OLE container (including files).
45
     *
46
     * @param string $filename The name of the file where to save the OLE container
47
     * @throws \Exception
48
     * @return boolean
49
     */
50
    public function save($filename)
51
    {
52
        $this->openFile($filename);
53
54
        $this->setBlockSizes();
55
56
        // Make an array of PPS's (for Save)
57
        $list = array();
58
        self::setPointers($list, array($this));
59
60
        list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->calcSize($list);
61
62
        $this->saveHeader($iSBDcnt, $iBBcnt, $iPPScnt);
63
        $this->saveSmallData($list);
64
        $this->saveBigData($iSBDcnt, $list);
65
        $this->savePps($list);
66
        $this->saveBigBlockChain($iSBDcnt, $iBBcnt, $iPPScnt);
67
68
        fclose($this->rootFilePointer);
69
    }
70
71
    /**
72
     *
73
     */
74
    protected function setBlockSizes()
75
    {
76
        $this->bigBlockSize = pow(2, 9);
77
        $this->smallBlockSize = pow(2, 6);
78
    }
79
80
    /**
81
     * @param $filename
82
     *
83
     * @throws \Exception
84
     */
85
    protected function openFile($filename)
86
    {
87
        $this->rootFilePointer = @fopen($filename, "wb");
88
        if ($this->rootFilePointer === false) {
89
            throw new \Exception("Can't open $filename. It may be in use or protected.");
90
        }
91
    }
92
93
    /**
94
     * @param $size
95
     * @param $blockSize
96
     *
97
     * @return float
98
     */
99
    protected function getBlocksCount($size, $blockSize)
100
    {
101
        return floor($size / $blockSize) + (($size % $blockSize) ? 1 : 0);
102
    }
103
104
    /**
105
     * Calculate some numbers
106
     *
107
     * @param PPS[] $list Reference to an array of PPS's
108
     *
109
     * @return array The array of numbers
110
     */
111
    protected function calcSize($list)
112
    {
113
        $iSBcnt = 0;
114
        $iBBcnt = 0;
115
        foreach ($list as $item) {
116
            if (!$item->isFile()) {
117
                continue;
118
            }
119
120
            $size = $item->getSize();
121
            if ($size < self::DATA_SIZE_SMALL) {
122
                $iSBcnt += $this->getBlocksCount($size, $this->smallBlockSize);
123
            } else {
124
                $iBBcnt += $this->getBlocksCount($size, $this->bigBlockSize);
125
            }
126
        }
127
128
        $iSmallLen = $iSBcnt * $this->smallBlockSize;
129
        $iSlCnt = $this->getPointersPerBlock($this->bigBlockSize);
130
        $iSBDcnt = $this->getBlocksCount($iSBcnt, $iSlCnt);
131
        $iBBcnt += $this->getBlocksCount($iSmallLen, $this->bigBlockSize);
132
        $iBdCnt = $this->getPointersPerBlock($this->bigBlockSize, self::PPS_SIZE);
133
        $iPPScnt = $this->getBlocksCount(count($list), $iBdCnt);
134
135
        return array($iSBDcnt, $iBBcnt, $iPPScnt);
136
    }
137
138
    /**
139
     * Saving big data (PPS's with data bigger than OLE_DATA_SIZE_SMALL)
140
     *
141
     * @param integer $iStBlk
142
     * @param PPS[] &$list Reference to array of PPS's
143
     */
144
    public function saveBigData($iStBlk, &$list)
145
    {
146
        foreach ($list as $item) {
147
            $size = $item->getSize();
148
            if ($size >= self::DATA_SIZE_SMALL
149
                || ($item->isRoot() && $item->hasData())
150
            ) {
151
                $this->write($item->getData());
152
153
                if ($size % $this->bigBlockSize) {
154
                    $zeroByteCount = ($this->bigBlockSize - ($size % $this->bigBlockSize));
155
                    $this->write(str_repeat("\x00", $zeroByteCount));
156
                }
157
158
                // Set For PPS
159
                $item->setStartBlock($iStBlk);
160
                $iStBlk += $this->getBlocksCount($size, $this->bigBlockSize);
161
            }
162
        }
163
    }
164
165
    /**
166
     * get small data (PPS's with data smaller than OLE_DATA_SIZE_SMALL)
167
     *
168
     * @param PPS[] &$list Reference to array of PPS's
169
     * @return string
170
     */
171
    protected function saveSmallData(&$list)
172
    {
173
        $result = '';
174
        $iSmBlk = 0;
175
        foreach ($list as $item) {
176
            if (!$item->isFile()) {
177
                continue;
178
            }
179
180
            $size = $item->getSize();
181
            if ($size <= 0 || $size >= self::DATA_SIZE_SMALL) {
182
                continue;
183
            }
184
185
            $sbCount = $this->getBlocksCount($size, $this->smallBlockSize);
186
            // Add to SBD
187
            for ($j = 0; $j < $sbCount - 1; $j++) {
188
                $this->writeUlong($j + $iSmBlk + 1);
189
            }
190
            $this->writeUlong(-2);
191
192
            $result .= $item->getData();
193
194
            $exp = $size % $this->smallBlockSize;
195
            if ($exp) {
196
                $zeroByteCount = $this->smallBlockSize - $exp;
197
                $result .= str_repeat("\x00", $zeroByteCount);
198
            }
199
200
            $item->setStartBlock($iSmBlk);
201
            $iSmBlk += $sbCount;
202
        }
203
204
        $sbCount = $this->getPointersPerBlock($this->bigBlockSize);
205
        if ($iSmBlk % $sbCount) {
206
            $repeatCount = $sbCount - ($iSmBlk % $sbCount);
207
            $this->writeUlong(-1, $repeatCount);
208
        }
209
210
        $this->data = $result;
211
    }
212
213
    /**
214
     * Saves all the PPS's WKs
215
     *
216
     * @param PPS[] $list Reference to an array with all PPS's
217
     */
218
    protected function savePps(&$list)
219
    {
220
        // Save each PPS WK
221
        $raListCount = count($list);
222
        for ($i = 0; $i < $raListCount; $i++) {
223
            $this->write($list[$i]->getPpsWk());
224
        }
225
226
        // Adjust for Block
227
        $iCnt = count($list);
228
        $iBCnt = $this->getPointersPerBlock($this->bigBlockSize, self::PPS_SIZE);
229
        if ($iCnt % $iBCnt) {
230
            $zeroByteCount = ($iBCnt - ($iCnt % $iBCnt)) * self::PPS_SIZE;
231
            $this->write(str_repeat("\x00", $zeroByteCount));
232
        }
233
    }
234
235
    /**
236
     * @param     $value
237
     * @param int $count
238
     */
239
    protected function writeUlong($value, $count = 1)
240
    {
241
        $packed = pack("V", $value);
242
        $this->write(str_repeat($packed, $count));
243
    }
244
245
    /**
246
     * @param $data
247
     */
248
    protected function write($data)
249
    {
250
        fwrite($this->rootFilePointer, $data);
251
    }
252
253
    /**
254
     * Saving Big Block Depot
255
     *
256
     * @param integer $numSbBlocks - number of Smallblock depot blocks
257
     * @param integer $numBbBlocks - number of Bigblock depot blocks
258
     * @param integer $numPpsBlocks - number of PropertySetStorage blocks
259
     */
260
    protected function saveBigBlockChain($numSbBlocks, $numBbBlocks, $numPpsBlocks)
261
    {
262
        $info = $this->calcBigBlockChain($numSbBlocks, $numBbBlocks, $numPpsBlocks);
263
        $headerEntriesCount = $info["header_list_entries"];
264
        $entriesCount = $info["list_entries"];
265
        $entriesPerBlock = $info["entries_per_block"];
266
267
        if ($numSbBlocks > 0) {
268
            for ($i = 0; $i < $numSbBlocks - 1; $i++) {
269
                $this->writeUlong($i + 1);
270
            }
271
            $this->writeUlong(-2);
272
        }
273
274 View Code Duplication
        for ($i = 0; $i < $numBbBlocks - 1; $i++) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
275
            $this->writeUlong($i + $numSbBlocks + 1);
276
        }
277
        $this->writeUlong(-2);
278
279 View Code Duplication
        for ($i = 0; $i < $numPpsBlocks - 1; $i++) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
280
            $this->writeUlong($i + $numSbBlocks + $numBbBlocks + 1);
281
        }
282
        $this->writeUlong(-2);
283
284
        $this->writeUlong(0xFFFFFFFD, $info["FD_entries"]);
285
        $this->writeUlong(0xFFFFFFFC, $info["FC_entries"]);
286
287
        // Adjust for Block
288
        $allEntries = $numSbBlocks
289
            + $numBbBlocks
290
            + $numPpsBlocks
291
            + $info["FD_entries"]
292
            + $info["FC_entries"];
293
        if ($allEntries % $entriesPerBlock) {
294
            $rest = $entriesPerBlock - ($allEntries % $entriesPerBlock);
295
            $this->writeUlong(-1, $rest);
296
        }
297
298
        // Extra BDList
299
        if ($entriesCount > $headerEntriesCount) {
300
            $iN = 0;
301
            $iNb = 0;
302
            $lastEntryIdx = $entriesPerBlock - 1;
303
304
            for ($i = $headerEntriesCount; $i < $entriesCount; $i++, $iN++) {
305
                if ($iN >= $lastEntryIdx) {
306
                    $iN = 0;
307
                    $iNb++;
308
309
                    $val = $numSbBlocks
310
                        + $numBbBlocks
311
                        + $numPpsBlocks
312
                        + $info["FD_entries"]
313
                        + $iNb;
314
                    $this->writeUlong($val);
315
                }
316
317
                $this->writeUlong($numBbBlocks + $numSbBlocks + $numPpsBlocks + $i);
318
            }
319
320
            $allEntries = $entriesCount - $headerEntriesCount;
321
            if ($allEntries % $lastEntryIdx) {
322
                $rest = $lastEntryIdx - ($allEntries % $lastEntryIdx);
323
                $this->writeUlong(-1, $rest);
324
            }
325
326
            $this->writeUlong(-2);
327
        }
328
    }
329
330
    /**
331
     * Save OLE header
332
     *
333
     * @param integer $numSbBlocks - number of Smallblock depot blocks
334
     * @param integer $numBbBlocks - number of Bigblock depot blocks
335
     * @param integer $numPpsBlocks - number of PropertySetStorage blocks
336
     */
337
    public function saveHeader($numSbBlocks, $numBbBlocks, $numPpsBlocks)
338
    {
339
        $info = $this->calcBigBlockChain($numSbBlocks, $numBbBlocks, $numPpsBlocks);
340
        $headerEntriesCount = $info["header_list_entries"];
341
        $entriesCount = $info["list_entries"];
342
343
        $this->write(
344
            "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
345
            . pack("V4", 0, 0, 0, 0)
346
            . pack("v6", 0x3b, 0x03, -2, 9, 6, 0)
347
            . pack("V2", 0, 0)
348
            . pack("V", $entriesCount)
349
            . pack("V", $numSbBlocks + $numBbBlocks) //ROOT START
350
            . pack("V2", 0, 0x1000)
351
        );
352
353
        //Small Block Depot
354
        $value = ($numSbBlocks > 0) ? 0 : -2;
355
        $this->writeUlong($value);
356
        $this->writeUlong($numSbBlocks);
357
358
        // Extra BDList Start, Count
359
        if ($entriesCount < $headerEntriesCount) {
360
            $this->writeUlong(-2); // Extra BDList Start
361
            $this->writeUlong(0); // Extra BDList Count
362
        } else {
363
            $this->writeUlong($numSbBlocks + $numBbBlocks + $numPpsBlocks + $info["FD_entries"]);
364
            $this->writeUlong($info["FC_entries"]);
365
        }
366
367
        // BDList
368
        for ($i = 0; $i < $headerEntriesCount && $i < $entriesCount; $i++) {
369
            $this->writeUlong($numBbBlocks + $numSbBlocks + $numPpsBlocks + $i);
370
        }
371
372
        if ($i < $headerEntriesCount) {
373
            $repeatCount = $headerEntriesCount - $i;
374
            $this->writeUlong(-1, $repeatCount);
375
        }
376
    }
377
378
    /**
379
     * New method to calculate Bigblock chain
380
     *
381
     * @param integer $numSb - number of Smallblock depot blocks
382
     * @param integer $numBb - number of Bigblock depot blocks
383
     * @param integer $numPps - number of PropertySetStorage blocks
384
     * @return array
385
     */
386
    protected function calcBigBlockChain($numSb, $numBb, $numPps)
387
    {
388
        $totalBlocks = $numSb + $numBb + $numPps;
389
        $info = array(
390
            "entries_per_block" => $this->getPointersPerBlock($this->bigBlockSize),
391
            "header_list_entries" => $this->getPointersPerBlock($this->bigBlockSize - 0x4C),
392
            "entries" => $totalBlocks,
393
            "ext_list_entries" => 0,
394
            "FC_entries" => 0,
395
            "FD_entries" => $this->getNumberOfPointerBlocks($totalBlocks)
396
        );
397
398
        $info["list_entries"] = $this->getNumberOfPointerBlocks(
399
            $totalBlocks + $info["FD_entries"]
400
        );
401
402
        if ($info["list_entries"] <= $info["header_list_entries"]) {
403
            return $info;
404
        }
405
406
        return $this->calcBigBlockChainExtra($info);
407
    }
408
409
    /**
410
     * @param array $info
411
     *
412
     * @return array
413
     */
414
    protected function calcBigBlockChainExtra($info)
415
    {
416
        while (true) {
417
            $pointerBlocksCount = $this->getNumberOfPointerBlocks(
418
                $info["entries"] + $info["FD_entries"] + $info["FC_entries"]
419
            );
420
421
            if ($info["list_entries"] >= $pointerBlocksCount) {
422
                break;
423
            }
424
425
            $info["list_entries"] = $pointerBlocksCount;
426
            $info["ext_list_entries"] = $info["list_entries"] - $info["header_list_entries"];
427
            $info["FC_entries"] = $this->getNumberOfPointerBlocks(
428
                $info["ext_list_entries"]
429
            );
430
            $info["FD_entries"] = $this->getNumberOfPointerBlocks(
431
                $info["entries"] + $info["FD_entries"] + $info["FC_entries"]
432
            );
433
        }
434
435
        return $info;
436
    }
437
438
    /**
439
     * Calculates number of pointer blocks
440
     *
441
     * @param integer $numPointers - number of pointers
442
     *
443
     * @return int
444
     */
445
    protected function getNumberOfPointerBlocks($numPointers)
446
    {
447
        return $this->getBlocksCount($numPointers, $this->getPointersPerBlock($this->bigBlockSize));
448
    }
449
450
    /**
451
     * @param int $blockSize
452
     * @param int $pointerSize
453
     *
454
     * @return int
455
     */
456
    protected function getPointersPerBlock($blockSize, $pointerSize = self::LONG_INT_SIZE)
457
    {
458
        return intval(floor($blockSize / $pointerSize));
459
    }
460
}
461