Issues (17)

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.

lib/DataManager/ArrayManager.php (1 issue)

Labels
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
    Condorcet PHP - Election manager and results calculator.
4
    Designed for the Condorcet method. Integrating a large number of algorithms extending Condorcet. Expandable for all types of voting systems.
5
6
    By Julien Boudry and contributors - MIT LICENSE (Please read LICENSE.txt)
7
    https://github.com/julien-boudry/Condorcet
8
*/
9
declare(strict_types=1);
10
11
namespace CondorcetPHP\Condorcet\DataManager;
12
13
use CondorcetPHP\Condorcet\CondorcetVersion;
14
use CondorcetPHP\Condorcet\DataManager\DataHandlerDrivers\DataHandlerDriverInterface;
15
use CondorcetPHP\Condorcet\Throwable\CondorcetException;
16
17
abstract class ArrayManager implements \ArrayAccess, \Countable, \Iterator
18
{
19
    use CondorcetVersion;
20
21
        //////
22
23
    public static $CacheSize = 2000;
24
    public static $MaxContainerLength = 2000;
25
26
    protected $_Container = [];
27
    protected $_DataHandler = null;
28
    protected $_link = [];
29
30
    protected $_Cache = [];
31
    protected $_CacheMaxKey = 0;
32
    protected $_CacheMinKey = 0;
33
34
    protected $_cursor = null;
35
    protected $_counter = 0;
36
    protected $_maxKey = -1;
37
38
    public function __construct () {}
39
40
    public function __destruct ()
41
    {
42
        $this->regularize();
43
    }
44
45 1
    public function __clone ()
46
    {
47 1
        $this->_link = [];
48 1
    }
49
50 2
    public function __sleep () : array
51
    {
52 2
        $this->regularize();
53 2
        $this->clearCache();
54 2
        $this->rewind();
55
56 2
        return ['_Container','_DataHandler','_link'];
57
    }
58
59 2
    public function __wakeup ()
60
    {
61 2
        $this->resetMaxKey();
62 2
        $this->resetCounter();
63 2
    }
64
65
66
/////////// Implement ArrayAccess ///////////
67
68 131
    public function offsetSet($offset, $value) : void
69
    {
70 131
        if ($offset === null) :
71 131
            $this->_Container[++$this->_maxKey] = $value;
72 131
            ++$this->_counter;
73
        else :
74 1
            $state = $this->keyExist($offset);
75 1
            $this->_Container[$offset] = $value;
76
77 1
            if (!$state) :
78
                ++$this->_counter;
79
80
                if ($offset > $this->_maxKey) :
81
                    $this->_maxKey = $offset;
82
                endif;
83
84
                ksort($this->_Container,SORT_NUMERIC);
85 1
            elseif ($this->_DataHandler !== null) :
86 1
                $this->_DataHandler->deleteOneEntity($offset, true);
87
            endif;
88
89 1
            $this->clearCache();
90
        endif;
91
92 131
        $this->checkRegularize();
93 131
    }
94
95
    // Use by isset() function, must return false if offset value is null.
96
    public function offsetExists($offset) : bool
97
    {
98
        return ( isset($this->_Container[$offset]) || ($this->_DataHandler !== null && $this->_DataHandler->selectOneEntity($offset) !== false) ) ? true : false ;
99
    }
100
101 8
    public function offsetUnset($offset) : void
102
    {
103 8
        if ($this->keyExist($offset)) :
104 8
            if (array_key_exists($offset, $this->_Container)) :
105 8
                $this->preDeletedTask($this->_Container[$offset]);
106 8
                unset($this->_Container[$offset]);
107
            else :
108 1
                if (array_key_exists($offset, $this->_Cache)) :
109 1
                    $this->preDeletedTask($this->_Cache[$offset]);
110 1
                    unset($this->_Cache[$offset]);
111
                endif;
112
113 1
                $this->_DataHandler->deleteOneEntity($offset, false);
114
            endif;
115
116 8
            --$this->_counter;
117
        endif;
118 8
    }
119
120 104
    public function offsetGet($offset)
121
    {
122 104
        if (isset($this->_Container[$offset])) :
123 102
            return $this->_Container[$offset];
124 4
        elseif ($this->_DataHandler !== null) :
125 4
            if (array_key_exists($offset, $this->_Cache)) :
126 4
                return $this->_Cache[$offset];
127
            else :
128 4
                $oneEntity = $this->_DataHandler->selectOneEntity($offset);
129 4
                if ($oneEntity === false) :
130
                    return null;
131
                else : 
132 4
                    $this->_Cache[$offset] = $oneEntity;
133 4
                    return $oneEntity;
134
                endif;
135
            endif;
136
        else :
137
            return null;
138
        endif;
139
    }
140
141
142
/////////// Implement Iterator ///////////
143
144
    protected $valid = true;
145
146 103
    public function rewind() : void {
147 103
        $this->_cursor = null;
148 103
        $this->valid = true;
149
150 103
        reset($this->_Cache);
151 103
        reset($this->_Container);
152 103
    }
153
154 103
    public function current() {
155 103
        return $this->offsetGet($this->key());
156
    }
157
158 103
    public function key() : ?int
159
    {
160 103
        if ($this->_counter === 0) :
161
            return null;
162
        else :
163 103
            return $this->_cursor ?? $this->getFirstKey();
164
        endif;
165
    }
166
167 103
    public function next() : void
168
    {
169 103
        $oldCursor = $this->_cursor;
170
171 103
        if ($this->_cursor >= $this->_maxKey) :
172
            // Do nothing
173 87
        elseif (!$this->isUsingHandler()) :
174 84
            $this->setCursorOnNextKeyInArray($this->_Container);
175
        else :
176 4
            $this->populateCache();
177 4
            $this->setCursorOnNextKeyInArray($this->_Cache);
178
        endif;
179
180 103
        if ($this->_cursor === $oldCursor) :
181 102
            $this->valid = false;
182
        endif;
183 103
    }
184
185 87
        protected function setCursorOnNextKeyInArray (array &$array) : void
186
        {
187 87
            next($array);
188 87
            $arrayKey = key($array);
189
190 87
            if ($arrayKey > $this->key()) :
191 87
                $this->_cursor = $arrayKey;
192
            endif;
193 87
        }
194
195 103
    public function valid() : bool {
196 103
        return ($this->_counter !== 0) ? $this->valid : false;
197
    }
198
199
200
/////////// Implement Countable ///////////
201
202 16
    public function count () : int {
203 16
        return $this->_counter;
204
    }
205
206
/////////// Array Methods ///////////
207
208 14
    public function getFullDataSet () : array
209
    {
210 14
        if ($this->isUsingHandler()) :
211 1
            $this->regularize();
212 1
            $this->clearCache();
213
214 1
            return $this->_Cache = $this->_DataHandler->selectRangeEntitys(0,$this->_maxKey + 1);
215
        else :
216 13
            return $this->_Container;
217
        endif;
218
    }
219
220 9
    public function keyExist ($offset) : bool
221
    {
222 9
        if ( array_key_exists($offset, $this->_Container) || ($this->_DataHandler !== null && $this->_DataHandler->selectOneEntity($offset) !== false) ) :
223 9
            return true;
224
        else  :
225 1
            return false;
226
        endif;
227
    }
228
229 103
    public function getFirstKey () : int
230
    {
231 103
        $r = array_keys($this->_Container);
232
233 103
        if ($this->_DataHandler !== null) :
234 4
            $r[] = $this->_DataHandler->selectMinKey();
235
        endif;
236
237 103
        return (int) min($r);
238
    }
239
240 9
    public function getContainerSize () : int
241
    {
242 9
        return count($this->_Container);
243
    }
244
245 1
    public function getCacheSize () : int
246
    {
247 1
        return count($this->_Cache);
248
    }
249
250 1
    public function debugGetCache () : array
251
    {
252 1
        return $this->_Cache;
253
    }
254
255
256
/////////// HANDLER API ///////////
257
258
    abstract protected function preDeletedTask ($object) : void;
259
260 9
    public function regularize () : bool
261
    {
262 9
        if (!$this->isUsingHandler() || empty($this->_Container)) :
263 9
            return false;
264
        else :
265 6
            $this->_DataHandler->insertEntitys($this->_Container);
266 6
            $this->_Container = [];
267 6
            return true;
268
        endif;
269
    }
270
271 131
    public function checkRegularize () : bool
272
    {
273 131
        if ( $this->_DataHandler !== null && self::$MaxContainerLength <= $this->getContainerSize() ) :
274 4
            $this->regularize();
275 4
            return true;
276
        else :
277 131
            return false;
278
        endif;
279
    }
280
281 4
    protected function populateCache () : void
282
    {
283 4
        $this->regularize();
284
285 4
        $currentKey = $this->key();
286
287 4
        if ( empty($this->_Cache) || $currentKey >= $this->_CacheMaxKey || $currentKey < $this->_CacheMinKey ) :
288 4
            $this->clearCache();
289 4
            $this->_Cache = $this->_DataHandler->selectRangeEntitys($currentKey, self::$CacheSize);
290
291 4
            $keys = array_keys($this->_Cache);
292 4
            $this->_CacheMaxKey = max($keys);
293 4
            $this->_CacheMinKey = min($keys);
294
        endif;
295 4
    }
296
297 7
    public function clearCache () : void
298
    {
299 7
        foreach ($this->_Cache as $e) :
300 5
            $this->preDeletedTask($e);
301
        endforeach;
302
303 7
        $this->_Cache = [];
304 7
        $this->_CacheMaxKey = 0;
305 7
        $this->_CacheMinKey = 0;
306 7
    }
307
308 100
    public function isUsingHandler ()
309
    {
310 100
        return $this->_DataHandler !== null;
311
    }
312
313
/////////// HANDLER INTERRACTION ///////////
314
315 9
    public function resetCounter () : int
316
    {
317 9
        return $this->_counter = $this->getContainerSize() + ( $this->isUsingHandler() ? $this->_DataHandler->countEntitys() : 0 );
318
    }
319
320 9
    public function resetMaxKey () : ?int
321
    {
322 9
        $this->resetCounter();
323
324 9
        if ($this->count() < 1) :
325 7
            $this->_maxKey = -1;
326 7
            return null;
327
        else :
328 3
            $maxContainerKey = empty($this->_Container) ? null : max(array_keys($this->_Container));
329 3
            $maxHandlerKey = $this->_DataHandler !== null ? $this->_DataHandler->selectMaxKey() : null;
330
331 3
            return $this->_maxKey = max( $maxContainerKey,$maxHandlerKey );
332
        endif;
333
    }
334
335 7
    public function importHandler (DataHandlerDriverInterface $handler) : bool
336
    {
337 7
        if ($handler->countEntitys() === 0) :
338 7
            $this->_DataHandler = $handler;
339 7
            $this->_DataHandler->_dataContextObject = $this->getDataContextObject();
0 ignored issues
show
Accessing _dataContextObject on the interface CondorcetPHP\Condorcet\D...aHandlerDriverInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
340
341
            try {
342 7
                $this->regularize();
343
            } catch (\Exception $e) {
344
                $this->_DataHandler = null;
345
                $this->resetCounter();
346
                $this->resetMaxKey();
347
                throw $e;
348
            }
349
350 7
            $this->resetCounter();
351 7
            $this->resetMaxKey();
352
353 7
            return true;
354
        else :
355
            throw new CondorcetException;
356
        endif;
357
    }
358
359 1
    public function closeHandler () : void
360
    {
361 1
        if ($this->_DataHandler !== null) :
362 1
            $this->regularize();
363 1
            $this->clearCache();
364
365 1
            $this->_Container = $this->_DataHandler->selectRangeEntitys(0,$this->_maxKey + 1);
366
367 1
            $this->_DataHandler = null;
368
369 1
            $this->resetCounter();
370 1
            $this->resetMaxKey();
371
        endif;
372 1
    }
373
374
    abstract public function getDataContextObject () : DataContextInterface;
375
}
376