Example #1
0
function node_func($file, $conditional, $node, $current_scope, $current_class, $namespace = '')
{
    global $scope;
    if ($node instanceof \ast\Node) {
        $req = $opt = 0;
        $dc = ['return' => '', 'params' => []];
        if (!empty($node->docComment)) {
            $dc = parse_doc_comment($node->docComment);
        }
        $result = ['file' => $file, 'namespace' => $namespace, 'scope' => $current_scope, 'conditional' => $conditional, 'flags' => $node->flags, 'lineno' => $node->lineno, 'endLineno' => $node->endLineno, 'name' => strpos($current_scope, '::') === false ? $namespace . $node->name : $node->name, 'docComment' => $node->docComment, 'params' => node_paramlist($file, $node->children[0], $req, $opt, $dc, $namespace), 'required' => $req, 'optional' => $opt, 'ret' => '', 'oret' => '', 'ast' => $node->children[2]];
        if ($node->children[3] !== null) {
            $result['oret'] = ast_node_type($file, $node->children[3], $namespace);
            // Original return type
            $result['ret'] = ast_node_type($file, $node->children[3], $namespace);
            // This one changes as we walk the tree
        } else {
            // Check if the docComment has a return value specified
            if (!empty($dc['return'])) {
                if ($dc['return'] == 'static' || $dc['return'] == 'self' || $dc['return'] == '$this') {
                    if (strpos($current_scope, '::') !== false) {
                        list($dc['return'], ) = explode('::', $current_scope);
                    }
                }
                $result['oret'] = $dc['return'];
                $result['ret'] = $dc['return'];
            }
        }
        // Add params to local scope for user functions
        if ($file != 'internal') {
            $i = 1;
            foreach ($result['params'] as $k => $v) {
                if (empty($v['type'])) {
                    // If there is no type specified in PHP, check for a docComment
                    // We assume order in the docComment matches the parameter order in the code
                    if (!empty($dc['params'][$k]['type'])) {
                        $scope[$current_scope]['vars'][$v['name']] = ['type' => $dc['params'][$k]['type'], 'tainted' => false, 'tainted_by' => '', 'param' => $i];
                    } else {
                        $scope[$current_scope]['vars'][$v['name']] = ['type' => '', 'tainted' => false, 'tainted_by' => '', 'param' => $i];
                    }
                } else {
                    $scope[$current_scope]['vars'][$v['name']] = ['type' => $v['type'], 'tainted' => false, 'tainted_by' => '', 'param' => $i];
                }
                if (array_key_exists('def', $v)) {
                    $type = node_type($file, $namespace, $v['def'], $current_scope, $current_class);
                    if ($type === "NULL") {
                        add_type($current_scope, $v['name'], $type);
                        if (!empty($result['params'][$k]['type'])) {
                            $result['params'][$k]['type'] .= '|NULL';
                        }
                    } else {
                        if ($scope[$current_scope]['vars'][$v['name']]['type'] !== '') {
                            // Does the default value match the declared type?
                            if (!type_check($type, $scope[$current_scope]['vars'][$v['name']]['type'])) {
                                Log::err(Log::ETYPE, "Default value for {$scope[$current_scope]['vars'][$v['name']]['type']} \${$v['name']} can't be {$type}", $file, $node->lineno);
                            }
                        }
                    }
                }
                $i++;
            }
        }
        return $result;
    }
    assert(false, "{$node} was not an \\ast\\Node");
}
Example #2
0
File: pass1.php Project: nikic/phan
function node_func($file, $conditional, $node, $current_scope, $current_class, $namespace = '')
{
    global $scope, $classes;
    if ($node instanceof \ast\Node) {
        $req = $opt = 0;
        $dc = ['return' => '', 'params' => []];
        if (!empty($node->docComment)) {
            $dc = parse_doc_comment($node->docComment);
        }
        $result = ['file' => $file, 'namespace' => $namespace, 'scope' => $current_scope, 'conditional' => $conditional, 'flags' => $node->flags, 'lineno' => $node->lineno, 'endLineno' => $node->endLineno, 'name' => strpos($current_scope, '::') === false ? $namespace . $node->name : $node->name, 'docComment' => $node->docComment, 'params' => node_paramlist($file, $node->children[0], $req, $opt, $dc, $namespace), 'required' => $req, 'optional' => $opt, 'ret' => '', 'oret' => '', 'ast' => $node->children[2]];
        if (!empty($dc['deprecated'])) {
            $result['deprecated'] = true;
        }
        if ($node->children[3] !== null) {
            $result['oret'] = ast_node_type($file, $node->children[3], $namespace);
            // Original return type
            $result['ret'] = ast_node_type($file, $node->children[3], $namespace);
            // This one changes as we walk the tree
        } else {
            // Check if the docComment has a return value specified
            if (!empty($dc['return'])) {
                // We can't actually figure out 'static' at this point, but fill it in regardless. It will be partially correct
                if ($dc['return'] == 'static' || $dc['return'] == 'self' || $dc['return'] == '$this') {
                    if (strpos($current_scope, '::') !== false) {
                        list($dc['return'], ) = explode('::', $current_scope);
                    }
                }
                $result['oret'] = $dc['return'];
                $result['ret'] = $dc['return'];
            }
        }
        // Add params to local scope for user functions
        if ($file != 'internal') {
            $i = 1;
            foreach ($result['params'] as $k => $v) {
                if (empty($v['type'])) {
                    // If there is no type specified in PHP, check for a docComment
                    // We assume order in the docComment matches the parameter order in the code
                    if (!empty($dc['params'][$k]['type'])) {
                        $scope[$current_scope]['vars'][$v['name']] = ['type' => $dc['params'][$k]['type'], 'tainted' => false, 'tainted_by' => '', 'param' => $i];
                    } else {
                        $scope[$current_scope]['vars'][$v['name']] = ['type' => '', 'tainted' => false, 'tainted_by' => '', 'param' => $i];
                    }
                } else {
                    $scope[$current_scope]['vars'][$v['name']] = ['type' => $v['type'], 'tainted' => false, 'tainted_by' => '', 'param' => $i];
                }
                if (array_key_exists('def', $v)) {
                    $type = node_type($file, $namespace, $v['def'], $current_scope, empty($current_class) ? null : $classes[strtolower($current_class)]);
                    if ($scope[$current_scope]['vars'][$v['name']]['type'] !== '') {
                        // Does the default value match the declared type?
                        if ($type !== 'null' && !type_check($type, $scope[$current_scope]['vars'][$v['name']]['type'])) {
                            Log::err(Log::ETYPE, "Default value for {$scope[$current_scope]['vars'][$v['name']]['type']} \${$v['name']} can't be {$type}", $file, $node->lineno);
                        }
                    }
                    add_type($current_scope, $v['name'], strtolower($type));
                    // If we have no other type info about a parameter, just because it has a default value of null
                    // doesn't mean that is its type. Any type can default to null
                    if ($type === 'null' && !empty($result['params'][$k]['type'])) {
                        $result['params'][$k]['type'] = merge_type($result['params'][$k]['type'], strtolower($type));
                    }
                }
                $i++;
            }
            if (!empty($dc['vars'])) {
                foreach ($dc['vars'] as $var) {
                    if (empty($scope[$current_scope]['vars'][$var['name']])) {
                        $scope[$current_scope]['vars'][$var['name']] = ['type' => $var['type'], 'tainted' => false, 'tainted_by' => ''];
                    } else {
                        add_type($current_scope, $var['name'], $var['type']);
                    }
                }
            }
        }
        return $result;
    }
    assert(false, "{$node} was not an \\ast\\Node");
}
Example #3
0
function node_func($file, $conditional, $node, $current_scope, $namespace = '')
{
    global $scope;
    if ($node instanceof \ast\Node) {
        $req = $opt = 0;
        $dc = ['return' => '', 'params' => []];
        if (!empty($node->docComment)) {
            $dc = parse_doc_comment($node->docComment);
        }
        $result = ['file' => $file, 'scope' => $current_scope, 'conditional' => $conditional, 'flags' => $node->flags, 'lineno' => $node->lineno, 'endLineno' => $node->endLineno, 'name' => $namespace . $node->name, 'docComment' => $node->docComment, 'params' => node_paramlist($file, $node->children[0], $req, $opt, $dc), 'required' => $req, 'optional' => $opt, 'ast' => $node->children[2]];
        if ($node->children[3] !== null) {
            $result['oret'] = ast_node_type($node->children[3]);
            // Original return type
            $result['ret'] = ast_node_type($node->children[3]);
            // This one changes as we walk the tree
        } else {
            // Check if the docComment has a return value specified
            if (!empty($dc['return'])) {
                $result['oret'] = $dc['return'];
                $result['ret'] = $dc['return'];
            }
        }
        // Add params to local scope for user functions
        if ($file != 'internal') {
            $i = 1;
            foreach ($result['params'] as $k => $v) {
                if (empty($v['type'])) {
                    // If there is no type specified in PHP, check for a docComment
                    // We assume order in the docComment matches the parameter order in the code
                    if (!empty($dc['params'][$k]['type'])) {
                        $scope[$current_scope]['vars'][$v['name']] = ['type' => $dc['params'][$k]['type'], 'tainted' => false, 'tainted_by' => '', 'param' => $i];
                    } else {
                        if (!empty($v['def'])) {
                            $scope[$current_scope]['vars'][$v['name']] = ['type' => node_type($file, $v['def'], $current_scope), 'tainted' => false, 'tainted_by' => '', 'param' => $i];
                        } else {
                            $scope[$current_scope]['vars'][$v['name']] = ['type' => '', 'tainted' => false, 'tainted_by' => '', 'param' => $i];
                        }
                    }
                } else {
                    $scope[$current_scope]['vars'][$v['name']] = ['type' => $v['type'], 'tainted' => false, 'tainted_by' => '', 'param' => $i];
                }
                $i++;
            }
        }
        return $result;
    }
    assert(false, "{$node} was not an \\ast\\Node");
}