Issues (35)

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.

debug/Frame.php (3 issues)

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 namespace nyx\diagnostics\debug;
2
3
// External dependencies
4
use nyx\core;
5
use nyx\utils;
6
7
/**
8
 * Frame
9
 *
10
 * Represents a single frame from a diagnostic inspection, ie. from a stack trace.
11
 *
12
 * @package     Nyx\Diagnostics\Debug
13
 * @version     0.1.0
14
 * @author      Michal Chojnacki <[email protected]>
15
 * @copyright   2012-2016 Nyx Dev Team
16
 * @link        http://docs.muyo.io/nyx/diagnostics/debug.html
17
 * @todo        setData() validation.
18
 */
19
class Frame implements core\interfaces\Serializable
20
{
21
    /**
22
     * The traits of a Frame instance.
23
     */
24
    use core\traits\Serializable;
25
    use utils\traits\Jetget;
26
27
    /**
28
     * @var int     The line in which the error occurred.
29
     */
30
    private $line;
31
32
    /**
33
     * @var string  The namespace the error occurred in, if any.
34
     */
35
    private $namespace;
36
37
    /**
38
     * @var string  The fully-qualified name (ie. with namespace) of the class the error occurred in, if any.
39
     */
40
    private $class;
41
42
    /**
43
     * @var string  The short name (ie. without namespace) of the class the error occurred in, if any.
44
     */
45
    private $shortClass;
46
47
    /**
48
     * @var string  The name of the function/method the error occurred in.
49
     */
50
    private $function;
51
52
    /**
53
     * @var string  The type of the error.
54
     */
55
    private $type;
56
57
    /**
58
     * @var array   The context the error occurred in.
59
     */
60
    private $args;
61
62
    /**
63
     * @var string  The path to the file the error occurred in.
64
     */
65
    private $file;
66
67
    /**
68
     * @var int     The nesting limit of flattened args.
69
     */
70
    private $nestingLimit = 10;
71
72
    /**
73
     * @var array   An array of cached file paths => file contents. Kept static to reduce IO overhead when
74
     *              multiple Frames are assigned to the same files.
75
     */
76
    private static $files;
77
78
    /**
79
     * Constructs the Frame.
80
     *
81
     * @param   array   $data   The frame's data, in the format returned by \Exception::getTrace().
82
     */
83
    public function __construct(array $data)
84
    {
85
        $this->setData($data);
86
    }
87
88
    /**
89
     * Returns the Frame's data as an array.
90
     *
91
     * @return  array   $data   The Frame's data, in the same format as returned by \Exception::getTrace().
92
     */
93
    public function getData() : array
94
    {
95
        return [
96
            'file'     => $this->file,
97
            'line'     => $this->line,
98
            'function' => $this->function,
99
            'class'    => $this->class,
100
            'type'     => $this->type,
101
            'args'     => $this->args
102
        ];
103
    }
104
105
    /**
106
     * Sets the Frame's data.
107
     *
108
     * @param   array   $data   The Frame's data, in the same format as returned by \Exception::getTrace().
109
     */
110
    public function setData(array $data)
111
    {
112
        $this->line     = isset($data['line']) ? $data['line'] : null;
113
        $this->class    = isset($data['class']) ? $data['class'] : null;
114
        $this->function = isset($data['function']) ? $data['function'] : null;
115
        $this->type     = isset($data['type']) ? $data['type'] : null;
116
        $this->args     = isset($data['args']) ? (array) $data['args'] : [];
117
        $this->file     = isset($data['file']) ? $data['file'] : null;
118
119
        // If we're dealing with a class, try to get its namespace and short name.
120
        if (null !== $this->class) {
121
            $parts = explode('\\', $this->class);
122
123
            $this->shortClass = array_pop($parts);
124
            $this->namespace  = implode('\\', $parts);
125
        }
126
    }
127
128
    /**
129
     * Returns the line which got executed resulting in the inspected trace.
130
     *
131
     * @return  int|null
132
     */
133
    public function getLine()
134
    {
135
        return $this->line;
136
    }
137
138
    /**
139
     * Returns the name of the class which got executed resulting in the inspected trace.
140
     *
141
     * @return  string|null
142
     */
143
    public function getClass()
144
    {
145
        return $this->class;
146
    }
147
148
    /**
149
     * Returns the namespace of the class which got executed resulting in the inspected trace.
150
     *
151
     * @return  string|null
152
     */
153
    public function getNamespace()
154
    {
155
        return $this->namespace;
156
    }
157
158
    /**
159
     * Returns the shortened name (without the namespace) of the class which got executed resulting in the
160
     * inspected trace.
161
     *
162
     * @return  string|null
163
     */
164
    public function getShortClass()
165
    {
166
        return $this->shortClass;
167
    }
168
169
    /**
170
     * Returns the function/method which got executed resulting in the inspected trace.
171
     *
172
     * @return  string|null
173
     */
174
    public function getFunction()
175
    {
176
        return $this->function;
177
    }
178
179
    /**
180
     * Returns the type of the function/method call (static or dynamic).
181
     *
182
     * @return  string|null
183
     */
184
    public function getType()
185
    {
186
        return $this->type;
187
    }
188
189
    /**
190
     * Returns the arguments which were passed to the function resulting in the inspected trace.
191
     *
192
     * @return  array
193
     */
194
    public function getArgs() : array
195
    {
196
        return $this->args;
197
    }
198
199
    /**
200
     * Returns the path to the file assigned to the current frame.
201
     *
202
     * @return  string
203
     */
204
    public function getFile()
205
    {
206
        return $this->file;
207
    }
208
209
    /**
210
     * Returns the contents of the file assigned to this frame as a string.
211
     *
212
     * @return  string|bool     Returns either the contents of the assigned file or false if no file is assigned
213
     *                          or its contents could not be fetched.
214
     */
215
    public function getFileContents()
216
    {
217
        // No point in continuing if there is no file assigned to this frame.
218
        if (!$this->file || $this->file === 'Unknown') {
219
            return false;
220
        }
221
222
        // If the assigned file's contents are already cached, return them right away.
223
        // Note: "False" might also be cached instead of the actual file contents if retrieval
224
        // of the contents failed once already.
225
        if (isset(static::$files[$this->file])) {
0 ignored issues
show
Since $files is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $files to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
226
            return static::$files[$this->file];
0 ignored issues
show
Since $files is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $files to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
227
        }
228
229
        // Otherwise grab the contents, cache them and return them.
230
        return static::$files[$this->file] = file_get_contents($this->file);
0 ignored issues
show
Since $files is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $files to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
231
    }
232
233
    /**
234
     * Returns the contents of the file assigned to this frame as an array of lines optionally sliced from
235
     * the given starting line to the given ending line. The arguments used work in exactly the same way as
236
     * {@see array_splice()}.
237
     *
238
     * Note: Lines are 0-indexed.
239
     *
240
     * @param   int $offset     The starting offset.
241
     * @param   int $length     The length of the resulting subset.
242
     * @return  string[]|null   The resulting array of lines or an empty array when no file contents are available.
243
     */
244
    public function getFileLines(int $offset = 0, int $length = null) : array
245
    {
246
        // Return null right away if we are not able to grab the file contents for any reason.
247
        if (!$contents = $this->getFileContents()) {
248
            return [];
249
        }
250
251
        // Explode the contents into an array by line breaks and return the slice. Note: Normally we'd simply read
252
        // the contents into an array directly by using file(), but to avoid code duplication and to keep caching
253
        // simple it's done as-is.
254
        return array_slice(explode("\n", $contents), $offset, $length, true);
255
    }
256
257
    /**
258
     * Returns the file path (if present) with the part common for all frames replaced by an ellipsis and slashes
259
     * replaced by soft slashes for presentation purposes (word wrapping).
260
     *
261
     * @return  string
262
     * @todo    Replace the dirname() calls with a required string parameter for the path which shall get cut out.
263
     */
264
    public function getPrettyPath()
265
    {
266
        if ($path = $this->file) {
267
            $dirname = dirname(dirname(dirname(dirname(dirname(dirname(__DIR__))))));
268
            $path = str_replace($dirname, "…", $path);
269
        }
270
271
        return $path;
272
    }
273
274
    /**
275
     * {@inheritDoc}
276
     */
277
    public function serialize()
278
    {
279
        $data = $this->toArray();
280
281
        !empty($data['args']) && $data['args'] = $this->flattenArgs($data['args']);
282
283
        return serialize($data);
284
    }
285
286
    /**
287
     * {@inheritDoc}
288
     */
289
    public function unserialize($data)
290
    {
291
        $this->setData(unserialize($data));
292
    }
293
294
    /**
295
     * {@inheritDoc}
296
     */
297
    public function toArray() : array
298
    {
299
        return $this->getData();
300
    }
301
302
    /**
303
     * Flattens the args to make them easier to serialize.
304
     *
305
     * @param   array   $args   The args to flatten.
306
     * @param   int     $level  The current nesting depth.
307
     * @return  array           The flattened args.
308
     */
309
    protected function flattenArgs(array $args, $level = 0)
310
    {
311
        $result = [];
312
313
        foreach ($args as $key => $value) {
314
            if (is_object($value)) {
315
                $result[$key] = ['object', get_class($value)];
316
            } elseif (is_array($value)) {
317
                if ($level > $this->nestingLimit) {
318
                    $result[$key] = ['array', '*DEEP NESTED ARRAY*'];
319
                } else {
320
                    $result[$key] = ['array', $this->flattenArgs($value, ++$level)];
321
                }
322
            } elseif (null === $value) {
323
                $result[$key] = ['null', null];
324
            } elseif (is_bool($value)) {
325
                $result[$key] = ['boolean', $value];
326
            } elseif (is_resource($value)) {
327
                $result[$key] = ['resource', get_resource_type($value)];
328
            }
329
            // Special case of object, is_object will return false.
330
            elseif ($value instanceof \__PHP_Incomplete_Class) {
331
                $array = new \ArrayObject($value);
332
                $result[$key] = ['incomplete-object', $array['__PHP_Incomplete_Class_Name']];
333
            } else {
334
                $result[$key] = ['string', (string) $value];
335
            }
336
        }
337
338
        return $result;
339
    }
340
}
341