Issues (245)

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/AspectRegister.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
/**
4
 * \AppserverIo\Doppelgaenger\AspectRegister
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Bernhard Wick <[email protected]>
15
 * @copyright 2015 TechDivision GmbH - <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/appserver-io/doppelgaenger
18
 * @link      http://www.appserver.io/
19
 */
20
21
namespace AppserverIo\Doppelgaenger;
22
23
use AppserverIo\Doppelgaenger\Entities\Definitions\Advice;
24
use AppserverIo\Doppelgaenger\Entities\Definitions\Aspect;
25
use AppserverIo\Doppelgaenger\Entities\Definitions\AspectDefinition;
26
use AppserverIo\Doppelgaenger\Entities\Lists\AbstractTypedList;
27
use AppserverIo\Doppelgaenger\Entities\Lists\TypedList;
28
use AppserverIo\Doppelgaenger\Entities\PointcutExpression;
29
use AppserverIo\Doppelgaenger\Entities\Pointcuts\PointcutFactory;
30
use AppserverIo\Doppelgaenger\Entities\Definitions\Pointcut as PointcutDefinition;
31
use AppserverIo\Doppelgaenger\Entities\Pointcuts\PointcutPointcut;
32
use AppserverIo\Psr\MetaobjectProtocol\Aop\Annotations\Advices\After;
33
use AppserverIo\Psr\MetaobjectProtocol\Aop\Annotations\Advices\AfterReturning;
34
use AppserverIo\Psr\MetaobjectProtocol\Aop\Annotations\Advices\AfterThrowing;
35
use AppserverIo\Psr\MetaobjectProtocol\Aop\Annotations\Advices\Around;
36
use AppserverIo\Psr\MetaobjectProtocol\Aop\Annotations\Advices\Before;
37
use AppserverIo\Psr\MetaobjectProtocol\Aop\Annotations\Pointcut;
38
use Herrera\Annotations\Convert\ToArray;
39
use Herrera\Annotations\Tokenizer;
40
use Herrera\Annotations\Tokens;
41
42
/**
43
 * Class which knows about registered aspects to allow for checks of methods against all given pointcuts
44
 *
45
 * @author    Bernhard Wick <[email protected]>
46
 * @copyright 2015 TechDivision GmbH - <[email protected]>
47
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
48
 * @link      https://github.com/appserver-io/doppelgaenger
49
 * @link      http://www.appserver.io/
50
 */
51
class AspectRegister extends AbstractTypedList
52
{
53
54
    /**
55
     * Default constructor
56
     */
57
    public function __construct()
58
    {
59
        parent::__construct();
60
61
        $this->itemType = '\AppserverIo\Doppelgaenger\Entities\Definitions\Aspect';
62
        $this->defaultOffset = 'qualifiedName';
63
    }
64
65
    /**
66
     * Look up a certain advice based on a glob-like expression optionally containing aspect name and advice name
67
     *
68
     * @param string $adviceExpression Expression defining the search term
69
     *
70
     * @return array<\AppserverIo\Doppelgaenger\Entities\Definitions\Advice>
71
     */
72 View Code Duplication
    public function lookupAdvice($adviceExpression)
73
    {
74
        // clean the expression
75
        $adviceExpression = trim(ltrim(rtrim($adviceExpression, '()'), '\\'));
76
77
        // if there is an aspect name within the expression we have to filter our search range and cut the expression
78
        $container = $this->container;
79
        if (strpos($adviceExpression, '->')) {
80
            $aspectExpression = strstr($adviceExpression, '->', true);
81
            $container = $this->lookupAspects($aspectExpression);
82
            $adviceExpression = str_replace('->', '', strstr($adviceExpression, '->'));
83
        }
84
85
        $matches = array();
86
        foreach ($container as $aspect) {
87
            $matches = array_merge($matches, $this->lookupEntries($aspect->getAdvices(), $adviceExpression));
88
        }
89
90
        return $matches;
91
    }
92
93
    /**
94
     * Will narrow down the choice of aspects to make when looking up pointcuts or advices.
95
     * Just pass the expression to look up any of both
96
     *
97
     * @param string $expression Expression defining the search term
98
     *
99
     * @return array<\AppserverIo\Doppelgaenger\Entities\Definitions\Aspect>
100
     */
101
    public function lookupAspects($expression)
102
    {
103
        return $this->lookupEntries($this->container, $expression);
104
    }
105
106
    /**
107
     * Look up certain entities in a container based on their qualified name and a glob-like expression
108
     *
109
     * @param array|\Traversable $container  Traversable container we will look in
110
     * @param string             $expression Expression defining the search term
111
     *
112
     * @return array
113
     */
114
    protected function lookupEntries($container, $expression)
115
    {
116
117
        // clean the expression
118
        $expression = trim(ltrim(rtrim($expression, '()'), '\\'));
119
120
        // if we got the complete name of the aspect we can return it alone
121
        if ($this->entryExists($expression)) {
122
            return array($this->get($expression));
123
        }
124
125
        // as it seems we got something else we have to get all regex about
126
        $matches = array();
127
        foreach ($container as $entry) {
128
            if (fnmatch($expression, $entry->getQualifiedName())) {
129
                $matches[] = $entry;
130
            }
131
        }
132
133
        return $matches;
134
    }
135
136
    /**
137
     * Look up a certain advice based on a glob-like expression optionally containing aspect name and pointcut name
138
     *
139
     * @param string $pointcutExpression Expression defining the search term
140
     *
141
     * @return array<\AppserverIo\Doppelgaenger\Entities\Definitions\Pointcut>
142
     */
143 View Code Duplication
    public function lookupPointcuts($pointcutExpression)
144
    {
145
        // clean the expression
146
        $pointcutExpression = trim(ltrim(rtrim($pointcutExpression, '()'), '\\'));
147
148
        // if there is an aspect name within the expression we have to filter our search range and cut the expression
149
        $container = $this->container;
150
        if (strpos($pointcutExpression, '->')) {
151
            $aspectExpression = strstr($pointcutExpression, '->', true);
152
            $container = $this->lookupAspects($aspectExpression);
153
            $pointcutExpression = str_replace('->', '', strstr($pointcutExpression, '->'));
154
        }
155
156
        $matches = array();
157
        foreach ($container as $aspect) {
158
            $matches = array_merge($matches, $this->lookupEntries($aspect->getPointcuts(), $pointcutExpression));
159
        }
160
161
        return $matches;
162
    }
163
164
    /**
165
     * Will register a complete aspect to the AspectRegister.
166
     * This include its advices and pointcuts which can be looked up from this point on
167
     *
168
     * @param \AppserverIo\Doppelgaenger\Entities\Definitions\AspectDefinition $aspectDefinition Structure to register as an aspect
169
     *
170
     * @return null
171
     */
172
    public function register(AspectDefinition $aspectDefinition)
173
    {
174
175
        // create the new aspect and fill it with things we already know
176
        $aspect = new Aspect();
177
        $aspect->setName($aspectDefinition->getName());
178
        $aspect->setNamespace($aspectDefinition->getNamespace());
179
180
        // prepare the tokenizer we will need for further processing
181
        $needles = array(
182
            AfterReturning::ANNOTATION,
183
            AfterThrowing::ANNOTATION,
184
            After::ANNOTATION,
185
            Around::ANNOTATION,
186
            Before::ANNOTATION
187
        );
188
        $tokenizer = new Tokenizer();
189
        $tokenizer->ignore(
190
            array(
191
                'param',
192
                'return',
193
                'throws'
194
            )
195
        );
196
197
        // iterate the functions and filter out the ones used as advices
198
        $scheduledAdviceDefinitions = array();
199
        foreach ($aspectDefinition->getFunctionDefinitions() as $functionDefinition) {
0 ignored issues
show
The expression $aspectDefinition->getFunctionDefinitions() of type null|object<AppserverIo\...FunctionDefinitionList> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
200
            $foundNeedle = false;
201
            foreach ($needles as $needle) {
202
                // create the advice
203
                if (strpos($functionDefinition->getDocBlock(), '@' . $needle) !== false) {
204
                    $foundNeedle = true;
205
                    $scheduledAdviceDefinitions[$needle][] = $functionDefinition;
206
207
                    break;
208
                }
209
            }
210
211
            // create the pointcut
212
            if (!$foundNeedle && strpos($functionDefinition->getDocBlock(), '@' . Pointcut::ANNOTATION) !== false) {
213
                $pointcut = new PointcutDefinition();
214
                $pointcut->setName($functionDefinition->getName());
215
216
                $tokens = new Tokens($tokenizer->parse($functionDefinition->getDocBlock()));
217
218
                // convert to array and run it through our advice factory
219
                $toArray = new ToArray();
220
                $annotations = $toArray->convert($tokens);
221
222
                // create the entities for the join-points and advices the pointcut describes
223
                $pointcut->setPointcutExpression(new PointcutExpression(array_pop(array_pop($annotations)->values)));
224
                $aspect->getPointcuts()->add($pointcut);
225
            }
226
        }
227
        $this->add($aspect);
228
229
        // do the pointcut lookups where we will need the pointcut factory for later use
230
        $pointcutFactory = new PointcutFactory();
231
        foreach ($scheduledAdviceDefinitions as $codeHook => $hookedAdviceDefinitions) {
232
            foreach ($hookedAdviceDefinitions as $scheduledAdviceDefinition) {
233
                // create our advice
234
                $advice = new Advice();
235
                $advice->setAspectName($aspectDefinition->getQualifiedName());
236
                $advice->setName($scheduledAdviceDefinition->getName());
237
                $advice->setCodeHook((string) $codeHook);
238
239
                $tokens = new Tokens($tokenizer->parse($scheduledAdviceDefinition->getDocBlock()));
240
241
                // convert to array and run it through our advice factory
242
                $toArray = new ToArray();
243
                $annotations = $toArray->convert($tokens);
244
245
                // create the entities for the join-points and advices the pointcut describes
246
                foreach ($annotations as $annotation) {
247
                    $pointcut = $pointcutFactory->getInstance(array_pop($annotation->values));
248
                    if ($pointcut instanceof PointcutPointcut) {
249
                        // get the referenced pointcuts for the split parts of the expression
250
                        $expressionParts = explode(PointcutPointcut::EXPRESSION_CONNECTOR, $pointcut->getExpression());
251
252
                        // lookup all the referenced pointcuts
253
                        $referencedPointcuts = array();
254
                        foreach ($expressionParts as $expressionPart) {
255
                            $referencedPointcuts = array_merge($referencedPointcuts, $this->lookupPointcuts($expressionPart));
256
                        }
257
258
                        $pointcut->setReferencedPointcuts($referencedPointcuts);
259
                    }
260
261
                    $advice->getPointcuts()->add($pointcut);
262
                }
263
264
                $aspect->getAdvices()->add($advice);
265
            }
266
        }
267
268
        $this->set($aspectDefinition->getQualifiedName(), $aspect);
269
    }
270
}
271