!C99Shell v. 2.0 [PHP 7 Update] [25.02.2019]!

Software: nginx/1.23.4. PHP/5.6.40-65+ubuntu20.04.1+deb.sury.org+1 

uname -a: Linux foro-restaurado-2 5.15.0-1040-oracle #46-Ubuntu SMP Fri Jul 14 21:47:21 UTC 2023
aarch64
 

uid=33(www-data) gid=33(www-data) groups=33(www-data) 

Safe-mode: OFF (not secure)

/home/scripts/pba/phc-read-only/src/hir_to_mir/   drwxrwxr-x
Free 83.21 GB of 96.73 GB (86.02%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     Lower_control_flow.cpp (12.25 KB)      -rw-rw-r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 * phc -- the open source PHP compiler
 * See doc/license/README.license for licensing information
 *
 * Lower any control flow statements into conditional
 * gotos, and add necessary labels.
 */

// TODO we have to handle iterators too: 
//   http://www.php.net/manual/en/ref.spl.php
//   http://ramikayyali.com/archives/2005/02/25/iterators


#include <sstream>

#include "lib/Vector.h"

#include "Lower_control_flow.h"
#include "HIR_to_MIR.h"
#include "process_ir/General.h"

using namespace HIR;
using namespace std;

template <class T>
const char* get_attr_name ()
{
    if (T::ID == Break::ID) return "phc.codegen.break_label";
    if (T::ID == Continue::ID) return "phc.codegen.continue_label";
    return NULL;
}

void clear_attrs (Node* in)
{
    in->attrs->erase ("phc.codegen.break_label");
    in->attrs->erase ("phc.codegen.continue_label");
}

/* We increase the depth for any statement which works with break and continue.
 * We decrease it on the way back up. The labels are created by post_break,
 * stored in the labels stack, and used as necessary. */
template <class T>
void Lower_control_flow::add_label (Node* in, Statement_list *out)
{
    assert (break_levels.back () == in);
    assert (continue_levels.back () == in);

    // Not a great way to do this, sorry.
    const char* attr_name = get_attr_name<T> ();
    if (!in->attrs->has (attr_name))
        return;

    MIR::Label* label = dyc<MIR::Label> (in->attrs->get (attr_name));
    out->push_back (new FOREIGN (label->clone ()));
}

template <class T>
MIR::Label*
Lower_control_flow::get_label (Node* in)
{
    assert (break_levels.back () == in);
    assert (continue_levels.back () == in);

    // Not a great way to do this, sorry.
    const char* attr_name = get_attr_name<T> ();
    if (!in->attrs->has (attr_name))
        return NULL;

    return dyc<MIR::Label> (in->attrs->get (attr_name));
}

// Get IN's exit label, or create one for it, and return it.
template <class T>
MIR::Label* Lower_control_flow::exit_label (Node* in)
{
    const char* attr_name = get_attr_name <T> ();
    if (in->attrs->has (attr_name))
    {
        MIR::Label *label = dynamic_cast <MIR::Label*> (in->attrs->get (attr_name));
        assert (label);
        return label;
    }

    MIR::Label *label = MIR::fresh_label ();
    in->attrs->set (attr_name, label);
    return label;
}

MIR::VARIABLE_NAME* Lower_control_flow::fold_var (VARIABLE_NAME* in)
{
    return folder.fold_variable_name (in);
}


/* Convert
 *            if ($x) { y (); }
 *            else { z (); }
 * into
 *            if ($x) goto L1;
 *            else goto L2;
 *        L1:
 *            y ();
 *            goto L3;
 *        L2:
 *            z ();
 *            goto L3;
 *        L3:
 *
 * We only need two labels, since the first edge can be an implict
 * fall-through edge if we negate the condition, but this is more
 * readable and understandable, as it keeps the structure of the original
 * if-else statement. */
void Lower_control_flow::lower_if(If* in, Statement_list* out)
{
    // Don't lower them if they're already lowered
    MIR::Label *l1 = MIR::fresh_label ();
    MIR::Label *l2 = MIR::fresh_label ();
    MIR::Label *l3 = MIR::fresh_label ();

    // create the gotos
    MIR::Goto *l1_goto_l3 = new MIR::Goto (l3->label_name->clone ());
    MIR::Goto *l2_goto_l3 = new MIR::Goto (l3->label_name->clone ());

    // make the if
    MIR::Branch *branch = new MIR::Branch (
        fold_var (in->variable_name), 
        l1->label_name->clone (), 
        l2->label_name->clone ());

    // generate the code
    out->push_back (new FOREIGN (branch));
    out->push_back (new FOREIGN (l1));
    out->push_back_all (in->iftrue);
    out->push_back (new FOREIGN (l1_goto_l3));
    out->push_back (new FOREIGN (l2));
    out->push_back_all (in->iffalse);
    out->push_back (new FOREIGN (l2_goto_l3));
    out->push_back (new FOREIGN (l3));
}

void Lower_control_flow::post_if(If* in, Statement_list* out)
{
    lower_if (in, out);
}

/* Convert
 *            while ($x) { y (); }
 * into
 *        L0:
 *            y ();
 *            goto L0
 */

void Lower_control_flow::lower_loop (Loop* in, Statement_list* out)
{
    MIR::Label *l0 = MIR::fresh_label ();
    MIR::Goto *goto_l0 = new MIR::Goto (l0->label_name->clone ());

    // generate code
    out->push_back (new FOREIGN (l0));
    out->push_back_all (in->statements);
    out->push_back (new FOREIGN (goto_l0));
}

void Lower_control_flow::post_loop (Loop* in, Statement_list* out)
{
    add_label<Continue> (in, out);
    lower_loop (in, out);
    add_label<Break> (in, out);
    break_levels.pop_back ();
    continue_levels.pop_back ();
    clear_attrs (in);
}

/* Convert 
 *   foreach ($arr as $key => $value)
 *   {
 *         ...;
 *   }
 * into
 *            if (!is_array ($arr)) 
 *            {
 *                if (!is_object ($arr))
 *                {
 *                    trigger_error (\"Invalid argument supplied for foreach()\", E_USER_WARNING);"
 *                    goto L4;
 *                }
 *
 *                $arr = (array)($arr);
 *            }
 *            foreach_reset ($arr, iter); 
 *        L0:
 *            $T = foreach_has_key ($arr, iter);
 *            if ($T) goto L1; else goto L2;
 *        L1:
 *            $key = foreach_get_key ($arr, iter); // optional 
 *            $val = foreach_get_val ($arr, iter);
 *            ....  
 *        L3: // continues to here
 *            foreach_next ($arr, iter); 
 *            goto L0:
 *        L2: // breaks jump here
 *            foreach_end ($arr, iter);
 *        L4:
 */

void Lower_control_flow::lower_foreach (Foreach* in, Statement_list* out)
{
    /* We wrap a number of MIR nodes in foreign, but we need to convert some of
     * them first. */
    HIR::VARIABLE_NAME* cast_array_name = fresh_var_name ("LF");
    MIR::VARIABLE_NAME* array_name = fold_var (cast_array_name); // keep the attributes

    (*out
        << "if (!is_array ($" << in->arr << "))"
        << "{"
        << "    if (!is_object ($" << in->arr << "))"
        << "    {"
        << "        trigger_error (\"Invalid argument supplied for foreach()\", E_USER_WARNING);"
        << "        PHC_XXX();" // a goto will be added here
        << "    }"
        <<    "    else"
        << "        $" << cast_array_name << " = (array)($" << in->arr << ");"
        << "}"
        << "else"
        << "{"
        << "    $" << cast_array_name << " =" << (in->is_ref ? "&" : "") << " $" << in->arr << ";"
        << "}"
    ).to_pass (s("HIR-to-MIR"), in);


    // foreach_reset ($arr, iter); 
    MIR::HT_ITERATOR* iter = MIR::fresh_iter ();
    out->push_back (new FOREIGN (
        new MIR::Foreach_reset (array_name->clone (), iter)));


    // L0:
    MIR::Label* l0 = MIR::fresh_label ();
    out->push_back (new FOREIGN (l0));

    // $T = foreach_has_key ($arr, iter);
    VARIABLE_NAME* has_key = fresh_var_name ("THK");
    out->push_back (
        new Assign_var (
            has_key,
            false,
            new FOREIGN (
                new MIR::Foreach_has_key (
                    array_name->clone (),
                    iter->clone ()))));


    // if ($T) goto L1; else goto L2;
    MIR::Label* l1 = MIR::fresh_label ();
    MIR::Label* l2 = get_label<Break> (in);
    if (l2 == NULL) l2 = MIR::fresh_label ();

    out->push_back (new FOREIGN (
        new MIR::Branch (
            fold_var (has_key),
            l1->label_name->clone (), 
            l2->label_name->clone ())));


    // L1:
    out->push_back (new FOREIGN (l1));


    // $key = foreach_get_key ($arr, iter); 
    MIR::Foreach_get_key* get_key = new MIR::Foreach_get_key (
        array_name->clone (),
        iter->clone ());

    VARIABLE_NAME* key = in->key;
    if (key == NULL)
        key = fresh_var_name ("LCF_KEY_");

    out->push_back (
            new Assign_var (
                key,
                new FOREIGN (get_key)));
    

    out->push_back (
        new Assign_var(
            in->val->clone (),
            in->is_ref,
            new FOREIGN (
                new MIR::Foreach_get_val (
                    array_name->clone (),
                    iter->clone ()))));


    // ....  
    out->push_back_all (in->statements);


    // L3: // continues jump to here
    add_label<Continue> (in, out);


    // foreach_next ($arr, iter); 
    out->push_back (new FOREIGN (
            new MIR::Foreach_next (
                array_name->clone (),
                iter->clone ())));

    // goto L0:
    out->push_back (new FOREIGN (new MIR::Goto (l0->label_name->clone ())));


    // L2:
    out->push_back (new FOREIGN (l2)); // continues jump to here


    // foreach_end ($arr, iter);
    out->push_back (new FOREIGN (
        new MIR::Foreach_end (
            array_name->clone (),
            iter->clone ())));

    // L4:
    MIR::Label* l4 = MIR::fresh_label ();
    out->push_back (new FOREIGN (l4)); // scalars jump to here

    // HACK: Because we couldnt put a goto in the parsed code above, we put in a
    // marker PHC_XXX(). We'll replace that with a goto now.
    foreach (HIR::Statement*& stmt, *out)
    {
        if (stmt->match (new Eval_expr (new HIR::Method_invocation (NULL, new METHOD_NAME ("PHC_XXX"), new HIR::Actual_parameter_list))))
        {
            stmt = new FOREIGN (new MIR::Goto (l4->label_name->clone ()));
            break;
        }
    }

    // wrap it in a PHP script to call visit
    (new PHP_script (out))->visit (new Clone_blank_mixins<Node, Visitor> (in, new Node_list)); // TODO we should have nodes here
}

void Lower_control_flow::post_foreach(Foreach* in, Statement_list* out)
{
    lower_foreach (in, out);
    // we add the break and continue labels in lower_foreach
    break_levels.pop_back ();
    continue_levels.pop_back ();
    clear_attrs (in);
}


/* Transform:
 *        break $x;
 *    into:
 *        $TB1 = $x;
 *        if ($TB1 = 1) goto L1; else goto L2;
 *    L2:
 *        if ($TB1 = 2) goto L3; else goto L4;
 *    L4:
 *        if ($TB1 = 3) goto L5; else goto L6;
 *    L6:
 *        if ($TB1 = 4) goto L7; else goto L8;
 *    L8:
 *
 *    where L(2n) is the label at the end of the nth inner loop construct
 */
// TODO: what about 'break "my_string" (and then break '17')?
// TODO: FYI: Objects/strings evaluate to 0
template <class T>
void Lower_control_flow::lower_exit (T* in, Statement_list* out)
{
    Vector<Node*> *levels;
    if (Break::ID == in->ID) levels = &break_levels;
    if (Continue::ID == in->ID) levels = &continue_levels;
    assert (levels);
    int num_levels = (int)(levels->size ());


    int error_depth;
    // 'break', 'break 1', and all coefficients < 1 are all the same. 
    INT *_int = dynamic_cast<INT*> (in->expr);
    if (in->expr == NULL || (_int && _int->value <= 1))
    {
        error_depth = 1;
        in->expr = new INT (1);
        in->expr->clone_mixin_from (in);
    }
    else if (_int)
        error_depth = _int->value;
    else
        error_depth = -1; // we don't know


    // Check that we arent being asked to jump further than we know
    // we can go
    if (error_depth > num_levels || num_levels == 0)
    {
        // find a good node to put the error on
        Node* error_node = in->expr;
        if (error_node == NULL)
            error_node = in;

        if (error_depth == -1)
            error_depth = 1; // TODO need a better error message

        phc_error ("Cannot break/continue %d levels", error_node, error_depth);
    }

    // if we survived, we expect there to be a target
    assert (num_levels);


    if (error_depth != -1) // We know exactly where we're jumping to
    {
        // Create a label, pushback a goto to it, and attach it as an attribute
        // of the appropriate looping construct.
        Node* level = (*levels)[num_levels - error_depth];
        out->push_back (new FOREIGN (
            new MIR::Goto ((exit_label<T> (level))->label_name->clone ())));
    }
    else
    {
        // Otherwise we create a label and a goto for each possible loop, and attach
        // the label to the goto.
        //
        // $TB1 = $x;
        VARIABLE_NAME* lhs = fresh_var_name ("TB");
        out->push_back (
            new Assign_var (
                lhs,
                in->expr));

        // 1 branch and label per level:
        //        if ($TB1 = 1) goto L1; else goto L2;
        //    L2:
        Vector<Node*>::reverse_iterator i;
        int depth;
        for (i = levels->rbegin (), depth = 1; i != levels->rend (); i++, depth++)
        {
            // We break to depth 1 for any expr <= 1
            OP* op = new OP (new String ("=="));
            if (depth == 1)
                op = new OP (new String ("<="));

            //    if ($TB1 == depth) goto L1; else goto L2;
            MIR::Label* iffalse = MIR::fresh_label ();
            push_back_pieces ( // push the pieces from the eval_var back
                new FOREIGN (
                    new MIR::Branch (
                        (fold_var (eval (
                            new Bin_op (
                                lhs->clone(),
                                op,
                                eval (new INT (depth)))))),
                        exit_label<T> (*i)->label_name, // get the label from this depth
                        iffalse->label_name->clone ())),
                out);

            //    L2:
            out->push_back (new FOREIGN (iffalse));
        }
        assert (depth == num_levels + 1);

        // Print an error, and die with 255
        (*out
            <<    "echo (\"\nFatal error: Cannot break/continue $"
            << lhs
            << " levels in " << in->get_filename ()
            << " on line " << in->get_line_number () << "\n\");\n"
            << "die (255);"
        ).finish (in);

    }
}

void Lower_control_flow::post_break (Break* in, Statement_list* out)
{
    lower_exit<Break> (in, out);
}

void Lower_control_flow::post_continue (Continue* in, Statement_list* out)
{
    lower_exit<Continue> (in, out);
}


void Lower_control_flow::pre_control_flow (Statement* in, Statement_list* out)
{
    break_levels.push_back (in);
    continue_levels.push_back (in);
    out->push_back (in);
}


void Lower_control_flow::pre_loop(Loop* in, Statement_list* out)
{
    pre_control_flow (in, out);
}

void Lower_control_flow::pre_foreach(Foreach* in, Statement_list* out)
{
    pre_control_flow (in, out);
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.0 [PHP 7 Update] [25.02.2019] maintained by HackingTool | HackingTool | Generation time: 0.0083 ]--