mirror of
https://github.com/github/codeql.git
synced 2026-05-16 12:17:07 +02:00
Compare commits
3 Commits
codeql-cli
...
josefs/php
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77dc871b21 | ||
|
|
57ff0bb2c8 | ||
|
|
cea862bfb3 |
27
Cargo.lock
generated
27
Cargo.lock
generated
@@ -419,6 +419,23 @@ dependencies = [
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codeql-extractor-php"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"codeql-extractor",
|
||||
"encoding",
|
||||
"lazy_static",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"tree-sitter",
|
||||
"tree-sitter-php",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codeql-extractor-ruby"
|
||||
version = "0.1.0"
|
||||
@@ -2891,6 +2908,16 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4013970217383f67b18aef68f6fb2e8d409bc5755227092d32efb0422ba24b8"
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter-php"
|
||||
version = "0.23.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f066e94e9272cfe4f1dcb07a1c50c66097eca648f2d7233d299c8ae9ed8c130c"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"tree-sitter-language",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter-ql"
|
||||
version = "0.23.1"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
resolver = "2"
|
||||
members = [
|
||||
"shared/tree-sitter-extractor",
|
||||
"php/extractor",
|
||||
"ruby/extractor",
|
||||
"rust/extractor",
|
||||
"rust/extractor/macros",
|
||||
|
||||
59
php/BUILD.bazel
Normal file
59
php/BUILD.bazel
Normal file
@@ -0,0 +1,59 @@
|
||||
load("@rules_pkg//pkg:mappings.bzl", "pkg_filegroup")
|
||||
load("//misc/bazel:pkg.bzl", "codeql_pack", "codeql_pkg_files")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
alias(
|
||||
name = "dbscheme",
|
||||
actual = "//php/ql/lib:dbscheme",
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "dbscheme-stats",
|
||||
actual = "//php/ql/lib:dbscheme-stats",
|
||||
)
|
||||
|
||||
codeql_pkg_files(
|
||||
name = "dbscheme-group",
|
||||
srcs = [
|
||||
":dbscheme",
|
||||
":dbscheme-stats",
|
||||
],
|
||||
strip_prefix = None,
|
||||
)
|
||||
|
||||
pkg_filegroup(
|
||||
name = "db-files",
|
||||
srcs = [
|
||||
":dbscheme-group",
|
||||
"//php/downgrades",
|
||||
],
|
||||
)
|
||||
|
||||
codeql_pkg_files(
|
||||
name = "codeql-extractor-yml",
|
||||
srcs = [
|
||||
"codeql-extractor.yml",
|
||||
"//:LICENSE",
|
||||
],
|
||||
strip_prefix = None,
|
||||
)
|
||||
|
||||
codeql_pkg_files(
|
||||
name = "extractor-arch",
|
||||
exes = [
|
||||
"//php/extractor",
|
||||
],
|
||||
prefix = "tools/{CODEQL_PLATFORM}",
|
||||
)
|
||||
|
||||
codeql_pack(
|
||||
name = "php",
|
||||
srcs = [
|
||||
":codeql-extractor-yml",
|
||||
":dbscheme-group",
|
||||
":extractor-arch",
|
||||
"//php/downgrades",
|
||||
"//php/tools",
|
||||
],
|
||||
)
|
||||
36
php/codeql-extractor.yml
Normal file
36
php/codeql-extractor.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
name: "php"
|
||||
display_name: "PHP"
|
||||
version: 0.1.0
|
||||
column_kind: "utf8"
|
||||
legacy_qltest_extraction: true
|
||||
build_modes:
|
||||
- none
|
||||
github_api_languages:
|
||||
- PHP
|
||||
scc_languages:
|
||||
- PHP
|
||||
file_types:
|
||||
- name: php
|
||||
display_name: PHP files
|
||||
extensions:
|
||||
- .php
|
||||
- .phtml
|
||||
- .php3
|
||||
- .php4
|
||||
- .php5
|
||||
- .php7
|
||||
- .phps
|
||||
- .inc
|
||||
options:
|
||||
trap:
|
||||
title: Options pertaining to TRAP.
|
||||
type: object
|
||||
properties:
|
||||
compression:
|
||||
title: Controls compression for the TRAP files written by the extractor.
|
||||
description: >
|
||||
This option is only intended for use in debugging the extractor. Accepted
|
||||
values are 'gzip' (the default, to write gzip-compressed TRAP) 'zstd' (to
|
||||
write Zstandard-compressed TRAP) and 'none' (to write uncompressed TRAP).
|
||||
type: string
|
||||
pattern: "^(none|gzip|zstd)$"
|
||||
19
php/extractor/BUILD.bazel
Normal file
19
php/extractor/BUILD.bazel
Normal file
@@ -0,0 +1,19 @@
|
||||
load("//misc/bazel:rust.bzl", "codeql_rust_binary")
|
||||
load("//misc/bazel/3rdparty/tree_sitter_extractors_deps:defs.bzl", "aliases", "all_crate_deps")
|
||||
|
||||
exports_files(["Cargo.toml"])
|
||||
|
||||
codeql_rust_binary(
|
||||
name = "extractor",
|
||||
srcs = glob(["src/*.rs"]),
|
||||
aliases = aliases(),
|
||||
proc_macro_deps = all_crate_deps(
|
||||
proc_macro = True,
|
||||
),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = all_crate_deps(
|
||||
normal = True,
|
||||
) + [
|
||||
"//shared/tree-sitter-extractor",
|
||||
],
|
||||
)
|
||||
21
php/extractor/Cargo.toml
Normal file
21
php/extractor/Cargo.toml
Normal file
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "codeql-extractor-php"
|
||||
description = "CodeQL PHP extractor"
|
||||
version = "0.1.0"
|
||||
authors = ["GitHub"]
|
||||
edition = "2024"
|
||||
|
||||
# When updating these dependencies, run `misc/bazel/3rdparty/update_cargo_deps.sh`
|
||||
[dependencies]
|
||||
tree-sitter = ">= 0.23.0"
|
||||
tree-sitter-php = "0.23.11"
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
|
||||
rayon = "1.11.0"
|
||||
regex = "1.11.3"
|
||||
encoding = "0.2"
|
||||
lazy_static = "1.5.0"
|
||||
serde_json = "1.0.145"
|
||||
|
||||
codeql-extractor = { path = "../../shared/tree-sitter-extractor" }
|
||||
20
php/extractor/src/autobuilder.rs
Normal file
20
php/extractor/src/autobuilder.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::Args;
|
||||
|
||||
use codeql_extractor::autobuilder;
|
||||
|
||||
#[derive(Args)]
|
||||
pub struct Options {}
|
||||
|
||||
pub fn run(_: Options) -> std::io::Result<()> {
|
||||
let database = env::var("CODEQL_EXTRACTOR_PHP_WIP_DATABASE")
|
||||
.expect("CODEQL_EXTRACTOR_PHP_WIP_DATABASE not set");
|
||||
|
||||
autobuilder::Autobuilder::new("php", PathBuf::from(database))
|
||||
.include_extensions(&[".php", ".phtml", ".inc", ".php3", ".php4", ".php5", ".php7", ".phps"])
|
||||
.exclude_globs(&["**/.git", "**/vendor"])
|
||||
.size_limit("10m")
|
||||
.run()
|
||||
}
|
||||
142
php/extractor/src/extractor.rs
Normal file
142
php/extractor/src/extractor.rs
Normal file
@@ -0,0 +1,142 @@
|
||||
use clap::Args;
|
||||
use codeql_extractor::file_paths;
|
||||
use rayon::prelude::*;
|
||||
use std::collections::HashSet;
|
||||
use std::fs;
|
||||
use std::io::BufRead;
|
||||
use std::path::PathBuf;
|
||||
use tree_sitter::Language;
|
||||
|
||||
use codeql_extractor::{diagnostics, extractor, node_types, trap};
|
||||
|
||||
#[derive(Args)]
|
||||
pub struct Options {
|
||||
/// Sets a custom source archive folder
|
||||
#[arg(long)]
|
||||
source_archive_dir: String,
|
||||
|
||||
/// Sets a custom trap folder
|
||||
#[arg(long)]
|
||||
output_dir: String,
|
||||
|
||||
/// A text file containing the paths of the files to extract
|
||||
#[arg(long)]
|
||||
file_list: String,
|
||||
}
|
||||
|
||||
fn get_overlay_changed_files() -> Option<HashSet<PathBuf>> {
|
||||
let path = std::env::var("CODEQL_EXTRACTOR_PHP_OVERLAY_CHANGED_FILES").ok()?;
|
||||
let contents = fs::read_to_string(path).ok()?;
|
||||
Some(
|
||||
contents
|
||||
.lines()
|
||||
.filter(|l| !l.is_empty())
|
||||
.map(|l| PathBuf::from(l).canonicalize().unwrap_or_else(|_| PathBuf::from(l)))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn run(options: Options) -> std::io::Result<()> {
|
||||
extractor::set_tracing_level("php");
|
||||
tracing::info!("PHP extraction started");
|
||||
let diagnostics = diagnostics::DiagnosticLoggers::new("php");
|
||||
let mut main_thread_logger = diagnostics.logger();
|
||||
let num_threads = match codeql_extractor::options::num_threads() {
|
||||
Ok(num) => num,
|
||||
Err(e) => {
|
||||
main_thread_logger.write(
|
||||
main_thread_logger
|
||||
.new_entry("configuration-error", "Configuration error")
|
||||
.message(
|
||||
"{}; defaulting to 1 thread.",
|
||||
&[diagnostics::MessageArg::Code(&e)],
|
||||
)
|
||||
.severity(diagnostics::Severity::Warning),
|
||||
);
|
||||
1
|
||||
}
|
||||
};
|
||||
tracing::info!(
|
||||
"Using {} {}",
|
||||
num_threads,
|
||||
if num_threads == 1 {
|
||||
"thread"
|
||||
} else {
|
||||
"threads"
|
||||
}
|
||||
);
|
||||
let trap_compression =
|
||||
match trap::Compression::from_env("CODEQL_EXTRACTOR_PHP_OPTION_TRAP_COMPRESSION") {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
main_thread_logger.write(
|
||||
main_thread_logger
|
||||
.new_entry("configuration-error", "Configuration error")
|
||||
.message("{}; using gzip.", &[diagnostics::MessageArg::Code(&e)])
|
||||
.severity(diagnostics::Severity::Warning),
|
||||
);
|
||||
trap::Compression::Gzip
|
||||
}
|
||||
};
|
||||
drop(main_thread_logger);
|
||||
rayon::ThreadPoolBuilder::new()
|
||||
.num_threads(num_threads)
|
||||
.build_global()
|
||||
.unwrap();
|
||||
|
||||
let src_archive_dir = file_paths::path_from_string(&options.source_archive_dir);
|
||||
let trap_dir = file_paths::path_from_string(&options.output_dir);
|
||||
let file_list = fs::File::open(file_paths::path_from_string(&options.file_list))?;
|
||||
|
||||
let overlay_changed_files: Option<HashSet<PathBuf>> = get_overlay_changed_files();
|
||||
let path_transformer = file_paths::load_path_transformer()?;
|
||||
|
||||
let language: Language = tree_sitter_php::LANGUAGE_PHP.into();
|
||||
let schema = node_types::read_node_types_str("php", tree_sitter_php::PHP_NODE_TYPES)?;
|
||||
|
||||
let lines: std::io::Result<Vec<String>> = std::io::BufReader::new(file_list).lines().collect();
|
||||
let lines = lines?;
|
||||
lines
|
||||
.par_iter()
|
||||
.try_for_each(|line| -> std::io::Result<()> {
|
||||
let mut diagnostics_writer = diagnostics.logger();
|
||||
let path = PathBuf::from(line).canonicalize()?;
|
||||
match &overlay_changed_files {
|
||||
Some(changed_files) if !changed_files.contains(&path) => {
|
||||
return Ok(());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let src_archive_file =
|
||||
file_paths::path_for(&src_archive_dir, &path, "", path_transformer.as_ref());
|
||||
let source = std::fs::read(&path)?;
|
||||
let mut trap_writer = trap::Writer::new();
|
||||
tracing::info!("extracting: {}", path.display());
|
||||
extractor::extract(
|
||||
&language,
|
||||
"php",
|
||||
&schema,
|
||||
&mut diagnostics_writer,
|
||||
&mut trap_writer,
|
||||
path_transformer.as_ref(),
|
||||
&path,
|
||||
&source,
|
||||
&[],
|
||||
);
|
||||
|
||||
let trap_ext = format!(".{}", trap_compression.extension());
|
||||
let trap_file = file_paths::path_for(&trap_dir, &path, &trap_ext, path_transformer.as_ref());
|
||||
std::fs::create_dir_all(trap_file.parent().unwrap())?;
|
||||
trap_writer
|
||||
.write_to_file(&trap_file, trap_compression)
|
||||
.unwrap_or_else(|e| {
|
||||
tracing::error!("Failed to write trap file {}: {}", trap_file.display(), e);
|
||||
});
|
||||
|
||||
std::fs::create_dir_all(src_archive_file.parent().unwrap())?;
|
||||
std::fs::copy(&path, &src_archive_file)?;
|
||||
Ok(())
|
||||
})?;
|
||||
tracing::info!("PHP extraction completed");
|
||||
Ok(())
|
||||
}
|
||||
31
php/extractor/src/generator.rs
Normal file
31
php/extractor/src/generator.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use clap::Args;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use codeql_extractor::generator::{generate, language::Language};
|
||||
|
||||
#[derive(Args)]
|
||||
pub struct Options {
|
||||
/// Path of the generated dbscheme file
|
||||
#[arg(long)]
|
||||
dbscheme: PathBuf,
|
||||
|
||||
/// Path of the generated QLL file
|
||||
#[arg(long)]
|
||||
library: PathBuf,
|
||||
}
|
||||
|
||||
pub fn run(options: Options) -> std::io::Result<()> {
|
||||
codeql_extractor::extractor::set_tracing_level("php");
|
||||
|
||||
let languages = vec![Language {
|
||||
name: "Php".to_owned(),
|
||||
node_types: tree_sitter_php::PHP_NODE_TYPES,
|
||||
}];
|
||||
|
||||
generate(
|
||||
languages,
|
||||
options.dbscheme,
|
||||
options.library,
|
||||
"run the PHP extractor generate command",
|
||||
)
|
||||
}
|
||||
23
php/extractor/src/main.rs
Normal file
23
php/extractor/src/main.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
use clap::Parser;
|
||||
|
||||
mod autobuilder;
|
||||
mod extractor;
|
||||
mod generator;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about)]
|
||||
enum Cli {
|
||||
Extract(extractor::Options),
|
||||
Generate(generator::Options),
|
||||
Autobuild(autobuilder::Options),
|
||||
}
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
match cli {
|
||||
Cli::Extract(options) => extractor::run(options),
|
||||
Cli::Generate(options) => generator::run(options),
|
||||
Cli::Autobuild(options) => autobuilder::run(options),
|
||||
}
|
||||
}
|
||||
1822
php/php.dbscheme
Normal file
1822
php/php.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
0
php/php.dbscheme.stats
Normal file
0
php/php.dbscheme.stats
Normal file
10
php/ql/lib/Customizations.qll
Normal file
10
php/ql/lib/Customizations.qll
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Contains customizations to the standard library.
|
||||
*
|
||||
* This module is imported by `php.qll`, so any customizations defined here automatically
|
||||
* apply to all queries.
|
||||
*
|
||||
* Typical examples of customizations include adding new subclasses of abstract classes such as
|
||||
* the `Source` and `Sink` classes associated with the security queries to model frameworks
|
||||
* that are not covered by the standard library.
|
||||
*/
|
||||
70
php/ql/lib/codeql/Locations.qll
Normal file
70
php/ql/lib/codeql/Locations.qll
Normal file
@@ -0,0 +1,70 @@
|
||||
/** Provides classes for working with locations. */
|
||||
overlay[local]
|
||||
module;
|
||||
|
||||
import files.FileSystem
|
||||
|
||||
/**
|
||||
* A location as given by a file, a start line, a start column,
|
||||
* an end line, and an end column.
|
||||
*
|
||||
* For more information about locations see [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
class Location extends @location_default {
|
||||
/** Gets the file for this location. */
|
||||
File getFile() { locations_default(this, result, _, _, _, _) }
|
||||
|
||||
/** Gets the 1-based line number (inclusive) where this location starts. */
|
||||
int getStartLine() { locations_default(this, _, result, _, _, _) }
|
||||
|
||||
/** Gets the 1-based column number (inclusive) where this location starts. */
|
||||
int getStartColumn() { locations_default(this, _, _, result, _, _) }
|
||||
|
||||
/** Gets the 1-based line number (inclusive) where this location ends. */
|
||||
int getEndLine() { locations_default(this, _, _, _, result, _) }
|
||||
|
||||
/** Gets the 1-based column number (inclusive) where this location ends. */
|
||||
int getEndColumn() { locations_default(this, _, _, _, _, result) }
|
||||
|
||||
/** Gets the number of lines covered by this location. */
|
||||
int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
bindingset[this]
|
||||
pragma[inline_late]
|
||||
string toString() {
|
||||
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
|
||||
this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
|
||||
result = filepath + "@" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
exists(File f |
|
||||
locations_default(this, f, startline, startcolumn, endline, endcolumn) and
|
||||
filepath = f.getAbsolutePath()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this location starts strictly before the specified location. */
|
||||
pragma[inline]
|
||||
predicate strictlyBefore(Location other) {
|
||||
this.getStartLine() < other.getStartLine()
|
||||
or
|
||||
this.getStartLine() = other.getStartLine() and this.getStartColumn() < other.getStartColumn()
|
||||
}
|
||||
}
|
||||
|
||||
/** An entity representing an empty location. */
|
||||
class EmptyLocation extends Location {
|
||||
EmptyLocation() { empty_location(this) }
|
||||
}
|
||||
38
php/ql/lib/codeql/files/FileSystem.qll
Normal file
38
php/ql/lib/codeql/files/FileSystem.qll
Normal file
@@ -0,0 +1,38 @@
|
||||
/** Provides classes for working with files and folders. */
|
||||
overlay[local]
|
||||
module;
|
||||
|
||||
private import codeql.Locations
|
||||
private import codeql.util.FileSystem
|
||||
|
||||
private module Input implements InputSig {
|
||||
abstract class ContainerBase extends @container {
|
||||
abstract string getAbsolutePath();
|
||||
|
||||
ContainerBase getParentContainer() { containerparent(result, this) }
|
||||
|
||||
string toString() { result = this.getAbsolutePath() }
|
||||
}
|
||||
|
||||
class FolderBase extends ContainerBase, @folder {
|
||||
override string getAbsolutePath() { folders(this, result) }
|
||||
}
|
||||
|
||||
class FileBase extends ContainerBase, @file {
|
||||
override string getAbsolutePath() { files(this, result) }
|
||||
}
|
||||
|
||||
predicate hasSourceLocationPrefix = sourceLocationPrefix/1;
|
||||
}
|
||||
|
||||
private module Impl = Make<Input>;
|
||||
|
||||
class Container = Impl::Container;
|
||||
|
||||
class Folder = Impl::Folder;
|
||||
|
||||
/** A file. */
|
||||
class File extends Container, Impl::File {
|
||||
/** Holds if this file was extracted from ordinary source code. */
|
||||
predicate fromSource() { any() }
|
||||
}
|
||||
72
php/ql/lib/codeql/php/AST.qll
Normal file
72
php/ql/lib/codeql/php/AST.qll
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Provides classes representing the abstract syntax tree (AST) of PHP programs.
|
||||
*/
|
||||
|
||||
import codeql.Locations
|
||||
import ast.Call
|
||||
import ast.Control
|
||||
import ast.Expr
|
||||
import ast.Literal
|
||||
import ast.Function
|
||||
import ast.ClassLike
|
||||
import ast.Parameter
|
||||
import ast.Statement
|
||||
import ast.Variable
|
||||
private import ast.internal.AST
|
||||
private import ast.internal.TreeSitter
|
||||
private import Customizations
|
||||
|
||||
/**
|
||||
* A node in the abstract syntax tree. This class is the base class for all PHP
|
||||
* program elements.
|
||||
*/
|
||||
class AstNode extends TPhpAstNode {
|
||||
/**
|
||||
* Gets the name of a primary CodeQL class to which this node belongs.
|
||||
*/
|
||||
string getAPrimaryQlClass() { result = "???" }
|
||||
|
||||
/**
|
||||
* Gets a comma-separated list of the names of the primary CodeQL classes to
|
||||
* which this element belongs.
|
||||
*/
|
||||
final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
|
||||
|
||||
/** Gets a textual representation of this node. */
|
||||
cached
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the location of this node. */
|
||||
Location getLocation() { php_ast_node_location(this, result) }
|
||||
|
||||
/** Gets the file of this node. */
|
||||
final File getFile() { result = this.getLocation().getFile() }
|
||||
|
||||
/** Gets a child node of this `AstNode`. */
|
||||
AstNode getAChild() { php_ast_node_parent(result, this, _) }
|
||||
|
||||
/** Gets the `i`th child of this `AstNode`. */
|
||||
AstNode getChild(int i) { php_ast_node_parent(result, this, i) }
|
||||
|
||||
/** Gets the parent of this `AstNode`, if this node is not a root node. */
|
||||
AstNode getParent() { php_ast_node_parent(this, result, _) }
|
||||
|
||||
/** Gets the index of this node within its parent. */
|
||||
int getIndex() { php_ast_node_parent(this, _, result) }
|
||||
}
|
||||
|
||||
/** A PHP program (source file). */
|
||||
class Program extends AstNode, @php_program {
|
||||
override string getAPrimaryQlClass() { result = "Program" }
|
||||
|
||||
override string toString() { result = "program" }
|
||||
|
||||
/** Gets the `i`th statement in this program. */
|
||||
Stmt getStatement(int i) { php_program_child(this, i, result) }
|
||||
|
||||
/** Gets a statement in this program. */
|
||||
Stmt getAStatement() { result = this.getStatement(_) }
|
||||
|
||||
/** Gets the number of statements in this program. */
|
||||
int getNumberOfStatements() { result = count(int i | php_program_child(this, i, _)) }
|
||||
}
|
||||
9
php/ql/lib/codeql/php/CFG.qll
Normal file
9
php/ql/lib/codeql/php/CFG.qll
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Provides classes representing the control flow graph for PHP programs.
|
||||
*
|
||||
* This module re-exports the full CFG implementation from
|
||||
* `codeql.php.controlflow.ControlFlowGraph` and `codeql.php.controlflow.BasicBlocks`.
|
||||
*/
|
||||
|
||||
import codeql.php.controlflow.ControlFlowGraph
|
||||
import codeql.php.controlflow.BasicBlocks
|
||||
5
php/ql/lib/codeql/php/Customizations.qll
Normal file
5
php/ql/lib/codeql/php/Customizations.qll
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Contains customizations to the PHP CodeQL library.
|
||||
*/
|
||||
|
||||
import codeql.php.AST
|
||||
17
php/ql/lib/codeql/php/DataFlow.qll
Normal file
17
php/ql/lib/codeql/php/DataFlow.qll
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Provides classes for performing local (intra-procedural) and
|
||||
* global (inter-procedural) data flow analyses for PHP.
|
||||
*/
|
||||
|
||||
import codeql.Locations
|
||||
|
||||
/**
|
||||
* Provides classes for performing local (intra-procedural) and
|
||||
* global (inter-procedural) data flow analyses.
|
||||
*/
|
||||
module DataFlow {
|
||||
private import codeql.php.dataflow.internal.DataFlowImplSpecific
|
||||
private import codeql.dataflow.DataFlow
|
||||
import DataFlowMake<Location, PhpDataFlow>
|
||||
import Public
|
||||
}
|
||||
12
php/ql/lib/codeql/php/TaintTracking.qll
Normal file
12
php/ql/lib/codeql/php/TaintTracking.qll
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Provides classes for performing local (intra-procedural) and
|
||||
* global (inter-procedural) taint-tracking analyses for PHP.
|
||||
*/
|
||||
module TaintTracking {
|
||||
import codeql.php.dataflow.internal.TaintTrackingPublic
|
||||
private import codeql.php.dataflow.internal.DataFlowImplSpecific
|
||||
private import codeql.php.dataflow.internal.TaintTrackingImplSpecific
|
||||
private import codeql.dataflow.TaintTracking
|
||||
private import codeql.Locations
|
||||
import TaintFlowMake<Location, PhpDataFlow, PhpTaintTracking>
|
||||
}
|
||||
110
php/ql/lib/codeql/php/ast/Call.qll
Normal file
110
php/ql/lib/codeql/php/ast/Call.qll
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Provides classes for PHP call expressions.
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** A call expression (function call, method call, or static method call). */
|
||||
class Call extends Expr {
|
||||
Call() {
|
||||
this instanceof @php_function_call_expression or
|
||||
this instanceof @php_member_call_expression or
|
||||
this instanceof @php_nullsafe_member_call_expression or
|
||||
this instanceof @php_scoped_call_expression
|
||||
}
|
||||
|
||||
/** Gets the arguments of this call. */
|
||||
Arguments getArguments() { none() }
|
||||
|
||||
/** Gets the `i`th argument expression (unwrapped from Argument wrapper). */
|
||||
AstNode getArgument(int i) {
|
||||
exists(@php_argument arg |
|
||||
php_arguments_child(this.getArguments(), i, arg) and
|
||||
php_argument_def(arg, result)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets an argument of this call. */
|
||||
AstNode getAnArgument() { result = this.getArgument(_) }
|
||||
|
||||
/** Gets the number of arguments. */
|
||||
int getNumberOfArguments() { result = this.getArguments().getNumberOfArguments() }
|
||||
}
|
||||
|
||||
/** A function call expression (`func(...)` or `$var(...)`). */
|
||||
class FunctionCallExpr extends Call, @php_function_call_expression {
|
||||
override string getAPrimaryQlClass() { result = "FunctionCallExpr" }
|
||||
|
||||
/** Gets the function being called. */
|
||||
AstNode getFunction() { php_function_call_expression_def(this, _, result) }
|
||||
|
||||
/** Gets the arguments list. */
|
||||
override Arguments getArguments() { php_function_call_expression_def(this, result, _) }
|
||||
|
||||
/**
|
||||
* Gets the name of the function being called, if it is a simple name.
|
||||
*/
|
||||
string getFunctionName() {
|
||||
exists(Name n |
|
||||
n = this.getFunction() and
|
||||
result = n.getValue()
|
||||
)
|
||||
or
|
||||
exists(QualifiedName qn |
|
||||
qn = this.getFunction() and
|
||||
result = qn.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() { result = this.getFunctionName() + "(...)" }
|
||||
}
|
||||
|
||||
/** A method call expression (`$obj->method(...)`). */
|
||||
class MethodCallExpr extends Call, @php_member_call_expression {
|
||||
override string getAPrimaryQlClass() { result = "MethodCallExpr" }
|
||||
|
||||
/** Gets the object on which the method is called. */
|
||||
AstNode getObject() { php_member_call_expression_def(this, _, _, result) }
|
||||
|
||||
/** Gets the name of the method being called. */
|
||||
Name getMethodName() { php_member_call_expression_def(this, _, result, _) }
|
||||
|
||||
/** Gets the arguments list. */
|
||||
override Arguments getArguments() { php_member_call_expression_def(this, result, _, _) }
|
||||
|
||||
/** Gets the string name of the method being called. */
|
||||
string getMethodNameString() { result = this.getMethodName().getValue() }
|
||||
|
||||
override string toString() { result = "...->(" + this.getMethodNameString() + ")(...)"}
|
||||
}
|
||||
|
||||
/** A nullsafe method call expression (`$obj?->method(...)`). */
|
||||
class NullsafeMethodCallExpr extends Call, @php_nullsafe_member_call_expression {
|
||||
override string getAPrimaryQlClass() { result = "NullsafeMethodCallExpr" }
|
||||
|
||||
AstNode getObject() { php_nullsafe_member_call_expression_def(this, _, _, result) }
|
||||
|
||||
Name getMethodName() { php_nullsafe_member_call_expression_def(this, _, result, _) }
|
||||
|
||||
override Arguments getArguments() { php_nullsafe_member_call_expression_def(this, result, _, _) }
|
||||
|
||||
string getMethodNameString() { result = this.getMethodName().getValue() }
|
||||
|
||||
override string toString() { result = "...?->(" + this.getMethodNameString() + ")(...)"}
|
||||
}
|
||||
|
||||
/** A scoped (static) call expression (`ClassName::method(...)`). */
|
||||
class ScopedCallExpr extends Call, @php_scoped_call_expression {
|
||||
override string getAPrimaryQlClass() { result = "ScopedCallExpr" }
|
||||
|
||||
AstNode getScope() { php_scoped_call_expression_def(this, _, _, result) }
|
||||
|
||||
Name getMethodName() { php_scoped_call_expression_def(this, _, result, _) }
|
||||
|
||||
override Arguments getArguments() { php_scoped_call_expression_def(this, result, _, _) }
|
||||
|
||||
string getMethodNameString() { result = this.getMethodName().getValue() }
|
||||
|
||||
override string toString() { result = "...::(" + this.getMethodNameString() + ")(...)"}
|
||||
}
|
||||
178
php/ql/lib/codeql/php/ast/ClassLike.qll
Normal file
178
php/ql/lib/codeql/php/ast/ClassLike.qll
Normal file
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Provides classes for PHP class-like declarations (classes, interfaces, traits, enums).
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** A class-like declaration (class, interface, trait, or enum). */
|
||||
class ClassLike extends Stmt {
|
||||
ClassLike() {
|
||||
this instanceof ClassDecl or
|
||||
this instanceof InterfaceDecl or
|
||||
this instanceof TraitDecl or
|
||||
this instanceof EnumDecl
|
||||
}
|
||||
|
||||
/** Gets the name of this class-like declaration. */
|
||||
Name getName() { none() }
|
||||
|
||||
/** Gets the string name. */
|
||||
string getNameString() {
|
||||
result = this.getName().getValue()
|
||||
}
|
||||
}
|
||||
|
||||
/** A class declaration. */
|
||||
class ClassDecl extends Stmt, @php_class_declaration {
|
||||
override string getAPrimaryQlClass() { result = "ClassDecl" }
|
||||
|
||||
/** Gets the name. */
|
||||
Name getName() { php_class_declaration_def(this, _, result) }
|
||||
|
||||
/** Gets the string name. */
|
||||
string getNameString() { result = this.getName().getValue() }
|
||||
|
||||
/** Gets the declaration list (body). */
|
||||
DeclarationList getBody() { php_class_declaration_def(this, result, _) }
|
||||
|
||||
/** Gets the base clause (extends). */
|
||||
BaseClause getBaseClause() { php_class_declaration_child(this, _, result) }
|
||||
|
||||
/** Gets the interface implementation clause. */
|
||||
ClassInterfaceClause getInterfaceClause() { php_class_declaration_child(this, _, result) }
|
||||
|
||||
/** Holds if this class extends another class. */
|
||||
predicate hasBaseClass() { exists(this.getBaseClause()) }
|
||||
|
||||
override string toString() { result = "class " + this.getNameString() }
|
||||
}
|
||||
|
||||
/** A base clause (`extends ClassName`). */
|
||||
class BaseClause extends AstNode, @php_base_clause {
|
||||
override string getAPrimaryQlClass() { result = "BaseClause" }
|
||||
|
||||
override AstNode getChild(int i) { php_base_clause_child(this, i, result) }
|
||||
|
||||
override string toString() { result = "extends ..." }
|
||||
}
|
||||
|
||||
/** A class interface clause (`implements InterfaceName, ...`). */
|
||||
class ClassInterfaceClause extends AstNode, @php_class_interface_clause {
|
||||
override string getAPrimaryQlClass() { result = "ClassInterfaceClause" }
|
||||
|
||||
AstNode getInterface(int i) { php_class_interface_clause_child(this, i, result) }
|
||||
|
||||
AstNode getAnInterface() { result = this.getInterface(_) }
|
||||
|
||||
override string toString() { result = "implements ..." }
|
||||
}
|
||||
|
||||
/** A declaration list (class body). */
|
||||
class DeclarationList extends AstNode, @php_declaration_list {
|
||||
override string getAPrimaryQlClass() { result = "DeclarationList" }
|
||||
|
||||
AstNode getMember(int i) { php_declaration_list_child(this, i, result) }
|
||||
|
||||
AstNode getAMember() { result = this.getMember(_) }
|
||||
|
||||
override string toString() { result = "{ ... }" }
|
||||
}
|
||||
|
||||
/** An interface declaration. */
|
||||
class InterfaceDecl extends Stmt, @php_interface_declaration {
|
||||
override string getAPrimaryQlClass() { result = "InterfaceDecl" }
|
||||
|
||||
Name getName() { php_interface_declaration_def(this, _, result) }
|
||||
|
||||
string getNameString() { result = this.getName().getValue() }
|
||||
|
||||
DeclarationList getBody() { php_interface_declaration_def(this, result, _) }
|
||||
|
||||
BaseClause getBaseClause() { php_interface_declaration_child(this, result) }
|
||||
|
||||
override string toString() { result = "interface " + this.getNameString() }
|
||||
}
|
||||
|
||||
/** A trait declaration. */
|
||||
class TraitDecl extends Stmt, @php_trait_declaration {
|
||||
override string getAPrimaryQlClass() { result = "TraitDecl" }
|
||||
|
||||
Name getName() { php_trait_declaration_def(this, _, result) }
|
||||
|
||||
string getNameString() { result = this.getName().getValue() }
|
||||
|
||||
DeclarationList getBody() { php_trait_declaration_def(this, result, _) }
|
||||
|
||||
override string toString() { result = "trait " + this.getNameString() }
|
||||
}
|
||||
|
||||
/** An enum declaration. */
|
||||
class EnumDecl extends Stmt, @php_enum_declaration {
|
||||
override string getAPrimaryQlClass() { result = "EnumDecl" }
|
||||
|
||||
Name getName() { php_enum_declaration_def(this, _, result) }
|
||||
|
||||
string getNameString() { result = this.getName().getValue() }
|
||||
|
||||
AstNode getBody() { php_enum_declaration_def(this, result, _) }
|
||||
|
||||
override string toString() { result = "enum " + this.getNameString() }
|
||||
}
|
||||
|
||||
/** An enum case declaration. */
|
||||
class EnumCase extends AstNode, @php_enum_case {
|
||||
override string getAPrimaryQlClass() { result = "EnumCase" }
|
||||
|
||||
Name getName() { php_enum_case_def(this, result) }
|
||||
|
||||
Expr getValue() { php_enum_case_value(this, result) }
|
||||
|
||||
override string toString() { result = "case " + this.getName().getValue() }
|
||||
}
|
||||
|
||||
/** A property declaration. */
|
||||
class PropertyDecl extends AstNode, @php_property_declaration {
|
||||
override string getAPrimaryQlClass() { result = "PropertyDecl" }
|
||||
|
||||
TypeNode getType() { php_property_declaration_type(this, result) }
|
||||
|
||||
override AstNode getChild(int i) { php_property_declaration_child(this, i, result) }
|
||||
|
||||
PropertyElement getAProperty() { php_property_declaration_child(this, _, result) }
|
||||
|
||||
override string toString() { result = "property declaration" }
|
||||
}
|
||||
|
||||
/** A property element within a property declaration. */
|
||||
class PropertyElement extends AstNode, @php_property_element {
|
||||
override string getAPrimaryQlClass() { result = "PropertyElement" }
|
||||
|
||||
VariableName getName() { php_property_element_def(this, result) }
|
||||
|
||||
Expr getDefault() { php_property_element_default_value(this, result) }
|
||||
|
||||
predicate hasDefault() { exists(this.getDefault()) }
|
||||
|
||||
override string toString() { result = this.getName().getValue() }
|
||||
}
|
||||
|
||||
/** A constant declaration. */
|
||||
class ConstDecl extends AstNode, @php_const_declaration {
|
||||
override string getAPrimaryQlClass() { result = "ConstDecl" }
|
||||
|
||||
AstNode getConstant(int i) { php_const_declaration_child(this, i, result) }
|
||||
|
||||
AstNode getAConstant() { result = this.getConstant(_) }
|
||||
|
||||
override string toString() { result = "const ..." }
|
||||
}
|
||||
|
||||
/** A constant element. */
|
||||
class ConstElement extends AstNode, @php_const_element {
|
||||
override string getAPrimaryQlClass() { result = "ConstElement" }
|
||||
|
||||
override AstNode getChild(int i) { php_const_element_child(this, i, result) }
|
||||
|
||||
override string toString() { result = "const element" }
|
||||
}
|
||||
158
php/ql/lib/codeql/php/ast/Control.qll
Normal file
158
php/ql/lib/codeql/php/ast/Control.qll
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* Provides classes for PHP control flow statements.
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** An if statement. */
|
||||
class IfStmt extends Stmt, @php_if_statement {
|
||||
override string getAPrimaryQlClass() { result = "IfStmt" }
|
||||
|
||||
/** Gets the condition (a parenthesized expression). */
|
||||
AstNode getCondition() { php_if_statement_def(this, _, result) }
|
||||
|
||||
/** Gets the then branch. */
|
||||
AstNode getThen() { php_if_statement_def(this, result, _) }
|
||||
|
||||
/** Gets the `i`th alternative (elseif or else clause). */
|
||||
AstNode getAlternative(int i) { php_if_statement_alternative(this, i, result) }
|
||||
|
||||
/** Gets an alternative clause. */
|
||||
AstNode getAnAlternative() { result = this.getAlternative(_) }
|
||||
|
||||
override string toString() { result = "if (...) ..." }
|
||||
}
|
||||
|
||||
/** An elseif clause. */
|
||||
class ElseIfClause extends AstNode, @php_else_if_clause {
|
||||
override string getAPrimaryQlClass() { result = "ElseIfClause" }
|
||||
|
||||
AstNode getCondition() { php_else_if_clause_def(this, _, result) }
|
||||
|
||||
AstNode getBody() { php_else_if_clause_def(this, result, _) }
|
||||
|
||||
override string toString() { result = "elseif (...) ..." }
|
||||
}
|
||||
|
||||
/** A switch statement. */
|
||||
class SwitchStmt extends Stmt, @php_switch_statement {
|
||||
override string getAPrimaryQlClass() { result = "SwitchStmt" }
|
||||
|
||||
AstNode getCondition() { php_switch_statement_def(this, _, result) }
|
||||
|
||||
override string toString() { result = "switch (...) ..." }
|
||||
}
|
||||
|
||||
/** A case statement within a switch. */
|
||||
class CaseStmt extends AstNode, @php_case_statement {
|
||||
override string getAPrimaryQlClass() { result = "CaseStmt" }
|
||||
|
||||
Expr getValue() { php_case_statement_def(this, result) }
|
||||
|
||||
Stmt getStatement(int i) { php_case_statement_child(this, i, result) }
|
||||
|
||||
Stmt getAStatement() { result = this.getStatement(_) }
|
||||
|
||||
override string toString() { result = "case ...:" }
|
||||
}
|
||||
|
||||
/** A default statement within a switch. */
|
||||
class DefaultStmt extends AstNode, @php_default_statement {
|
||||
override string getAPrimaryQlClass() { result = "DefaultStmt" }
|
||||
|
||||
Stmt getStatement(int i) { php_default_statement_child(this, i, result) }
|
||||
|
||||
Stmt getAStatement() { result = this.getStatement(_) }
|
||||
|
||||
override string toString() { result = "default:" }
|
||||
}
|
||||
|
||||
/** A while statement. */
|
||||
class WhileStmt extends Stmt, @php_while_statement {
|
||||
override string getAPrimaryQlClass() { result = "WhileStmt" }
|
||||
|
||||
AstNode getCondition() { php_while_statement_def(this, _, result) }
|
||||
|
||||
AstNode getBody() { php_while_statement_def(this, result, _) }
|
||||
|
||||
override string toString() { result = "while (...) ..." }
|
||||
}
|
||||
|
||||
/** A do-while statement. */
|
||||
class DoWhileStmt extends Stmt, @php_do_statement {
|
||||
override string getAPrimaryQlClass() { result = "DoWhileStmt" }
|
||||
|
||||
Stmt getBody() { php_do_statement_def(this, result, _) }
|
||||
|
||||
AstNode getCondition() { php_do_statement_def(this, _, result) }
|
||||
|
||||
override string toString() { result = "do ... while (...)" }
|
||||
}
|
||||
|
||||
/** A for statement. */
|
||||
class ForStmt extends Stmt, @php_for_statement {
|
||||
override string getAPrimaryQlClass() { result = "ForStmt" }
|
||||
|
||||
AstNode getInitialize() { php_for_statement_initialize(this, result) }
|
||||
|
||||
AstNode getCondition() { php_for_statement_condition(this, result) }
|
||||
|
||||
AstNode getUpdate() { php_for_statement_update(this, result) }
|
||||
|
||||
Stmt getBodyStmt(int i) { php_for_statement_body(this, i, result) }
|
||||
|
||||
Stmt getABodyStmt() { result = this.getBodyStmt(_) }
|
||||
|
||||
override string toString() { result = "for (...) ..." }
|
||||
}
|
||||
|
||||
/** A foreach statement. */
|
||||
class ForeachStmt extends Stmt, @php_foreach_statement {
|
||||
override string getAPrimaryQlClass() { result = "ForeachStmt" }
|
||||
|
||||
override AstNode getChild(int i) { php_foreach_statement_child(this, i, result) }
|
||||
|
||||
AstNode getBody() { php_foreach_statement_body(this, result) }
|
||||
|
||||
override string toString() { result = "foreach (...) ..." }
|
||||
}
|
||||
|
||||
/** A try statement. */
|
||||
class TryStmt extends Stmt, @php_try_statement {
|
||||
override string getAPrimaryQlClass() { result = "TryStmt" }
|
||||
|
||||
CompoundStmt getBody() { php_try_statement_def(this, result) }
|
||||
|
||||
override AstNode getChild(int i) { php_try_statement_child(this, i, result) }
|
||||
|
||||
CatchClause getCatch(int i) { php_try_statement_child(this, i, result) }
|
||||
|
||||
CatchClause getACatch() { result = this.getCatch(_) }
|
||||
|
||||
FinallyClause getFinally() { php_try_statement_child(this, _, result) }
|
||||
|
||||
predicate hasFinally() { exists(this.getFinally()) }
|
||||
|
||||
override string toString() { result = "try { ... }" }
|
||||
}
|
||||
|
||||
/** A catch clause. */
|
||||
class CatchClause extends AstNode, @php_catch_clause {
|
||||
override string getAPrimaryQlClass() { result = "CatchClause" }
|
||||
|
||||
CompoundStmt getBody() { php_catch_clause_def(this, result, _) }
|
||||
|
||||
VariableName getVariable() { php_catch_clause_name(this, result) }
|
||||
|
||||
override string toString() { result = "catch (...) { ... }" }
|
||||
}
|
||||
|
||||
/** A finally clause. */
|
||||
class FinallyClause extends AstNode, @php_finally_clause {
|
||||
override string getAPrimaryQlClass() { result = "FinallyClause" }
|
||||
|
||||
CompoundStmt getBody() { php_finally_clause_def(this, result) }
|
||||
|
||||
override string toString() { result = "finally { ... }" }
|
||||
}
|
||||
342
php/ql/lib/codeql/php/ast/Expr.qll
Normal file
342
php/ql/lib/codeql/php/ast/Expr.qll
Normal file
@@ -0,0 +1,342 @@
|
||||
/**
|
||||
* Provides classes for PHP expressions.
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** An expression. */
|
||||
class Expr extends AstNode, @php_expression {
|
||||
override string getAPrimaryQlClass() { result = "Expr" }
|
||||
}
|
||||
|
||||
/** An assignment expression (`$x = expr`). */
|
||||
class AssignExpr extends Expr, @php_assignment_expression {
|
||||
override string getAPrimaryQlClass() { result = "AssignExpr" }
|
||||
|
||||
/** Gets the left-hand side (target) of the assignment. */
|
||||
AstNode getLeftOperand() { php_assignment_expression_def(this, result, _) }
|
||||
|
||||
/** Gets the right-hand side (value) of the assignment. */
|
||||
Expr getRightOperand() { php_assignment_expression_def(this, _, result) }
|
||||
|
||||
override string toString() { result = "... = ..." }
|
||||
}
|
||||
|
||||
/** A reference assignment expression (`$x =& expr`). */
|
||||
class RefAssignExpr extends Expr, @php_reference_assignment_expression {
|
||||
override string getAPrimaryQlClass() { result = "RefAssignExpr" }
|
||||
|
||||
Expr getLeftOperand() { php_reference_assignment_expression_def(this, result, _) }
|
||||
|
||||
Expr getRightOperand() { php_reference_assignment_expression_def(this, _, result) }
|
||||
|
||||
override string toString() { result = "... =& ..." }
|
||||
}
|
||||
|
||||
/** An augmented assignment expression (`$x += expr`, `$x .= expr`, etc.). */
|
||||
class AugmentedAssignExpr extends Expr, @php_augmented_assignment_expression {
|
||||
override string getAPrimaryQlClass() { result = "AugmentedAssignExpr" }
|
||||
|
||||
AstNode getLeftOperand() { php_augmented_assignment_expression_def(this, result, _, _) }
|
||||
|
||||
string getOperator() { result = this.(Php::AugmentedAssignmentExpression).getOperator() }
|
||||
|
||||
Expr getRightOperand() { php_augmented_assignment_expression_def(this, _, _, result) }
|
||||
|
||||
override string toString() { result = "... " + this.getOperator() + " ..." }
|
||||
}
|
||||
|
||||
/** A binary expression (`$x + $y`, `$x . $y`, etc.). */
|
||||
class BinaryExpr extends Expr, @php_binary_expression {
|
||||
override string getAPrimaryQlClass() { result = "BinaryExpr" }
|
||||
|
||||
Expr getLeftOperand() { php_binary_expression_def(this, result, _, _) }
|
||||
|
||||
string getOperator() { result = this.(Php::BinaryExpression).getOperator() }
|
||||
|
||||
Expr getRightOperand() { php_binary_expression_def(this, _, _, result) }
|
||||
|
||||
override string toString() { result = "... " + this.getOperator() + " ..." }
|
||||
}
|
||||
|
||||
/** A unary expression (`!$x`, `-$x`, `~$x`). */
|
||||
class UnaryExpr extends Expr, @php_unary_op_expression {
|
||||
override string getAPrimaryQlClass() { result = "UnaryExpr" }
|
||||
|
||||
string getOperator() {
|
||||
exists(AstNode op |
|
||||
php_unary_op_expression_operator(this, op) and
|
||||
php_tokeninfo(op, _, result)
|
||||
)
|
||||
}
|
||||
|
||||
Expr getOperand() { php_unary_op_expression_argument(this, result) }
|
||||
|
||||
override string toString() { result = this.getOperator() + "..." }
|
||||
}
|
||||
|
||||
/** An update expression (`$x++`, `$x--`, `++$x`, `--$x`). */
|
||||
class UpdateExpr extends Expr, @php_update_expression {
|
||||
override string getAPrimaryQlClass() { result = "UpdateExpr" }
|
||||
|
||||
AstNode getArgument() { php_update_expression_def(this, result, _) }
|
||||
|
||||
string getOperator() { result = this.(Php::UpdateExpression).getOperator() }
|
||||
|
||||
predicate isPrefix() { this.(Php::UpdateExpression).toString() = this.(Php::UpdateExpression).toString() }
|
||||
|
||||
override string toString() { result = this.getOperator() + "..." }
|
||||
}
|
||||
|
||||
/** A conditional (ternary) expression (`$x ? $y : $z`). */
|
||||
class ConditionalExpr extends Expr, @php_conditional_expression {
|
||||
override string getAPrimaryQlClass() { result = "ConditionalExpr" }
|
||||
|
||||
Expr getCondition() { php_conditional_expression_def(this, _, result) }
|
||||
|
||||
Expr getConsequence() { php_conditional_expression_body(this, result) }
|
||||
|
||||
Expr getAlternative() { php_conditional_expression_def(this, result, _) }
|
||||
|
||||
override string toString() { result = "... ? ... : ..." }
|
||||
}
|
||||
|
||||
/** A cast expression (`(int)$x`, `(string)$x`, etc.). */
|
||||
class CastExpr extends Expr, @php_cast_expression {
|
||||
override string getAPrimaryQlClass() { result = "CastExpr" }
|
||||
|
||||
AstNode getCastType() { php_cast_expression_def(this, result, _) }
|
||||
|
||||
AstNode getValue() { php_cast_expression_def(this, _, result) }
|
||||
|
||||
override string toString() { result = "(cast)..." }
|
||||
}
|
||||
|
||||
/** An error suppression expression (`@expr`). */
|
||||
class ErrorSuppressExpr extends Expr, @php_error_suppression_expression {
|
||||
override string getAPrimaryQlClass() { result = "ErrorSuppressExpr" }
|
||||
|
||||
Expr getExpr() { php_error_suppression_expression_def(this, result) }
|
||||
|
||||
override string toString() { result = "@..." }
|
||||
}
|
||||
|
||||
/** A clone expression (`clone $x`). */
|
||||
class CloneExpr extends Expr, @php_clone_expression {
|
||||
override string getAPrimaryQlClass() { result = "CloneExpr" }
|
||||
|
||||
Expr getExpr() { php_clone_expression_def(this, result) }
|
||||
|
||||
override string toString() { result = "clone ..." }
|
||||
}
|
||||
|
||||
/** A throw expression (`throw $x`). */
|
||||
class ThrowExpr extends Expr, @php_throw_expression {
|
||||
override string getAPrimaryQlClass() { result = "ThrowExpr" }
|
||||
|
||||
Expr getExpr() { php_throw_expression_def(this, result) }
|
||||
|
||||
override string toString() { result = "throw ..." }
|
||||
}
|
||||
|
||||
/** A parenthesized expression (`(expr)`). */
|
||||
class ParenExpr extends Expr, @php_parenthesized_expression {
|
||||
override string getAPrimaryQlClass() { result = "ParenExpr" }
|
||||
|
||||
Expr getExpr() { php_parenthesized_expression_def(this, result) }
|
||||
|
||||
override string toString() { result = "(...)" }
|
||||
}
|
||||
|
||||
/** An array creation expression (`[1, 2, 3]` or `array(1, 2, 3)`). */
|
||||
class ArrayCreationExpr extends Expr, @php_array_creation_expression {
|
||||
override string getAPrimaryQlClass() { result = "ArrayCreationExpr" }
|
||||
|
||||
ArrayElementInitializer getElement(int i) {
|
||||
php_array_creation_expression_child(this, i, result)
|
||||
}
|
||||
|
||||
ArrayElementInitializer getAnElement() { result = this.getElement(_) }
|
||||
|
||||
int getNumberOfElements() {
|
||||
result = count(int i | php_array_creation_expression_child(this, i, _))
|
||||
}
|
||||
|
||||
override string toString() { result = "array(...)" }
|
||||
}
|
||||
|
||||
/** An array element initializer. */
|
||||
class ArrayElementInitializer extends AstNode, @php_array_element_initializer {
|
||||
override string getAPrimaryQlClass() { result = "ArrayElementInitializer" }
|
||||
|
||||
override AstNode getChild(int i) { php_array_element_initializer_child(this, i, result) }
|
||||
|
||||
override string toString() { result = "... => ..." }
|
||||
}
|
||||
|
||||
/** A subscript (array access) expression (`$x[0]`). */
|
||||
class SubscriptExpr extends Expr, @php_subscript_expression {
|
||||
override string getAPrimaryQlClass() { result = "SubscriptExpr" }
|
||||
|
||||
AstNode getObject() { php_subscript_expression_child(this, 0, result) }
|
||||
|
||||
AstNode getIndexExpr() { php_subscript_expression_child(this, 1, result) }
|
||||
|
||||
override string toString() { result = "...[...]" }
|
||||
}
|
||||
|
||||
/** A member access expression (`$obj->prop`). */
|
||||
class MemberAccessExpr extends Expr, @php_member_access_expression {
|
||||
override string getAPrimaryQlClass() { result = "MemberAccessExpr" }
|
||||
|
||||
AstNode getObject() { php_member_access_expression_def(this, _, result) }
|
||||
|
||||
Name getName() { php_member_access_expression_def(this, result, _) }
|
||||
|
||||
override string toString() { result = "...->..." }
|
||||
}
|
||||
|
||||
/** A nullsafe member access expression (`$obj?->prop`). */
|
||||
class NullsafeMemberAccessExpr extends Expr, @php_nullsafe_member_access_expression {
|
||||
override string getAPrimaryQlClass() { result = "NullsafeMemberAccessExpr" }
|
||||
|
||||
AstNode getObject() { php_nullsafe_member_access_expression_def(this, _, result) }
|
||||
|
||||
Name getName() { php_nullsafe_member_access_expression_def(this, result, _) }
|
||||
|
||||
override string toString() { result = "...?->..." }
|
||||
}
|
||||
|
||||
/** A scoped property access expression (`ClassName::$prop`). */
|
||||
class ScopedPropertyAccessExpr extends Expr, @php_scoped_property_access_expression {
|
||||
override string getAPrimaryQlClass() { result = "ScopedPropertyAccessExpr" }
|
||||
|
||||
AstNode getScope() { php_scoped_property_access_expression_def(this, _, result) }
|
||||
|
||||
VariableName getName() { php_scoped_property_access_expression_def(this, result, _) }
|
||||
|
||||
override string toString() { result = "...::$..." }
|
||||
}
|
||||
|
||||
/** A class constant access expression (`ClassName::CONST`). */
|
||||
class ClassConstantAccessExpr extends Expr, @php_class_constant_access_expression {
|
||||
override string getAPrimaryQlClass() { result = "ClassConstantAccessExpr" }
|
||||
|
||||
AstNode getScope() { php_class_constant_access_expression_child(this, 0, result) }
|
||||
|
||||
Name getName() { php_class_constant_access_expression_child(this, 1, result) }
|
||||
|
||||
override string toString() { result = "...::..." }
|
||||
}
|
||||
|
||||
/** An `include` expression. */
|
||||
class IncludeExpr extends Expr, @php_include_expression {
|
||||
override string getAPrimaryQlClass() { result = "IncludeExpr" }
|
||||
|
||||
Expr getArgument() { php_include_expression_def(this, result) }
|
||||
|
||||
override string toString() { result = "include ..." }
|
||||
}
|
||||
|
||||
/** An `include_once` expression. */
|
||||
class IncludeOnceExpr extends Expr, @php_include_once_expression {
|
||||
override string getAPrimaryQlClass() { result = "IncludeOnceExpr" }
|
||||
|
||||
Expr getArgument() { php_include_once_expression_def(this, result) }
|
||||
|
||||
override string toString() { result = "include_once ..." }
|
||||
}
|
||||
|
||||
/** A `require` expression. */
|
||||
class RequireExpr extends Expr, @php_require_expression {
|
||||
override string getAPrimaryQlClass() { result = "RequireExpr" }
|
||||
|
||||
Expr getArgument() { php_require_expression_def(this, result) }
|
||||
|
||||
override string toString() { result = "require ..." }
|
||||
}
|
||||
|
||||
/** A `require_once` expression. */
|
||||
class RequireOnceExpr extends Expr, @php_require_once_expression {
|
||||
override string getAPrimaryQlClass() { result = "RequireOnceExpr" }
|
||||
|
||||
Expr getArgument() { php_require_once_expression_def(this, result) }
|
||||
|
||||
override string toString() { result = "require_once ..." }
|
||||
}
|
||||
|
||||
/** An object creation expression (`new ClassName(...)`). */
|
||||
class ObjectCreationExpr extends Expr, @php_object_creation_expression {
|
||||
override string getAPrimaryQlClass() { result = "ObjectCreationExpr" }
|
||||
|
||||
override AstNode getChild(int i) { php_object_creation_expression_child(this, i, result) }
|
||||
|
||||
override string toString() { result = "new ..." }
|
||||
}
|
||||
|
||||
/** A `yield` expression. */
|
||||
class YieldExpr extends Expr, @php_yield_expression {
|
||||
override string getAPrimaryQlClass() { result = "YieldExpr" }
|
||||
|
||||
AstNode getChild() { php_yield_expression_child(this, result) }
|
||||
|
||||
override string toString() { result = "yield ..." }
|
||||
}
|
||||
|
||||
/** A `print` expression. */
|
||||
class PrintExpr extends Expr, @php_print_intrinsic {
|
||||
override string getAPrimaryQlClass() { result = "PrintExpr" }
|
||||
|
||||
Expr getArgument() { php_print_intrinsic_def(this, result) }
|
||||
|
||||
override string toString() { result = "print ..." }
|
||||
}
|
||||
|
||||
/** A shell command expression (backtick operator). */
|
||||
class ShellCommandExpr extends Expr, @php_shell_command_expression {
|
||||
override string getAPrimaryQlClass() { result = "ShellCommandExpr" }
|
||||
|
||||
/** Gets the i-th child element (interpolated parts). */
|
||||
AstNode getElement(int i) { php_shell_command_expression_child(this, i, result) }
|
||||
|
||||
override string toString() { result = "`...`" }
|
||||
}
|
||||
|
||||
/** A dynamic variable name expression (`$$var`). */
|
||||
class DynamicVariableNameExpr extends Expr, @php_dynamic_variable_name {
|
||||
override string getAPrimaryQlClass() { result = "DynamicVariableNameExpr" }
|
||||
|
||||
AstNode getNameExpr() { php_dynamic_variable_name_def(this, result) }
|
||||
|
||||
override string toString() { result = "$$..." }
|
||||
}
|
||||
|
||||
/** A variadic unpacking expression (`...$arr`). */
|
||||
class VariadicUnpackingExpr extends AstNode, @php_variadic_unpacking {
|
||||
override string getAPrimaryQlClass() { result = "VariadicUnpackingExpr" }
|
||||
|
||||
Expr getExpr() { php_variadic_unpacking_def(this, result) }
|
||||
|
||||
override string toString() { result = "...expr" }
|
||||
}
|
||||
|
||||
/** A match expression. */
|
||||
class MatchExpr extends Expr, @php_match_expression {
|
||||
override string getAPrimaryQlClass() { result = "MatchExpr" }
|
||||
|
||||
override string toString() { result = "match ..." }
|
||||
}
|
||||
|
||||
/** An arguments list. */
|
||||
class Arguments extends AstNode, @php_arguments {
|
||||
override string getAPrimaryQlClass() { result = "Arguments" }
|
||||
|
||||
AstNode getArgument(int i) { php_arguments_child(this, i, result) }
|
||||
|
||||
AstNode getAnArgument() { result = this.getArgument(_) }
|
||||
|
||||
int getNumberOfArguments() { result = count(int i | php_arguments_child(this, i, _)) }
|
||||
|
||||
override string toString() { result = "(...)" }
|
||||
}
|
||||
121
php/ql/lib/codeql/php/ast/Function.qll
Normal file
121
php/ql/lib/codeql/php/ast/Function.qll
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Provides classes for PHP functions, closures, and arrow functions.
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** A callable (function, method, closure, or arrow function). */
|
||||
class Callable extends AstNode {
|
||||
Callable() {
|
||||
this instanceof FunctionDef or
|
||||
this instanceof MethodDecl or
|
||||
this instanceof AnonymousFunction or
|
||||
this instanceof ArrowFunction
|
||||
}
|
||||
|
||||
/** Gets the formal parameters node. */
|
||||
FormalParameters getParameters() {
|
||||
result = this.(FunctionDef).getParameters()
|
||||
or
|
||||
result = this.(MethodDecl).getParameters()
|
||||
or
|
||||
result = this.(AnonymousFunction).getParameters()
|
||||
or
|
||||
result = this.(ArrowFunction).getParameters()
|
||||
}
|
||||
|
||||
/** Gets the `i`th parameter. */
|
||||
Parameter getParameter(int i) { result = this.getParameters().getParameter(i) }
|
||||
|
||||
/** Gets a parameter. */
|
||||
Parameter getAParameter() { result = this.getParameter(_) }
|
||||
|
||||
/** Gets the number of parameters. */
|
||||
int getNumberOfParameters() { result = this.getParameters().getNumberOfParameters() }
|
||||
}
|
||||
|
||||
/** A function definition. */
|
||||
class FunctionDef extends Stmt, @php_function_definition {
|
||||
override string getAPrimaryQlClass() { result = "FunctionDef" }
|
||||
|
||||
/** Gets the name of this function. */
|
||||
Name getName() { php_function_definition_def(this, _, result, _) }
|
||||
|
||||
/** Gets the string name of this function. */
|
||||
string getNameString() { result = this.getName().getValue() }
|
||||
|
||||
/** Gets the formal parameters. */
|
||||
FormalParameters getParameters() { php_function_definition_def(this, _, _, result) }
|
||||
|
||||
/** Gets the body of this function. */
|
||||
CompoundStmt getBody() { php_function_definition_def(this, result, _, _) }
|
||||
|
||||
/** Gets the return type annotation, if any. */
|
||||
TypeNode getReturnType() { php_function_definition_return_type(this, result) }
|
||||
|
||||
override string toString() { result = "function " + this.getNameString() }
|
||||
}
|
||||
|
||||
/** A method declaration within a class, interface, trait, or enum. */
|
||||
class MethodDecl extends AstNode, @php_method_declaration {
|
||||
override string getAPrimaryQlClass() { result = "MethodDecl" }
|
||||
|
||||
/** Gets the name. */
|
||||
Name getName() { php_method_declaration_def(this, result, _) }
|
||||
|
||||
/** Gets the string name. */
|
||||
string getNameString() { result = this.getName().getValue() }
|
||||
|
||||
/** Gets the formal parameters. */
|
||||
FormalParameters getParameters() { php_method_declaration_def(this, _, result) }
|
||||
|
||||
/** Gets the body, if any (abstract methods have no body). */
|
||||
CompoundStmt getBody() { php_method_declaration_body(this, result) }
|
||||
|
||||
/** Gets the return type annotation, if any. */
|
||||
TypeNode getReturnType() { php_method_declaration_return_type(this, result) }
|
||||
|
||||
override string toString() { result = "method " + this.getNameString() }
|
||||
}
|
||||
|
||||
/** An anonymous function (closure). */
|
||||
class AnonymousFunction extends Expr, @php_anonymous_function {
|
||||
override string getAPrimaryQlClass() { result = "AnonymousFunction" }
|
||||
|
||||
FormalParameters getParameters() { php_anonymous_function_def(this, _, result) }
|
||||
|
||||
CompoundStmt getBody() { php_anonymous_function_def(this, result, _) }
|
||||
|
||||
TypeNode getReturnType() { php_anonymous_function_return_type(this, result) }
|
||||
|
||||
override string toString() { result = "function (...) { ... }" }
|
||||
}
|
||||
|
||||
/** An arrow function (`fn($x) => $x + 1`). */
|
||||
class ArrowFunction extends Expr, @php_arrow_function {
|
||||
override string getAPrimaryQlClass() { result = "ArrowFunction" }
|
||||
|
||||
FormalParameters getParameters() { php_arrow_function_def(this, _, result) }
|
||||
|
||||
Expr getBody() { php_arrow_function_def(this, result, _) }
|
||||
|
||||
TypeNode getReturnType() { php_arrow_function_return_type(this, result) }
|
||||
|
||||
override string toString() { result = "fn(...) => ..." }
|
||||
}
|
||||
|
||||
/** A formal parameters list. */
|
||||
class FormalParameters extends AstNode, @php_formal_parameters {
|
||||
override string getAPrimaryQlClass() { result = "FormalParameters" }
|
||||
|
||||
AstNode getParameter(int i) { php_formal_parameters_child(this, i, result) }
|
||||
|
||||
AstNode getAParameter() { result = this.getParameter(_) }
|
||||
|
||||
int getNumberOfParameters() {
|
||||
result = count(int i | php_formal_parameters_child(this, i, _))
|
||||
}
|
||||
|
||||
override string toString() { result = "(...)" }
|
||||
}
|
||||
86
php/ql/lib/codeql/php/ast/Literal.qll
Normal file
86
php/ql/lib/codeql/php/ast/Literal.qll
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Provides classes for PHP literal expressions.
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** A literal expression. */
|
||||
class Literal extends Expr, @php_literal {
|
||||
override string getAPrimaryQlClass() { result = "Literal" }
|
||||
}
|
||||
|
||||
/** An integer literal. */
|
||||
class IntegerLiteral extends Literal, @php_token_integer {
|
||||
override string getAPrimaryQlClass() { result = "IntegerLiteral" }
|
||||
|
||||
/** Gets the string representation of the integer value. */
|
||||
string getValue() { php_tokeninfo(this, _, result) }
|
||||
|
||||
override string toString() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/** A float literal. */
|
||||
class FloatLiteral extends Literal, @php_token_float {
|
||||
override string getAPrimaryQlClass() { result = "FloatLiteral" }
|
||||
|
||||
string getValue() { php_tokeninfo(this, _, result) }
|
||||
|
||||
override string toString() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/** A string literal. */
|
||||
class StringLiteral extends Literal, @php_string__ {
|
||||
override string getAPrimaryQlClass() { result = "StringLiteral" }
|
||||
|
||||
override string toString() { result = "\"...\"" }
|
||||
}
|
||||
|
||||
/** An encapsed (interpolated) string. */
|
||||
class EncapsedString extends Literal, @php_encapsed_string {
|
||||
override string getAPrimaryQlClass() { result = "EncapsedString" }
|
||||
|
||||
/** Gets the i-th element (string content or interpolated expression). */
|
||||
AstNode getElement(int i) { php_encapsed_string_child(this, i, result) }
|
||||
|
||||
/** Gets an element of this encapsed string. */
|
||||
AstNode getAnElement() { result = this.getElement(_) }
|
||||
|
||||
override string toString() { result = "\"...\"" }
|
||||
}
|
||||
|
||||
/** A heredoc string. */
|
||||
class Heredoc extends Literal, @php_heredoc {
|
||||
override string getAPrimaryQlClass() { result = "Heredoc" }
|
||||
|
||||
override string toString() { result = "<<<..." }
|
||||
}
|
||||
|
||||
/** A nowdoc string. */
|
||||
class Nowdoc extends Literal, @php_nowdoc {
|
||||
override string getAPrimaryQlClass() { result = "Nowdoc" }
|
||||
|
||||
override string toString() { result = "<<<'...'" }
|
||||
}
|
||||
|
||||
/** A boolean literal (`true` or `false`). */
|
||||
class BooleanLiteral extends Literal, @php_token_boolean {
|
||||
override string getAPrimaryQlClass() { result = "BooleanLiteral" }
|
||||
|
||||
string getValue() { php_tokeninfo(this, _, result) }
|
||||
|
||||
/** Holds if this is the `true` literal. */
|
||||
predicate isTrue() { this.getValue().toLowerCase() = "true" }
|
||||
|
||||
/** Holds if this is the `false` literal. */
|
||||
predicate isFalse() { this.getValue().toLowerCase() = "false" }
|
||||
|
||||
override string toString() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/** A null literal. */
|
||||
class NullLiteral extends Literal, @php_token_null {
|
||||
override string getAPrimaryQlClass() { result = "NullLiteral" }
|
||||
|
||||
override string toString() { result = "null" }
|
||||
}
|
||||
70
php/ql/lib/codeql/php/ast/Parameter.qll
Normal file
70
php/ql/lib/codeql/php/ast/Parameter.qll
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Provides classes for PHP parameters.
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** A parameter in a function, method, closure, or arrow function. */
|
||||
class Parameter extends AstNode {
|
||||
Parameter() {
|
||||
this instanceof SimpleParameter or
|
||||
this instanceof VariadicParameter or
|
||||
this instanceof PropertyPromotionParameter
|
||||
}
|
||||
|
||||
/** Gets the name of this parameter as a variable name node. */
|
||||
VariableName getVariableName() { none() }
|
||||
|
||||
/** Gets the string name of this parameter (including `$`). */
|
||||
string getNameString() { result = this.getVariableName().getValue() }
|
||||
|
||||
/** Gets the type annotation, if any. */
|
||||
TypeNode getType() { none() }
|
||||
|
||||
/** Gets the default value, if any. */
|
||||
Expr getDefault() { none() }
|
||||
|
||||
/** Holds if this parameter has a default value. */
|
||||
predicate hasDefault() { exists(this.getDefault()) }
|
||||
}
|
||||
|
||||
/** A simple parameter (`$x` or `Type $x`). */
|
||||
class SimpleParameter extends AstNode, @php_simple_parameter {
|
||||
override string getAPrimaryQlClass() { result = "SimpleParameter" }
|
||||
|
||||
/** Gets the variable name. */
|
||||
VariableName getVariableName() { php_simple_parameter_def(this, result) }
|
||||
|
||||
/** Gets the type annotation, if any. */
|
||||
TypeNode getType() { php_simple_parameter_type(this, result) }
|
||||
|
||||
/** Gets the default value, if any. */
|
||||
Expr getDefault() { php_simple_parameter_default_value(this, result) }
|
||||
|
||||
override string toString() { result = this.getVariableName().getValue() }
|
||||
}
|
||||
|
||||
/** A variadic parameter (`...$args`). */
|
||||
class VariadicParameter extends AstNode, @php_variadic_parameter {
|
||||
override string getAPrimaryQlClass() { result = "VariadicParameter" }
|
||||
|
||||
VariableName getVariableName() { php_variadic_parameter_def(this, result) }
|
||||
|
||||
TypeNode getType() { php_variadic_parameter_type(this, result) }
|
||||
|
||||
override string toString() { result = "..." + this.getVariableName().getValue() }
|
||||
}
|
||||
|
||||
/** A property promotion parameter (PHP 8.0+). */
|
||||
class PropertyPromotionParameter extends AstNode, @php_property_promotion_parameter {
|
||||
override string getAPrimaryQlClass() { result = "PropertyPromotionParameter" }
|
||||
|
||||
VariableName getVariableName() { php_property_promotion_parameter_def(this, result, _) }
|
||||
|
||||
TypeNode getType() { php_property_promotion_parameter_type(this, result) }
|
||||
|
||||
Expr getDefault() { php_property_promotion_parameter_default_value(this, result) }
|
||||
|
||||
override string toString() { result = this.getVariableName().getValue() }
|
||||
}
|
||||
160
php/ql/lib/codeql/php/ast/Statement.qll
Normal file
160
php/ql/lib/codeql/php/ast/Statement.qll
Normal file
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* Provides classes for PHP statements.
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** A statement. */
|
||||
class Stmt extends AstNode, @php_statement {
|
||||
override string getAPrimaryQlClass() { result = "Stmt" }
|
||||
}
|
||||
|
||||
/** An expression statement. */
|
||||
class ExprStmt extends Stmt, @php_expression_statement {
|
||||
override string getAPrimaryQlClass() { result = "ExprStmt" }
|
||||
|
||||
/** Gets the expression. */
|
||||
Expr getExpr() { php_expression_statement_def(this, result) }
|
||||
|
||||
override string toString() { result = "...;" }
|
||||
}
|
||||
|
||||
/** A compound (block) statement. */
|
||||
class CompoundStmt extends Stmt, @php_compound_statement {
|
||||
override string getAPrimaryQlClass() { result = "CompoundStmt" }
|
||||
|
||||
Stmt getStatement(int i) { php_compound_statement_child(this, i, result) }
|
||||
|
||||
Stmt getAStatement() { result = this.getStatement(_) }
|
||||
|
||||
int getNumberOfStatements() {
|
||||
result = count(int i | php_compound_statement_child(this, i, _))
|
||||
}
|
||||
|
||||
override string toString() { result = "{ ... }" }
|
||||
}
|
||||
|
||||
/** An empty statement (`;`). */
|
||||
class EmptyStmt extends Stmt, @php_token_empty_statement {
|
||||
override string getAPrimaryQlClass() { result = "EmptyStmt" }
|
||||
|
||||
override string toString() { result = ";" }
|
||||
}
|
||||
|
||||
/** A return statement. */
|
||||
class ReturnStmt extends Stmt, @php_return_statement {
|
||||
override string getAPrimaryQlClass() { result = "ReturnStmt" }
|
||||
|
||||
/** Gets the return value, if any. */
|
||||
Expr getValue() { php_return_statement_child(this, result) }
|
||||
|
||||
/** Holds if this return statement has a value. */
|
||||
predicate hasValue() { exists(this.getValue()) }
|
||||
|
||||
override string toString() { result = "return ..." }
|
||||
}
|
||||
|
||||
/** A break statement. */
|
||||
class BreakStmt extends Stmt, @php_break_statement {
|
||||
override string getAPrimaryQlClass() { result = "BreakStmt" }
|
||||
|
||||
override string toString() { result = "break" }
|
||||
}
|
||||
|
||||
/** A continue statement. */
|
||||
class ContinueStmt extends Stmt, @php_continue_statement {
|
||||
override string getAPrimaryQlClass() { result = "ContinueStmt" }
|
||||
|
||||
override string toString() { result = "continue" }
|
||||
}
|
||||
|
||||
/** A goto statement. */
|
||||
class GotoStmt extends Stmt, @php_goto_statement {
|
||||
override string getAPrimaryQlClass() { result = "GotoStmt" }
|
||||
|
||||
Name getLabel() { php_goto_statement_def(this, result) }
|
||||
|
||||
override string toString() { result = "goto ..." }
|
||||
}
|
||||
|
||||
/** A named label statement. */
|
||||
class LabelStmt extends Stmt, @php_named_label_statement {
|
||||
override string getAPrimaryQlClass() { result = "LabelStmt" }
|
||||
|
||||
Name getName() { php_named_label_statement_def(this, result) }
|
||||
|
||||
override string toString() { result = "label:" }
|
||||
}
|
||||
|
||||
/** An echo statement. */
|
||||
class EchoStmt extends Stmt, @php_echo_statement {
|
||||
override string getAPrimaryQlClass() { result = "EchoStmt" }
|
||||
|
||||
/** Gets the child expression (may be a sequence_expression for multiple args). */
|
||||
AstNode getExpression() { php_echo_statement_def(this, result) }
|
||||
|
||||
/** Gets an output expression of this echo statement. */
|
||||
AstNode getAnOutputExpression() {
|
||||
// Single expression: echo $x;
|
||||
php_echo_statement_def(this, result) and not result instanceof @php_sequence_expression
|
||||
or
|
||||
// Sequence expression: echo $x, $y;
|
||||
exists(@php_sequence_expression seq |
|
||||
php_echo_statement_def(this, seq) and
|
||||
php_sequence_expression_child(seq, _, result)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets an argument expression (alias for getAnOutputExpression). */
|
||||
AstNode getAnArgument() { result = this.getAnOutputExpression() }
|
||||
|
||||
override string toString() { result = "echo ..." }
|
||||
}
|
||||
|
||||
/** An unset statement. */
|
||||
class UnsetStmt extends Stmt, @php_unset_statement {
|
||||
override string getAPrimaryQlClass() { result = "UnsetStmt" }
|
||||
|
||||
AstNode getExpression(int i) { php_unset_statement_child(this, i, result) }
|
||||
|
||||
AstNode getAnExpression() { result = this.getExpression(_) }
|
||||
|
||||
override string toString() { result = "unset(...)" }
|
||||
}
|
||||
|
||||
/** A global variable declaration. */
|
||||
class GlobalDeclaration extends Stmt, @php_global_declaration {
|
||||
override string getAPrimaryQlClass() { result = "GlobalDeclaration" }
|
||||
|
||||
AstNode getVariable(int i) { php_global_declaration_child(this, i, result) }
|
||||
|
||||
AstNode getAVariable() { result = this.getVariable(_) }
|
||||
|
||||
override string toString() { result = "global ..." }
|
||||
}
|
||||
|
||||
/** A namespace definition. */
|
||||
class NamespaceDefinition extends Stmt, @php_namespace_definition {
|
||||
override string getAPrimaryQlClass() { result = "NamespaceDefinition" }
|
||||
|
||||
NamespaceName getNamespaceName() { php_namespace_definition_name(this, result) }
|
||||
|
||||
CompoundStmt getBody() { php_namespace_definition_body(this, result) }
|
||||
|
||||
override string toString() { result = "namespace ..." }
|
||||
}
|
||||
|
||||
/** A namespace use declaration (`use ...`). */
|
||||
class NamespaceUseDeclaration extends Stmt, @php_namespace_use_declaration {
|
||||
override string getAPrimaryQlClass() { result = "NamespaceUseDeclaration" }
|
||||
|
||||
override string toString() { result = "use ..." }
|
||||
}
|
||||
|
||||
/** A declare statement. */
|
||||
class DeclareStmt extends Stmt, @php_declare_statement {
|
||||
override string getAPrimaryQlClass() { result = "DeclareStmt" }
|
||||
|
||||
override string toString() { result = "declare(...)" }
|
||||
}
|
||||
117
php/ql/lib/codeql/php/ast/Variable.qll
Normal file
117
php/ql/lib/codeql/php/ast/Variable.qll
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Provides classes for PHP variables and names.
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** A name token (identifier). */
|
||||
class Name extends AstNode, @php_token_name {
|
||||
override string getAPrimaryQlClass() { result = "Name" }
|
||||
|
||||
/** Gets the string value of this name. */
|
||||
string getValue() { php_tokeninfo(this, _, result) }
|
||||
|
||||
override string toString() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/** A qualified name (`Namespace\ClassName`). */
|
||||
class QualifiedName extends AstNode, @php_qualified_name {
|
||||
override string getAPrimaryQlClass() { result = "QualifiedName" }
|
||||
|
||||
/** Gets the terminal name part. */
|
||||
Name getNamePart() { php_qualified_name_def(this, result) }
|
||||
|
||||
/** Gets the string value of the terminal name. */
|
||||
string getValue() { result = this.getNamePart().getValue() }
|
||||
|
||||
override string toString() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/** A namespace name. */
|
||||
class NamespaceName extends AstNode, @php_namespace_name {
|
||||
override string getAPrimaryQlClass() { result = "NamespaceName" }
|
||||
|
||||
/** Gets the i-th component name. */
|
||||
Name getComponent(int i) { php_namespace_name_child(this, i, result) }
|
||||
|
||||
/** Gets a component name. */
|
||||
Name getAComponent() { result = this.getComponent(_) }
|
||||
|
||||
override string toString() { result = "namespace_name" }
|
||||
}
|
||||
|
||||
/** A variable name (`$x`). */
|
||||
class VariableName extends AstNode, @php_variable_name {
|
||||
override string getAPrimaryQlClass() { result = "VariableName" }
|
||||
|
||||
/** Gets the inner name token. */
|
||||
Name getName() { php_variable_name_def(this, result) }
|
||||
|
||||
/** Gets the full variable name including the `$` prefix. */
|
||||
string getValue() { result = "$" + this.getName().getValue() }
|
||||
|
||||
/** Gets the name without the `$` prefix. */
|
||||
string getSimpleName() { result = this.getName().getValue() }
|
||||
|
||||
override string toString() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type node in a type annotation.
|
||||
*
|
||||
* This covers named types (`ClassName`), primitive types (`int`, `string`),
|
||||
* nullable types (`?int`), union types (`int|string`), and intersection types.
|
||||
*/
|
||||
class TypeNode extends AstNode, @php_type__ {
|
||||
override string getAPrimaryQlClass() { result = "TypeNode" }
|
||||
}
|
||||
|
||||
/** A named type (`ClassName`). */
|
||||
class NamedType extends TypeNode, @php_named_type {
|
||||
override string getAPrimaryQlClass() { result = "NamedType" }
|
||||
|
||||
AstNode getNameNode() { php_named_type_def(this, result) }
|
||||
|
||||
override string toString() { result = "named_type" }
|
||||
}
|
||||
|
||||
/** A primitive type (`int`, `string`, `bool`, etc.). */
|
||||
class PrimitiveType extends TypeNode, @php_token_primitive_type {
|
||||
override string getAPrimaryQlClass() { result = "PrimitiveType" }
|
||||
|
||||
string getValue() { php_tokeninfo(this, _, result) }
|
||||
|
||||
override string toString() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/** A nullable (optional) type (`?int`). */
|
||||
class OptionalType extends TypeNode, @php_optional_type {
|
||||
override string getAPrimaryQlClass() { result = "OptionalType" }
|
||||
|
||||
TypeNode getInnerType() { php_optional_type_def(this, result) }
|
||||
|
||||
override string toString() { result = "?..." }
|
||||
}
|
||||
|
||||
/** A union type (`int|string`). */
|
||||
class UnionType extends TypeNode, @php_union_type {
|
||||
override string getAPrimaryQlClass() { result = "UnionType" }
|
||||
|
||||
TypeNode getMember(int i) { php_union_type_child(this, i, result) }
|
||||
|
||||
TypeNode getAMember() { result = this.getMember(_) }
|
||||
|
||||
override string toString() { result = "...|..." }
|
||||
}
|
||||
|
||||
/** An intersection type (`Foo&Bar`). */
|
||||
class IntersectionType extends TypeNode, @php_intersection_type {
|
||||
override string getAPrimaryQlClass() { result = "IntersectionType" }
|
||||
|
||||
TypeNode getMember(int i) { php_intersection_type_child(this, i, result) }
|
||||
|
||||
TypeNode getAMember() { result = this.getMember(_) }
|
||||
|
||||
override string toString() { result = "...&..." }
|
||||
}
|
||||
10
php/ql/lib/codeql/php/ast/internal/AST.qll
Normal file
10
php/ql/lib/codeql/php/ast/internal/AST.qll
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Internal AST implementation for PHP.
|
||||
*/
|
||||
|
||||
import codeql.php.ast.internal.TreeSitter
|
||||
|
||||
/**
|
||||
* The base type for all PHP AST nodes.
|
||||
*/
|
||||
class TPhpAstNode = @php_ast_node;
|
||||
875
php/ql/lib/codeql/php/ast/internal/TreeSitter.qll
Normal file
875
php/ql/lib/codeql/php/ast/internal/TreeSitter.qll
Normal file
@@ -0,0 +1,875 @@
|
||||
/**
|
||||
* CodeQL library for Php
|
||||
* Automatically generated from the tree-sitter grammar; do not edit
|
||||
*/
|
||||
|
||||
import codeql.Locations as L
|
||||
|
||||
/** Holds if the database is an overlay. */overlay[local] private predicate isOverlay() { databaseMetadata("isOverlay", "true") }
|
||||
|
||||
/** Holds if `loc` is in the `file` and is part of the overlay base database. */overlay[local] private predicate discardableLocation(@file file, @location_default loc) { (not (isOverlay())) and (locations_default(loc, file, _, _, _, _)) }
|
||||
|
||||
/** Holds if `loc` should be discarded, because it is part of the overlay base and is in a file that was also extracted as part of the overlay database. */overlay[discard_entity] private predicate discardLocation(@location_default loc) { exists(@file file, string path | files(file, path) | (discardableLocation(file, loc)) and (overlayChangedFiles(path))) }
|
||||
|
||||
overlay[local] module Php {
|
||||
/** The base class for all AST nodes */class AstNode extends @php_ast_node {
|
||||
/** Gets a string representation of this element. */string toString() { result = this.getAPrimaryQlClass() }
|
||||
/** Gets the location of this element. */final L::Location getLocation() { php_ast_node_location(this, result) }
|
||||
/** Gets the parent of this element. */final AstNode getParent() { php_ast_node_parent(this, result, _) }
|
||||
/** Gets the index of this node among the children of its parent. */final int getParentIndex() { php_ast_node_parent(this, _, result) }
|
||||
/** Gets a field or child node of this node. */AstNode getAFieldOrChild() { none() }
|
||||
/** Gets the name of the primary QL class for this element. */string getAPrimaryQlClass() { result = "???" }
|
||||
/** Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. */string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
|
||||
}
|
||||
/** A token. */class Token extends @php_token, AstNode {
|
||||
/** Gets the value of this token. */final string getValue() { php_tokeninfo(this, _, result) }
|
||||
/** Gets a string representation of this element. */final override string toString() { result = this.getValue() }
|
||||
/** Gets the name of the primary QL class for this element. */override string getAPrimaryQlClass() { result = "Token" }
|
||||
}
|
||||
/** A reserved word. */class ReservedWord extends @php_reserved_word, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ReservedWord" }
|
||||
}
|
||||
/** Gets the file containing the given `node`. */private @file getNodeFile(@php_ast_node node) { exists(@location_default loc | php_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _)) }
|
||||
/** Holds if `node` is in the `file` and is part of the overlay base database. */private predicate discardableAstNode(@file file, @php_ast_node node) { (not (isOverlay())) and (file = getNodeFile(node)) }
|
||||
/** Holds if `node` should be discarded, because it is part of the overlay base and is in a file that was also extracted as part of the overlay database. */overlay[discard_entity] private predicate discardAstNode(@php_ast_node node) { exists(@file file, string path | files(file, path) | (discardableAstNode(file, node)) and (overlayChangedFiles(path))) }
|
||||
/** A class representing `abstract_modifier` tokens. */class AbstractModifier extends @php_token_abstract_modifier, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "AbstractModifier" }
|
||||
}
|
||||
/** A class representing `anonymous_class` nodes. */class AnonymousClass extends @php_anonymous_class, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "AnonymousClass" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_anonymous_class_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `body`. */final DeclarationList getBody() { php_anonymous_class_def(this, result) }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_anonymous_class_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_anonymous_class_attributes(this, result)) or (php_anonymous_class_def(this, result)) or (php_anonymous_class_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `anonymous_function` nodes. */class AnonymousFunction extends @php_anonymous_function, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "AnonymousFunction" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_anonymous_function_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `body`. */final CompoundStatement getBody() { php_anonymous_function_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `parameters`. */final FormalParameters getParameters() { php_anonymous_function_def(this, _, result) }
|
||||
/** Gets the node corresponding to the field `reference_modifier`. */final ReferenceModifier getReferenceModifier() { php_anonymous_function_reference_modifier(this, result) }
|
||||
/** Gets the node corresponding to the field `return_type`. */final AstNode getReturnType() { php_anonymous_function_return_type(this, result) }
|
||||
/** Gets the node corresponding to the field `static_modifier`. */final StaticModifier getStaticModifier() { php_anonymous_function_static_modifier(this, result) }
|
||||
/** Gets the child of this node. */final AnonymousFunctionUseClause getChild() { php_anonymous_function_child(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_anonymous_function_attributes(this, result)) or (php_anonymous_function_def(this, result, _)) or (php_anonymous_function_def(this, _, result)) or (php_anonymous_function_reference_modifier(this, result)) or (php_anonymous_function_return_type(this, result)) or (php_anonymous_function_static_modifier(this, result)) or (php_anonymous_function_child(this, result)) }
|
||||
}
|
||||
/** A class representing `anonymous_function_use_clause` nodes. */class AnonymousFunctionUseClause extends @php_anonymous_function_use_clause, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "AnonymousFunctionUseClause" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_anonymous_function_use_clause_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_anonymous_function_use_clause_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `argument` nodes. */class Argument extends @php_argument, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Argument" }
|
||||
/** Gets the node corresponding to the field `name`. */final Name getName() { php_argument_name(this, result) }
|
||||
/** Gets the node corresponding to the field `reference_modifier`. */final ReferenceModifier getReferenceModifier() { php_argument_reference_modifier(this, result) }
|
||||
/** Gets the child of this node. */final AstNode getChild() { php_argument_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_argument_name(this, result)) or (php_argument_reference_modifier(this, result)) or (php_argument_def(this, result)) }
|
||||
}
|
||||
/** A class representing `arguments` nodes. */class Arguments extends @php_arguments, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Arguments" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_arguments_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_arguments_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `array_creation_expression` nodes. */class ArrayCreationExpression extends @php_array_creation_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ArrayCreationExpression" }
|
||||
/** Gets the `i`th child of this node. */final ArrayElementInitializer getChild(int i) { php_array_creation_expression_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_array_creation_expression_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `array_element_initializer` nodes. */class ArrayElementInitializer extends @php_array_element_initializer, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ArrayElementInitializer" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_array_element_initializer_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_array_element_initializer_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `arrow_function` nodes. */class ArrowFunction extends @php_arrow_function, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ArrowFunction" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_arrow_function_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `body`. */final Expression getBody() { php_arrow_function_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `parameters`. */final FormalParameters getParameters() { php_arrow_function_def(this, _, result) }
|
||||
/** Gets the node corresponding to the field `reference_modifier`. */final ReferenceModifier getReferenceModifier() { php_arrow_function_reference_modifier(this, result) }
|
||||
/** Gets the node corresponding to the field `return_type`. */final AstNode getReturnType() { php_arrow_function_return_type(this, result) }
|
||||
/** Gets the node corresponding to the field `static_modifier`. */final StaticModifier getStaticModifier() { php_arrow_function_static_modifier(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_arrow_function_attributes(this, result)) or (php_arrow_function_def(this, result, _)) or (php_arrow_function_def(this, _, result)) or (php_arrow_function_reference_modifier(this, result)) or (php_arrow_function_return_type(this, result)) or (php_arrow_function_static_modifier(this, result)) }
|
||||
}
|
||||
/** A class representing `assignment_expression` nodes. */class AssignmentExpression extends @php_assignment_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "AssignmentExpression" }
|
||||
/** Gets the node corresponding to the field `left`. */final AstNode getLeft() { php_assignment_expression_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `right`. */final Expression getRight() { php_assignment_expression_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_assignment_expression_def(this, result, _)) or (php_assignment_expression_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `attribute` nodes. */class Attribute extends @php_attribute, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Attribute" }
|
||||
/** Gets the node corresponding to the field `parameters`. */final Arguments getParameters() { php_attribute_parameters(this, result) }
|
||||
/** Gets the child of this node. */final AstNode getChild() { php_attribute_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_attribute_parameters(this, result)) or (php_attribute_def(this, result)) }
|
||||
}
|
||||
/** A class representing `attribute_group` nodes. */class AttributeGroup extends @php_attribute_group, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "AttributeGroup" }
|
||||
/** Gets the `i`th child of this node. */final Attribute getChild(int i) { php_attribute_group_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_attribute_group_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `attribute_list` nodes. */class AttributeList extends @php_attribute_list, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "AttributeList" }
|
||||
/** Gets the `i`th child of this node. */final AttributeGroup getChild(int i) { php_attribute_list_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_attribute_list_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `augmented_assignment_expression` nodes. */class AugmentedAssignmentExpression extends @php_augmented_assignment_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "AugmentedAssignmentExpression" }
|
||||
/** Gets the node corresponding to the field `left`. */final AstNode getLeft() { php_augmented_assignment_expression_def(this, result, _, _) }
|
||||
/** Gets the node corresponding to the field `operator`. */final string getOperator() { exists(int value | php_augmented_assignment_expression_def(this, _, value, _) | ((result = "%=") and (value = 0)) or ((result = "&=") and (value = 1)) or ((result = "**=") and (value = 2)) or ((result = "*=") and (value = 3)) or ((result = "+=") and (value = 4)) or ((result = "-=") and (value = 5)) or ((result = ".=") and (value = 6)) or ((result = "/=") and (value = 7)) or ((result = "<<=") and (value = 8)) or ((result = ">>=") and (value = 9)) or ((result = "??=") and (value = 10)) or ((result = "^=") and (value = 11)) or ((result = "|=") and (value = 12))) }
|
||||
/** Gets the node corresponding to the field `right`. */final Expression getRight() { php_augmented_assignment_expression_def(this, _, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_augmented_assignment_expression_def(this, result, _, _)) or (php_augmented_assignment_expression_def(this, _, _, result)) }
|
||||
}
|
||||
/** A class representing `base_clause` nodes. */class BaseClause extends @php_base_clause, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "BaseClause" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_base_clause_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_base_clause_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `binary_expression` nodes. */class BinaryExpression extends @php_binary_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "BinaryExpression" }
|
||||
/** Gets the node corresponding to the field `left`. */final Expression getLeft() { php_binary_expression_def(this, result, _, _) }
|
||||
/** Gets the node corresponding to the field `operator`. */final string getOperator() { exists(int value | php_binary_expression_def(this, _, value, _) | ((result = "!=") and (value = 0)) or ((result = "!==") and (value = 1)) or ((result = "%") and (value = 2)) or ((result = "&") and (value = 3)) or ((result = "&&") and (value = 4)) or ((result = "*") and (value = 5)) or ((result = "**") and (value = 6)) or ((result = "+") and (value = 7)) or ((result = "-") and (value = 8)) or ((result = ".") and (value = 9)) or ((result = "/") and (value = 10)) or ((result = "<") and (value = 11)) or ((result = "<<") and (value = 12)) or ((result = "<=") and (value = 13)) or ((result = "<=>") and (value = 14)) or ((result = "<>") and (value = 15)) or ((result = "==") and (value = 16)) or ((result = "===") and (value = 17)) or ((result = ">") and (value = 18)) or ((result = ">=") and (value = 19)) or ((result = ">>") and (value = 20)) or ((result = "??") and (value = 21)) or ((result = "^") and (value = 22)) or ((result = "and") and (value = 23)) or ((result = "instanceof") and (value = 24)) or ((result = "or") and (value = 25)) or ((result = "xor") and (value = 26)) or ((result = "|") and (value = 27)) or ((result = "||") and (value = 28))) }
|
||||
/** Gets the node corresponding to the field `right`. */final AstNode getRight() { php_binary_expression_def(this, _, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_binary_expression_def(this, result, _, _)) or (php_binary_expression_def(this, _, _, result)) }
|
||||
}
|
||||
/** A class representing `boolean` tokens. */class Boolean extends @php_token_boolean, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Boolean" }
|
||||
}
|
||||
/** A class representing `bottom_type` tokens. */class BottomType extends @php_token_bottom_type, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "BottomType" }
|
||||
}
|
||||
/** A class representing `break_statement` nodes. */class BreakStatement extends @php_break_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "BreakStatement" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_break_statement_child(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_break_statement_child(this, result)) }
|
||||
}
|
||||
/** A class representing `by_ref` nodes. */class ByRef extends @php_by_ref, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ByRef" }
|
||||
/** Gets the child of this node. */final AstNode getChild() { php_by_ref_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_by_ref_def(this, result)) }
|
||||
}
|
||||
/** A class representing `case_statement` nodes. */class CaseStatement extends @php_case_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "CaseStatement" }
|
||||
/** Gets the node corresponding to the field `value`. */final Expression getValue() { php_case_statement_def(this, result) }
|
||||
/** Gets the `i`th child of this node. */final Statement getChild(int i) { php_case_statement_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_case_statement_def(this, result)) or (php_case_statement_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `cast_expression` nodes. */class CastExpression extends @php_cast_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "CastExpression" }
|
||||
/** Gets the node corresponding to the field `type`. */final CastType getType() { php_cast_expression_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `value`. */final AstNode getValue() { php_cast_expression_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_cast_expression_def(this, result, _)) or (php_cast_expression_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `cast_type` tokens. */class CastType extends @php_token_cast_type, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "CastType" }
|
||||
}
|
||||
/** A class representing `catch_clause` nodes. */class CatchClause extends @php_catch_clause, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "CatchClause" }
|
||||
/** Gets the node corresponding to the field `body`. */final CompoundStatement getBody() { php_catch_clause_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `name`. */final VariableName getName() { php_catch_clause_name(this, result) }
|
||||
/** Gets the node corresponding to the field `type`. */final TypeList getType() { php_catch_clause_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_catch_clause_def(this, result, _)) or (php_catch_clause_name(this, result)) or (php_catch_clause_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `class_constant_access_expression` nodes. */class ClassConstantAccessExpression extends @php_class_constant_access_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ClassConstantAccessExpression" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_class_constant_access_expression_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_class_constant_access_expression_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `class_declaration` nodes. */class ClassDeclaration extends @php_class_declaration, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ClassDeclaration" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_class_declaration_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `body`. */final DeclarationList getBody() { php_class_declaration_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `name`. */final Name getName() { php_class_declaration_def(this, _, result) }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_class_declaration_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_class_declaration_attributes(this, result)) or (php_class_declaration_def(this, result, _)) or (php_class_declaration_def(this, _, result)) or (php_class_declaration_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `class_interface_clause` nodes. */class ClassInterfaceClause extends @php_class_interface_clause, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ClassInterfaceClause" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_class_interface_clause_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_class_interface_clause_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `clone_expression` nodes. */class CloneExpression extends @php_clone_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "CloneExpression" }
|
||||
/** Gets the child of this node. */final PrimaryExpression getChild() { php_clone_expression_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_clone_expression_def(this, result)) }
|
||||
}
|
||||
/** A class representing `colon_block` nodes. */class ColonBlock extends @php_colon_block, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ColonBlock" }
|
||||
/** Gets the `i`th child of this node. */final Statement getChild(int i) { php_colon_block_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_colon_block_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `comment` tokens. */class Comment extends @php_token_comment, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Comment" }
|
||||
}
|
||||
/** A class representing `compound_statement` nodes. */class CompoundStatement extends @php_compound_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "CompoundStatement" }
|
||||
/** Gets the `i`th child of this node. */final Statement getChild(int i) { php_compound_statement_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_compound_statement_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `conditional_expression` nodes. */class ConditionalExpression extends @php_conditional_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ConditionalExpression" }
|
||||
/** Gets the node corresponding to the field `alternative`. */final Expression getAlternative() { php_conditional_expression_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `body`. */final Expression getBody() { php_conditional_expression_body(this, result) }
|
||||
/** Gets the node corresponding to the field `condition`. */final Expression getCondition() { php_conditional_expression_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_conditional_expression_def(this, result, _)) or (php_conditional_expression_body(this, result)) or (php_conditional_expression_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `const_declaration` nodes. */class ConstDeclaration extends @php_const_declaration, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ConstDeclaration" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_const_declaration_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `type`. */final Type getType() { php_const_declaration_type(this, result) }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_const_declaration_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_const_declaration_attributes(this, result)) or (php_const_declaration_type(this, result)) or (php_const_declaration_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `const_element` nodes. */class ConstElement extends @php_const_element, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ConstElement" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_const_element_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_const_element_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `continue_statement` nodes. */class ContinueStatement extends @php_continue_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ContinueStatement" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_continue_statement_child(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_continue_statement_child(this, result)) }
|
||||
}
|
||||
/** A class representing `declaration_list` nodes. */class DeclarationList extends @php_declaration_list, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "DeclarationList" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_declaration_list_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_declaration_list_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `declare_directive` nodes. */class DeclareDirective extends @php_declare_directive, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "DeclareDirective" }
|
||||
/** Gets the child of this node. */final Literal getChild() { php_declare_directive_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_declare_directive_def(this, result)) }
|
||||
}
|
||||
/** A class representing `declare_statement` nodes. */class DeclareStatement extends @php_declare_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "DeclareStatement" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_declare_statement_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_declare_statement_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `default_statement` nodes. */class DefaultStatement extends @php_default_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "DefaultStatement" }
|
||||
/** Gets the `i`th child of this node. */final Statement getChild(int i) { php_default_statement_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_default_statement_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `disjunctive_normal_form_type` nodes. */class DisjunctiveNormalFormType extends @php_disjunctive_normal_form_type, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "DisjunctiveNormalFormType" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_disjunctive_normal_form_type_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_disjunctive_normal_form_type_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `do_statement` nodes. */class DoStatement extends @php_do_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "DoStatement" }
|
||||
/** Gets the node corresponding to the field `body`. */final Statement getBody() { php_do_statement_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `condition`. */final ParenthesizedExpression getCondition() { php_do_statement_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_do_statement_def(this, result, _)) or (php_do_statement_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `dynamic_variable_name` nodes. */class DynamicVariableName extends @php_dynamic_variable_name, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "DynamicVariableName" }
|
||||
/** Gets the child of this node. */final AstNode getChild() { php_dynamic_variable_name_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_dynamic_variable_name_def(this, result)) }
|
||||
}
|
||||
/** A class representing `echo_statement` nodes. */class EchoStatement extends @php_echo_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "EchoStatement" }
|
||||
/** Gets the child of this node. */final AstNode getChild() { php_echo_statement_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_echo_statement_def(this, result)) }
|
||||
}
|
||||
/** A class representing `else_clause` nodes. */class ElseClause extends @php_else_clause, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ElseClause" }
|
||||
/** Gets the node corresponding to the field `body`. */final AstNode getBody() { php_else_clause_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_else_clause_def(this, result)) }
|
||||
}
|
||||
/** A class representing `else_if_clause` nodes. */class ElseIfClause extends @php_else_if_clause, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ElseIfClause" }
|
||||
/** Gets the node corresponding to the field `body`. */final AstNode getBody() { php_else_if_clause_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `condition`. */final ParenthesizedExpression getCondition() { php_else_if_clause_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_else_if_clause_def(this, result, _)) or (php_else_if_clause_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `empty_statement` tokens. */class EmptyStatement extends @php_token_empty_statement, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "EmptyStatement" }
|
||||
}
|
||||
/** A class representing `encapsed_string` nodes. */class EncapsedString extends @php_encapsed_string, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "EncapsedString" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_encapsed_string_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_encapsed_string_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `enum_case` nodes. */class EnumCase extends @php_enum_case, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "EnumCase" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_enum_case_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `name`. */final Name getName() { php_enum_case_def(this, result) }
|
||||
/** Gets the node corresponding to the field `value`. */final Expression getValue() { php_enum_case_value(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_enum_case_attributes(this, result)) or (php_enum_case_def(this, result)) or (php_enum_case_value(this, result)) }
|
||||
}
|
||||
/** A class representing `enum_declaration` nodes. */class EnumDeclaration extends @php_enum_declaration, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "EnumDeclaration" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_enum_declaration_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `body`. */final EnumDeclarationList getBody() { php_enum_declaration_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `name`. */final Name getName() { php_enum_declaration_def(this, _, result) }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_enum_declaration_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_enum_declaration_attributes(this, result)) or (php_enum_declaration_def(this, result, _)) or (php_enum_declaration_def(this, _, result)) or (php_enum_declaration_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `enum_declaration_list` nodes. */class EnumDeclarationList extends @php_enum_declaration_list, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "EnumDeclarationList" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_enum_declaration_list_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_enum_declaration_list_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `error_suppression_expression` nodes. */class ErrorSuppressionExpression extends @php_error_suppression_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ErrorSuppressionExpression" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_error_suppression_expression_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_error_suppression_expression_def(this, result)) }
|
||||
}
|
||||
/** A class representing `escape_sequence` tokens. */class EscapeSequence extends @php_token_escape_sequence, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "EscapeSequence" }
|
||||
}
|
||||
/** A class representing `exit_statement` nodes. */class ExitStatement extends @php_exit_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ExitStatement" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_exit_statement_child(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_exit_statement_child(this, result)) }
|
||||
}
|
||||
class Expression extends @php_expression, AstNode {
|
||||
}
|
||||
/** A class representing `expression_statement` nodes. */class ExpressionStatement extends @php_expression_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ExpressionStatement" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_expression_statement_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_expression_statement_def(this, result)) }
|
||||
}
|
||||
/** A class representing `final_modifier` tokens. */class FinalModifier extends @php_token_final_modifier, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "FinalModifier" }
|
||||
}
|
||||
/** A class representing `finally_clause` nodes. */class FinallyClause extends @php_finally_clause, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "FinallyClause" }
|
||||
/** Gets the node corresponding to the field `body`. */final CompoundStatement getBody() { php_finally_clause_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_finally_clause_def(this, result)) }
|
||||
}
|
||||
/** A class representing `float` tokens. */class Float extends @php_token_float, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Float" }
|
||||
}
|
||||
/** A class representing `for_statement` nodes. */class ForStatement extends @php_for_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ForStatement" }
|
||||
/** Gets the node corresponding to the field `body`. */final Statement getBody(int i) { php_for_statement_body(this, i, result) }
|
||||
/** Gets the node corresponding to the field `condition`. */final AstNode getCondition() { php_for_statement_condition(this, result) }
|
||||
/** Gets the node corresponding to the field `initialize`. */final AstNode getInitialize() { php_for_statement_initialize(this, result) }
|
||||
/** Gets the node corresponding to the field `update`. */final AstNode getUpdate() { php_for_statement_update(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_for_statement_body(this, _, result)) or (php_for_statement_condition(this, result)) or (php_for_statement_initialize(this, result)) or (php_for_statement_update(this, result)) }
|
||||
}
|
||||
/** A class representing `foreach_statement` nodes. */class ForeachStatement extends @php_foreach_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ForeachStatement" }
|
||||
/** Gets the node corresponding to the field `body`. */final AstNode getBody() { php_foreach_statement_body(this, result) }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_foreach_statement_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_foreach_statement_body(this, result)) or (php_foreach_statement_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `formal_parameters` nodes. */class FormalParameters extends @php_formal_parameters, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "FormalParameters" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_formal_parameters_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_formal_parameters_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `function_call_expression` nodes. */class FunctionCallExpression extends @php_function_call_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "FunctionCallExpression" }
|
||||
/** Gets the node corresponding to the field `arguments`. */final Arguments getArguments() { php_function_call_expression_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `function`. */final AstNode getFunction() { php_function_call_expression_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_function_call_expression_def(this, result, _)) or (php_function_call_expression_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `function_definition` nodes. */class FunctionDefinition extends @php_function_definition, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "FunctionDefinition" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_function_definition_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `body`. */final CompoundStatement getBody() { php_function_definition_def(this, result, _, _) }
|
||||
/** Gets the node corresponding to the field `name`. */final Name getName() { php_function_definition_def(this, _, result, _) }
|
||||
/** Gets the node corresponding to the field `parameters`. */final FormalParameters getParameters() { php_function_definition_def(this, _, _, result) }
|
||||
/** Gets the node corresponding to the field `return_type`. */final AstNode getReturnType() { php_function_definition_return_type(this, result) }
|
||||
/** Gets the child of this node. */final ReferenceModifier getChild() { php_function_definition_child(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_function_definition_attributes(this, result)) or (php_function_definition_def(this, result, _, _)) or (php_function_definition_def(this, _, result, _)) or (php_function_definition_def(this, _, _, result)) or (php_function_definition_return_type(this, result)) or (php_function_definition_child(this, result)) }
|
||||
}
|
||||
/** A class representing `function_static_declaration` nodes. */class FunctionStaticDeclaration extends @php_function_static_declaration, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "FunctionStaticDeclaration" }
|
||||
/** Gets the `i`th child of this node. */final StaticVariableDeclaration getChild(int i) { php_function_static_declaration_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_function_static_declaration_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `global_declaration` nodes. */class GlobalDeclaration extends @php_global_declaration, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "GlobalDeclaration" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_global_declaration_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_global_declaration_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `goto_statement` nodes. */class GotoStatement extends @php_goto_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "GotoStatement" }
|
||||
/** Gets the child of this node. */final Name getChild() { php_goto_statement_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_goto_statement_def(this, result)) }
|
||||
}
|
||||
/** A class representing `heredoc` nodes. */class Heredoc extends @php_heredoc, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Heredoc" }
|
||||
/** Gets the node corresponding to the field `end_tag`. */final HeredocEnd getEndTag() { php_heredoc_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `identifier`. */final HeredocStart getIdentifier() { php_heredoc_def(this, _, result) }
|
||||
/** Gets the node corresponding to the field `value`. */final HeredocBody getValue() { php_heredoc_value(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_heredoc_def(this, result, _)) or (php_heredoc_def(this, _, result)) or (php_heredoc_value(this, result)) }
|
||||
}
|
||||
/** A class representing `heredoc_body` nodes. */class HeredocBody extends @php_heredoc_body, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "HeredocBody" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_heredoc_body_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_heredoc_body_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `heredoc_end` tokens. */class HeredocEnd extends @php_token_heredoc_end, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "HeredocEnd" }
|
||||
}
|
||||
/** A class representing `heredoc_start` tokens. */class HeredocStart extends @php_token_heredoc_start, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "HeredocStart" }
|
||||
}
|
||||
/** A class representing `if_statement` nodes. */class IfStatement extends @php_if_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "IfStatement" }
|
||||
/** Gets the node corresponding to the field `alternative`. */final AstNode getAlternative(int i) { php_if_statement_alternative(this, i, result) }
|
||||
/** Gets the node corresponding to the field `body`. */final AstNode getBody() { php_if_statement_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `condition`. */final ParenthesizedExpression getCondition() { php_if_statement_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_if_statement_alternative(this, _, result)) or (php_if_statement_def(this, result, _)) or (php_if_statement_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `include_expression` nodes. */class IncludeExpression extends @php_include_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "IncludeExpression" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_include_expression_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_include_expression_def(this, result)) }
|
||||
}
|
||||
/** A class representing `include_once_expression` nodes. */class IncludeOnceExpression extends @php_include_once_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "IncludeOnceExpression" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_include_once_expression_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_include_once_expression_def(this, result)) }
|
||||
}
|
||||
/** A class representing `integer` tokens. */class Integer extends @php_token_integer, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Integer" }
|
||||
}
|
||||
/** A class representing `interface_declaration` nodes. */class InterfaceDeclaration extends @php_interface_declaration, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "InterfaceDeclaration" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_interface_declaration_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `body`. */final DeclarationList getBody() { php_interface_declaration_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `name`. */final Name getName() { php_interface_declaration_def(this, _, result) }
|
||||
/** Gets the child of this node. */final BaseClause getChild() { php_interface_declaration_child(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_interface_declaration_attributes(this, result)) or (php_interface_declaration_def(this, result, _)) or (php_interface_declaration_def(this, _, result)) or (php_interface_declaration_child(this, result)) }
|
||||
}
|
||||
/** A class representing `intersection_type` nodes. */class IntersectionType extends @php_intersection_type, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "IntersectionType" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_intersection_type_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_intersection_type_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `list_literal` nodes. */class ListLiteral extends @php_list_literal, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ListLiteral" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_list_literal_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_list_literal_child(this, _, result)) }
|
||||
}
|
||||
class Literal extends @php_literal, AstNode {
|
||||
}
|
||||
/** A class representing `match_block` nodes. */class MatchBlock extends @php_match_block, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "MatchBlock" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_match_block_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_match_block_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `match_condition_list` nodes. */class MatchConditionList extends @php_match_condition_list, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "MatchConditionList" }
|
||||
/** Gets the `i`th child of this node. */final Expression getChild(int i) { php_match_condition_list_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_match_condition_list_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `match_conditional_expression` nodes. */class MatchConditionalExpression extends @php_match_conditional_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "MatchConditionalExpression" }
|
||||
/** Gets the node corresponding to the field `conditional_expressions`. */final MatchConditionList getConditionalExpressions() { php_match_conditional_expression_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `return_expression`. */final Expression getReturnExpression() { php_match_conditional_expression_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_match_conditional_expression_def(this, result, _)) or (php_match_conditional_expression_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `match_default_expression` nodes. */class MatchDefaultExpression extends @php_match_default_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "MatchDefaultExpression" }
|
||||
/** Gets the node corresponding to the field `return_expression`. */final Expression getReturnExpression() { php_match_default_expression_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_match_default_expression_def(this, result)) }
|
||||
}
|
||||
/** A class representing `match_expression` nodes. */class MatchExpression extends @php_match_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "MatchExpression" }
|
||||
/** Gets the node corresponding to the field `body`. */final MatchBlock getBody() { php_match_expression_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `condition`. */final ParenthesizedExpression getCondition() { php_match_expression_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_match_expression_def(this, result, _)) or (php_match_expression_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `member_access_expression` nodes. */class MemberAccessExpression extends @php_member_access_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "MemberAccessExpression" }
|
||||
/** Gets the node corresponding to the field `name`. */final AstNode getName() { php_member_access_expression_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `object`. */final AstNode getObject() { php_member_access_expression_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_member_access_expression_def(this, result, _)) or (php_member_access_expression_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `member_call_expression` nodes. */class MemberCallExpression extends @php_member_call_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "MemberCallExpression" }
|
||||
/** Gets the node corresponding to the field `arguments`. */final Arguments getArguments() { php_member_call_expression_def(this, result, _, _) }
|
||||
/** Gets the node corresponding to the field `name`. */final AstNode getName() { php_member_call_expression_def(this, _, result, _) }
|
||||
/** Gets the node corresponding to the field `object`. */final AstNode getObject() { php_member_call_expression_def(this, _, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_member_call_expression_def(this, result, _, _)) or (php_member_call_expression_def(this, _, result, _)) or (php_member_call_expression_def(this, _, _, result)) }
|
||||
}
|
||||
/** A class representing `method_declaration` nodes. */class MethodDeclaration extends @php_method_declaration, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "MethodDeclaration" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_method_declaration_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `body`. */final CompoundStatement getBody() { php_method_declaration_body(this, result) }
|
||||
/** Gets the node corresponding to the field `name`. */final Name getName() { php_method_declaration_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `parameters`. */final FormalParameters getParameters() { php_method_declaration_def(this, _, result) }
|
||||
/** Gets the node corresponding to the field `return_type`. */final AstNode getReturnType() { php_method_declaration_return_type(this, result) }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_method_declaration_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_method_declaration_attributes(this, result)) or (php_method_declaration_body(this, result)) or (php_method_declaration_def(this, result, _)) or (php_method_declaration_def(this, _, result)) or (php_method_declaration_return_type(this, result)) or (php_method_declaration_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `name` tokens. */class Name extends @php_token_name, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Name" }
|
||||
}
|
||||
/** A class representing `named_label_statement` nodes. */class NamedLabelStatement extends @php_named_label_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "NamedLabelStatement" }
|
||||
/** Gets the child of this node. */final Name getChild() { php_named_label_statement_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_named_label_statement_def(this, result)) }
|
||||
}
|
||||
/** A class representing `named_type` nodes. */class NamedType extends @php_named_type, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "NamedType" }
|
||||
/** Gets the child of this node. */final AstNode getChild() { php_named_type_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_named_type_def(this, result)) }
|
||||
}
|
||||
/** A class representing `namespace_definition` nodes. */class NamespaceDefinition extends @php_namespace_definition, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "NamespaceDefinition" }
|
||||
/** Gets the node corresponding to the field `body`. */final CompoundStatement getBody() { php_namespace_definition_body(this, result) }
|
||||
/** Gets the node corresponding to the field `name`. */final NamespaceName getName() { php_namespace_definition_name(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_namespace_definition_body(this, result)) or (php_namespace_definition_name(this, result)) }
|
||||
}
|
||||
/** A class representing `namespace_name` nodes. */class NamespaceName extends @php_namespace_name, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "NamespaceName" }
|
||||
/** Gets the `i`th child of this node. */final Name getChild(int i) { php_namespace_name_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_namespace_name_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `namespace_use_clause` nodes. */class NamespaceUseClause extends @php_namespace_use_clause, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "NamespaceUseClause" }
|
||||
/** Gets the node corresponding to the field `alias`. */final Name getAlias() { php_namespace_use_clause_alias(this, result) }
|
||||
/** Gets the node corresponding to the field `type`. */final AstNode getType() { php_namespace_use_clause_type(this, result) }
|
||||
/** Gets the child of this node. */final AstNode getChild() { php_namespace_use_clause_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_namespace_use_clause_alias(this, result)) or (php_namespace_use_clause_type(this, result)) or (php_namespace_use_clause_def(this, result)) }
|
||||
}
|
||||
/** A class representing `namespace_use_declaration` nodes. */class NamespaceUseDeclaration extends @php_namespace_use_declaration, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "NamespaceUseDeclaration" }
|
||||
/** Gets the node corresponding to the field `body`. */final NamespaceUseGroup getBody() { php_namespace_use_declaration_body(this, result) }
|
||||
/** Gets the node corresponding to the field `type`. */final AstNode getType() { php_namespace_use_declaration_type(this, result) }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_namespace_use_declaration_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_namespace_use_declaration_body(this, result)) or (php_namespace_use_declaration_type(this, result)) or (php_namespace_use_declaration_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `namespace_use_group` nodes. */class NamespaceUseGroup extends @php_namespace_use_group, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "NamespaceUseGroup" }
|
||||
/** Gets the `i`th child of this node. */final NamespaceUseClause getChild(int i) { php_namespace_use_group_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_namespace_use_group_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `nowdoc` nodes. */class Nowdoc extends @php_nowdoc, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Nowdoc" }
|
||||
/** Gets the node corresponding to the field `end_tag`. */final HeredocEnd getEndTag() { php_nowdoc_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `identifier`. */final HeredocStart getIdentifier() { php_nowdoc_def(this, _, result) }
|
||||
/** Gets the node corresponding to the field `value`. */final NowdocBody getValue() { php_nowdoc_value(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_nowdoc_def(this, result, _)) or (php_nowdoc_def(this, _, result)) or (php_nowdoc_value(this, result)) }
|
||||
}
|
||||
/** A class representing `nowdoc_body` nodes. */class NowdocBody extends @php_nowdoc_body, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "NowdocBody" }
|
||||
/** Gets the `i`th child of this node. */final NowdocString getChild(int i) { php_nowdoc_body_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_nowdoc_body_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `nowdoc_string` tokens. */class NowdocString extends @php_token_nowdoc_string, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "NowdocString" }
|
||||
}
|
||||
/** A class representing `null` tokens. */class Null extends @php_token_null, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Null" }
|
||||
}
|
||||
/** A class representing `nullsafe_member_access_expression` nodes. */class NullsafeMemberAccessExpression extends @php_nullsafe_member_access_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "NullsafeMemberAccessExpression" }
|
||||
/** Gets the node corresponding to the field `name`. */final AstNode getName() { php_nullsafe_member_access_expression_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `object`. */final AstNode getObject() { php_nullsafe_member_access_expression_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_nullsafe_member_access_expression_def(this, result, _)) or (php_nullsafe_member_access_expression_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `nullsafe_member_call_expression` nodes. */class NullsafeMemberCallExpression extends @php_nullsafe_member_call_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "NullsafeMemberCallExpression" }
|
||||
/** Gets the node corresponding to the field `arguments`. */final Arguments getArguments() { php_nullsafe_member_call_expression_def(this, result, _, _) }
|
||||
/** Gets the node corresponding to the field `name`. */final AstNode getName() { php_nullsafe_member_call_expression_def(this, _, result, _) }
|
||||
/** Gets the node corresponding to the field `object`. */final AstNode getObject() { php_nullsafe_member_call_expression_def(this, _, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_nullsafe_member_call_expression_def(this, result, _, _)) or (php_nullsafe_member_call_expression_def(this, _, result, _)) or (php_nullsafe_member_call_expression_def(this, _, _, result)) }
|
||||
}
|
||||
/** A class representing `object_creation_expression` nodes. */class ObjectCreationExpression extends @php_object_creation_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ObjectCreationExpression" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_object_creation_expression_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_object_creation_expression_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `operation` tokens. */class Operation extends @php_token_operation, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Operation" }
|
||||
}
|
||||
/** A class representing `optional_type` nodes. */class OptionalType extends @php_optional_type, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "OptionalType" }
|
||||
/** Gets the child of this node. */final AstNode getChild() { php_optional_type_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_optional_type_def(this, result)) }
|
||||
}
|
||||
/** A class representing `pair` nodes. */class Pair extends @php_pair, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Pair" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_pair_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_pair_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `parenthesized_expression` nodes. */class ParenthesizedExpression extends @php_parenthesized_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ParenthesizedExpression" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_parenthesized_expression_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_parenthesized_expression_def(this, result)) }
|
||||
}
|
||||
/** A class representing `php_tag` tokens. */class PhpTag extends @php_token_php_tag, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "PhpTag" }
|
||||
}
|
||||
class PrimaryExpression extends @php_primary_expression, AstNode {
|
||||
}
|
||||
/** A class representing `primitive_type` tokens. */class PrimitiveType extends @php_token_primitive_type, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "PrimitiveType" }
|
||||
}
|
||||
/** A class representing `print_intrinsic` nodes. */class PrintIntrinsic extends @php_print_intrinsic, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "PrintIntrinsic" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_print_intrinsic_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_print_intrinsic_def(this, result)) }
|
||||
}
|
||||
/** A class representing `program` nodes. */class Program extends @php_program, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Program" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_program_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_program_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `property_declaration` nodes. */class PropertyDeclaration extends @php_property_declaration, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "PropertyDeclaration" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_property_declaration_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `type`. */final Type getType() { php_property_declaration_type(this, result) }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_property_declaration_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_property_declaration_attributes(this, result)) or (php_property_declaration_type(this, result)) or (php_property_declaration_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `property_element` nodes. */class PropertyElement extends @php_property_element, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "PropertyElement" }
|
||||
/** Gets the node corresponding to the field `default_value`. */final Expression getDefaultValue() { php_property_element_default_value(this, result) }
|
||||
/** Gets the node corresponding to the field `name`. */final VariableName getName() { php_property_element_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_property_element_default_value(this, result)) or (php_property_element_def(this, result)) }
|
||||
}
|
||||
/** A class representing `property_hook` nodes. */class PropertyHook extends @php_property_hook, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "PropertyHook" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_property_hook_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `body`. */final AstNode getBody() { php_property_hook_body(this, result) }
|
||||
/** Gets the node corresponding to the field `final`. */final FinalModifier getFinal() { php_property_hook_final(this, result) }
|
||||
/** Gets the node corresponding to the field `parameters`. */final FormalParameters getParameters() { php_property_hook_parameters(this, result) }
|
||||
/** Gets the node corresponding to the field `reference_modifier`. */final ReferenceModifier getReferenceModifier() { php_property_hook_reference_modifier(this, result) }
|
||||
/** Gets the child of this node. */final Name getChild() { php_property_hook_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_property_hook_attributes(this, result)) or (php_property_hook_body(this, result)) or (php_property_hook_final(this, result)) or (php_property_hook_parameters(this, result)) or (php_property_hook_reference_modifier(this, result)) or (php_property_hook_def(this, result)) }
|
||||
}
|
||||
/** A class representing `property_hook_list` nodes. */class PropertyHookList extends @php_property_hook_list, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "PropertyHookList" }
|
||||
/** Gets the `i`th child of this node. */final PropertyHook getChild(int i) { php_property_hook_list_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_property_hook_list_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `property_promotion_parameter` nodes. */class PropertyPromotionParameter extends @php_property_promotion_parameter, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "PropertyPromotionParameter" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_property_promotion_parameter_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `default_value`. */final Expression getDefaultValue() { php_property_promotion_parameter_default_value(this, result) }
|
||||
/** Gets the node corresponding to the field `name`. */final AstNode getName() { php_property_promotion_parameter_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `readonly`. */final ReadonlyModifier getReadonly() { php_property_promotion_parameter_readonly(this, result) }
|
||||
/** Gets the node corresponding to the field `type`. */final Type getType() { php_property_promotion_parameter_type(this, result) }
|
||||
/** Gets the node corresponding to the field `visibility`. */final VisibilityModifier getVisibility() { php_property_promotion_parameter_def(this, _, result) }
|
||||
/** Gets the child of this node. */final PropertyHookList getChild() { php_property_promotion_parameter_child(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_property_promotion_parameter_attributes(this, result)) or (php_property_promotion_parameter_default_value(this, result)) or (php_property_promotion_parameter_def(this, result, _)) or (php_property_promotion_parameter_readonly(this, result)) or (php_property_promotion_parameter_type(this, result)) or (php_property_promotion_parameter_def(this, _, result)) or (php_property_promotion_parameter_child(this, result)) }
|
||||
}
|
||||
/** A class representing `qualified_name` nodes. */class QualifiedName extends @php_qualified_name, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "QualifiedName" }
|
||||
/** Gets the node corresponding to the field `prefix`. */final AstNode getPrefix(int i) { php_qualified_name_prefix(this, i, result) }
|
||||
/** Gets the child of this node. */final Name getChild() { php_qualified_name_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_qualified_name_prefix(this, _, result)) or (php_qualified_name_def(this, result)) }
|
||||
}
|
||||
/** A class representing `readonly_modifier` tokens. */class ReadonlyModifier extends @php_token_readonly_modifier, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ReadonlyModifier" }
|
||||
}
|
||||
/** A class representing `reference_assignment_expression` nodes. */class ReferenceAssignmentExpression extends @php_reference_assignment_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ReferenceAssignmentExpression" }
|
||||
/** Gets the node corresponding to the field `left`. */final AstNode getLeft() { php_reference_assignment_expression_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `right`. */final Expression getRight() { php_reference_assignment_expression_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_reference_assignment_expression_def(this, result, _)) or (php_reference_assignment_expression_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `reference_modifier` tokens. */class ReferenceModifier extends @php_token_reference_modifier, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ReferenceModifier" }
|
||||
}
|
||||
/** A class representing `relative_scope` tokens. */class RelativeScope extends @php_token_relative_scope, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "RelativeScope" }
|
||||
}
|
||||
/** A class representing `require_expression` nodes. */class RequireExpression extends @php_require_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "RequireExpression" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_require_expression_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_require_expression_def(this, result)) }
|
||||
}
|
||||
/** A class representing `require_once_expression` nodes. */class RequireOnceExpression extends @php_require_once_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "RequireOnceExpression" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_require_once_expression_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_require_once_expression_def(this, result)) }
|
||||
}
|
||||
/** A class representing `return_statement` nodes. */class ReturnStatement extends @php_return_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ReturnStatement" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_return_statement_child(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_return_statement_child(this, result)) }
|
||||
}
|
||||
/** A class representing `scoped_call_expression` nodes. */class ScopedCallExpression extends @php_scoped_call_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ScopedCallExpression" }
|
||||
/** Gets the node corresponding to the field `arguments`. */final Arguments getArguments() { php_scoped_call_expression_def(this, result, _, _) }
|
||||
/** Gets the node corresponding to the field `name`. */final AstNode getName() { php_scoped_call_expression_def(this, _, result, _) }
|
||||
/** Gets the node corresponding to the field `scope`. */final AstNode getScope() { php_scoped_call_expression_def(this, _, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_scoped_call_expression_def(this, result, _, _)) or (php_scoped_call_expression_def(this, _, result, _)) or (php_scoped_call_expression_def(this, _, _, result)) }
|
||||
}
|
||||
/** A class representing `scoped_property_access_expression` nodes. */class ScopedPropertyAccessExpression extends @php_scoped_property_access_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ScopedPropertyAccessExpression" }
|
||||
/** Gets the node corresponding to the field `name`. */final AstNode getName() { php_scoped_property_access_expression_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `scope`. */final AstNode getScope() { php_scoped_property_access_expression_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_scoped_property_access_expression_def(this, result, _)) or (php_scoped_property_access_expression_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `sequence_expression` nodes. */class SequenceExpression extends @php_sequence_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "SequenceExpression" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_sequence_expression_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_sequence_expression_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `shell_command_expression` nodes. */class ShellCommandExpression extends @php_shell_command_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ShellCommandExpression" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_shell_command_expression_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_shell_command_expression_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `simple_parameter` nodes. */class SimpleParameter extends @php_simple_parameter, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "SimpleParameter" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_simple_parameter_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `default_value`. */final Expression getDefaultValue() { php_simple_parameter_default_value(this, result) }
|
||||
/** Gets the node corresponding to the field `name`. */final VariableName getName() { php_simple_parameter_def(this, result) }
|
||||
/** Gets the node corresponding to the field `reference_modifier`. */final ReferenceModifier getReferenceModifier() { php_simple_parameter_reference_modifier(this, result) }
|
||||
/** Gets the node corresponding to the field `type`. */final Type getType() { php_simple_parameter_type(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_simple_parameter_attributes(this, result)) or (php_simple_parameter_default_value(this, result)) or (php_simple_parameter_def(this, result)) or (php_simple_parameter_reference_modifier(this, result)) or (php_simple_parameter_type(this, result)) }
|
||||
}
|
||||
class Statement extends @php_statement, AstNode {
|
||||
}
|
||||
/** A class representing `static_modifier` tokens. */class StaticModifier extends @php_token_static_modifier, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "StaticModifier" }
|
||||
}
|
||||
/** A class representing `static_variable_declaration` nodes. */class StaticVariableDeclaration extends @php_static_variable_declaration, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "StaticVariableDeclaration" }
|
||||
/** Gets the node corresponding to the field `name`. */final VariableName getName() { php_static_variable_declaration_def(this, result) }
|
||||
/** Gets the node corresponding to the field `value`. */final Expression getValue() { php_static_variable_declaration_value(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_static_variable_declaration_def(this, result)) or (php_static_variable_declaration_value(this, result)) }
|
||||
}
|
||||
/** A class representing `string` nodes. */class String extends @php_string__, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "String" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_string_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_string_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `string_content` tokens. */class StringContent extends @php_token_string_content, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "StringContent" }
|
||||
}
|
||||
/** A class representing `subscript_expression` nodes. */class SubscriptExpression extends @php_subscript_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "SubscriptExpression" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_subscript_expression_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_subscript_expression_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `switch_block` nodes. */class SwitchBlock extends @php_switch_block, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "SwitchBlock" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_switch_block_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_switch_block_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `switch_statement` nodes. */class SwitchStatement extends @php_switch_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "SwitchStatement" }
|
||||
/** Gets the node corresponding to the field `body`. */final SwitchBlock getBody() { php_switch_statement_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `condition`. */final ParenthesizedExpression getCondition() { php_switch_statement_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_switch_statement_def(this, result, _)) or (php_switch_statement_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `text` tokens. */class Text extends @php_token_text, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "Text" }
|
||||
}
|
||||
/** A class representing `text_interpolation` nodes. */class TextInterpolation extends @php_text_interpolation, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "TextInterpolation" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_text_interpolation_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_text_interpolation_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `throw_expression` nodes. */class ThrowExpression extends @php_throw_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "ThrowExpression" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_throw_expression_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_throw_expression_def(this, result)) }
|
||||
}
|
||||
/** A class representing `trait_declaration` nodes. */class TraitDeclaration extends @php_trait_declaration, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "TraitDeclaration" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_trait_declaration_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `body`. */final DeclarationList getBody() { php_trait_declaration_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `name`. */final Name getName() { php_trait_declaration_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_trait_declaration_attributes(this, result)) or (php_trait_declaration_def(this, result, _)) or (php_trait_declaration_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `try_statement` nodes. */class TryStatement extends @php_try_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "TryStatement" }
|
||||
/** Gets the node corresponding to the field `body`. */final CompoundStatement getBody() { php_try_statement_def(this, result) }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_try_statement_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_try_statement_def(this, result)) or (php_try_statement_child(this, _, result)) }
|
||||
}
|
||||
class Type extends @php_type__, AstNode {
|
||||
}
|
||||
/** A class representing `type_list` nodes. */class TypeList extends @php_type_list, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "TypeList" }
|
||||
/** Gets the `i`th child of this node. */final NamedType getChild(int i) { php_type_list_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_type_list_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `unary_op_expression` nodes. */class UnaryOpExpression extends @php_unary_op_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "UnaryOpExpression" }
|
||||
/** Gets the node corresponding to the field `argument`. */final Expression getArgument() { php_unary_op_expression_argument(this, result) }
|
||||
/** Gets the node corresponding to the field `operator`. */final AstNode getOperator() { php_unary_op_expression_operator(this, result) }
|
||||
/** Gets the child of this node. */final Integer getChild() { php_unary_op_expression_child(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_unary_op_expression_argument(this, result)) or (php_unary_op_expression_operator(this, result)) or (php_unary_op_expression_child(this, result)) }
|
||||
}
|
||||
/** A class representing `union_type` nodes. */class UnionType extends @php_union_type, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "UnionType" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_union_type_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_union_type_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `unset_statement` nodes. */class UnsetStatement extends @php_unset_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "UnsetStatement" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_unset_statement_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_unset_statement_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `update_expression` nodes. */class UpdateExpression extends @php_update_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "UpdateExpression" }
|
||||
/** Gets the node corresponding to the field `argument`. */final AstNode getArgument() { php_update_expression_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `operator`. */final string getOperator() { exists(int value | php_update_expression_def(this, _, value) | ((result = "++") and (value = 0)) or ((result = "--") and (value = 1))) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_update_expression_def(this, result, _)) }
|
||||
}
|
||||
/** A class representing `use_as_clause` nodes. */class UseAsClause extends @php_use_as_clause, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "UseAsClause" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_use_as_clause_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_use_as_clause_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `use_declaration` nodes. */class UseDeclaration extends @php_use_declaration, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "UseDeclaration" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_use_declaration_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_use_declaration_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `use_instead_of_clause` nodes. */class UseInsteadOfClause extends @php_use_instead_of_clause, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "UseInsteadOfClause" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_use_instead_of_clause_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_use_instead_of_clause_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `use_list` nodes. */class UseList extends @php_use_list, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "UseList" }
|
||||
/** Gets the `i`th child of this node. */final AstNode getChild(int i) { php_use_list_child(this, i, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_use_list_child(this, _, result)) }
|
||||
}
|
||||
/** A class representing `var_modifier` tokens. */class VarModifier extends @php_token_var_modifier, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "VarModifier" }
|
||||
}
|
||||
/** A class representing `variable_name` nodes. */class VariableName extends @php_variable_name, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "VariableName" }
|
||||
/** Gets the child of this node. */final Name getChild() { php_variable_name_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_variable_name_def(this, result)) }
|
||||
}
|
||||
/** A class representing `variadic_parameter` nodes. */class VariadicParameter extends @php_variadic_parameter, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "VariadicParameter" }
|
||||
/** Gets the node corresponding to the field `attributes`. */final AttributeList getAttributes() { php_variadic_parameter_attributes(this, result) }
|
||||
/** Gets the node corresponding to the field `name`. */final VariableName getName() { php_variadic_parameter_def(this, result) }
|
||||
/** Gets the node corresponding to the field `reference_modifier`. */final ReferenceModifier getReferenceModifier() { php_variadic_parameter_reference_modifier(this, result) }
|
||||
/** Gets the node corresponding to the field `type`. */final Type getType() { php_variadic_parameter_type(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_variadic_parameter_attributes(this, result)) or (php_variadic_parameter_def(this, result)) or (php_variadic_parameter_reference_modifier(this, result)) or (php_variadic_parameter_type(this, result)) }
|
||||
}
|
||||
/** A class representing `variadic_placeholder` tokens. */class VariadicPlaceholder extends @php_token_variadic_placeholder, Token {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "VariadicPlaceholder" }
|
||||
}
|
||||
/** A class representing `variadic_unpacking` nodes. */class VariadicUnpacking extends @php_variadic_unpacking, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "VariadicUnpacking" }
|
||||
/** Gets the child of this node. */final Expression getChild() { php_variadic_unpacking_def(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_variadic_unpacking_def(this, result)) }
|
||||
}
|
||||
/** A class representing `visibility_modifier` nodes. */class VisibilityModifier extends @php_visibility_modifier, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "VisibilityModifier" }
|
||||
/** Gets the child of this node. */final Operation getChild() { php_visibility_modifier_child(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_visibility_modifier_child(this, result)) }
|
||||
}
|
||||
/** A class representing `while_statement` nodes. */class WhileStatement extends @php_while_statement, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "WhileStatement" }
|
||||
/** Gets the node corresponding to the field `body`. */final AstNode getBody() { php_while_statement_def(this, result, _) }
|
||||
/** Gets the node corresponding to the field `condition`. */final ParenthesizedExpression getCondition() { php_while_statement_def(this, _, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_while_statement_def(this, result, _)) or (php_while_statement_def(this, _, result)) }
|
||||
}
|
||||
/** A class representing `yield_expression` nodes. */class YieldExpression extends @php_yield_expression, AstNode {
|
||||
/** Gets the name of the primary QL class for this element. */final override string getAPrimaryQlClass() { result = "YieldExpression" }
|
||||
/** Gets the child of this node. */final AstNode getChild() { php_yield_expression_child(this, result) }
|
||||
/** Gets a field or child node of this node. */final override AstNode getAFieldOrChild() { (php_yield_expression_child(this, result)) }
|
||||
}
|
||||
}
|
||||
|
||||
101
php/ql/lib/codeql/php/controlflow/BasicBlocks.qll
Normal file
101
php/ql/lib/codeql/php/controlflow/BasicBlocks.qll
Normal file
@@ -0,0 +1,101 @@
|
||||
/** Provides classes representing basic blocks. */
|
||||
|
||||
private import codeql.php.AST
|
||||
private import codeql.php.controlflow.ControlFlowGraph
|
||||
private import internal.ControlFlowGraphImpl as CfgImpl
|
||||
private import CfgImpl::BasicBlocks as BasicBlocksImpl
|
||||
private import codeql.controlflow.BasicBlock as BB
|
||||
private import codeql.controlflow.SuccessorType
|
||||
|
||||
/**
|
||||
* A basic block, that is, a maximal straight-line sequence of control flow nodes
|
||||
* without branches or joins.
|
||||
*/
|
||||
final class BasicBlock extends BasicBlocksImpl::BasicBlock {
|
||||
/** Gets an immediate successor of this basic block, if any. */
|
||||
BasicBlock getASuccessor() { result = super.getASuccessor() }
|
||||
|
||||
/** Gets an immediate successor of this basic block of a given type, if any. */
|
||||
BasicBlock getASuccessor(SuccessorType t) { result = super.getASuccessor(t) }
|
||||
|
||||
/** Gets an immediate predecessor of this basic block, if any. */
|
||||
BasicBlock getAPredecessor() { result = super.getAPredecessor() }
|
||||
|
||||
/** Gets an immediate predecessor of this basic block of a given type, if any. */
|
||||
BasicBlock getAPredecessor(SuccessorType t) { result = super.getAPredecessor(t) }
|
||||
|
||||
/** Gets the control flow node at position `pos` in this basic block. */
|
||||
CfgNode getNode(int pos) { result = super.getNode(pos) }
|
||||
|
||||
/** Gets a control flow node in this basic block. */
|
||||
CfgNode getANode() { result = super.getANode() }
|
||||
|
||||
/** Gets the first control flow node in this basic block. */
|
||||
CfgNode getFirstNode() { result = super.getFirstNode() }
|
||||
|
||||
/** Gets the last control flow node in this basic block. */
|
||||
CfgNode getLastNode() { result = super.getLastNode() }
|
||||
|
||||
/** Holds if this basic block immediately dominates basic block `bb`. */
|
||||
predicate immediatelyDominates(BasicBlock bb) { super.immediatelyDominates(bb) }
|
||||
|
||||
/** Holds if this basic block strictly dominates basic block `bb`. */
|
||||
predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) }
|
||||
|
||||
/** Holds if this basic block dominates basic block `bb`. */
|
||||
predicate dominates(BasicBlock bb) { super.dominates(bb) }
|
||||
|
||||
/**
|
||||
* Holds if `df` is in the dominance frontier of this basic block.
|
||||
*/
|
||||
predicate inDominanceFrontier(BasicBlock df) { super.inDominanceFrontier(df) }
|
||||
|
||||
/** Gets the basic block that immediately dominates this basic block, if any. */
|
||||
BasicBlock getImmediateDominator() { result = super.getImmediateDominator() }
|
||||
|
||||
/** Holds if this basic block strictly post-dominates basic block `bb`. */
|
||||
predicate strictlyPostDominates(BasicBlock bb) { super.strictlyPostDominates(bb) }
|
||||
|
||||
/** Holds if this basic block post-dominates basic block `bb`. */
|
||||
predicate postDominates(BasicBlock bb) { super.postDominates(bb) }
|
||||
}
|
||||
|
||||
/** An entry basic block. */
|
||||
final class EntryBasicBlock extends BasicBlock, BasicBlocksImpl::EntryBasicBlock { }
|
||||
|
||||
/** An annotated exit basic block. */
|
||||
final class AnnotatedExitBasicBlock extends BasicBlock, BasicBlocksImpl::AnnotatedExitBasicBlock { }
|
||||
|
||||
/** An exit basic block. */
|
||||
final class ExitBasicBlock extends BasicBlock, BasicBlocksImpl::ExitBasicBlock { }
|
||||
|
||||
/** A basic block with more than one predecessor. */
|
||||
final class JoinBlock extends BasicBlock, BasicBlocksImpl::JoinBasicBlock {
|
||||
JoinBlockPredecessor getJoinBlockPredecessor(int i) { result = super.getJoinBlockPredecessor(i) }
|
||||
}
|
||||
|
||||
/** A basic block that is an immediate predecessor of a join block. */
|
||||
final class JoinBlockPredecessor extends BasicBlock, BasicBlocksImpl::JoinPredecessorBasicBlock { }
|
||||
|
||||
/**
|
||||
* A basic block that terminates in a condition, splitting the subsequent
|
||||
* control flow.
|
||||
*/
|
||||
final class ConditionBlock extends BasicBlock, BasicBlocksImpl::ConditionBasicBlock { }
|
||||
|
||||
private class BasicBlockAlias = BasicBlock;
|
||||
|
||||
private class EntryBasicBlockAlias = EntryBasicBlock;
|
||||
|
||||
/** Implements the `CfgSig` module for use by the SSA library. */
|
||||
module Cfg implements BB::CfgSig<Location> {
|
||||
class ControlFlowNode = CfgNode;
|
||||
|
||||
class BasicBlock = BasicBlockAlias;
|
||||
|
||||
class EntryBasicBlock = EntryBasicBlockAlias;
|
||||
|
||||
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) {
|
||||
BasicBlocksImpl::dominatingEdge(bb1, bb2)
|
||||
}
|
||||
}
|
||||
45
php/ql/lib/codeql/php/controlflow/ControlFlowGraph.qll
Normal file
45
php/ql/lib/codeql/php/controlflow/ControlFlowGraph.qll
Normal file
@@ -0,0 +1,45 @@
|
||||
/** Provides classes representing the control flow graph. */
|
||||
|
||||
import codeql.controlflow.SuccessorType
|
||||
private import codeql.php.AST
|
||||
private import codeql.php.controlflow.BasicBlocks
|
||||
private import internal.ControlFlowGraphImpl as CfgImpl
|
||||
private import internal.Completion
|
||||
|
||||
/**
|
||||
* An AST node with an associated control-flow graph.
|
||||
*
|
||||
* Functions, methods, closures, arrow functions, and programs are CFG scopes.
|
||||
*/
|
||||
class CfgScope extends AstNode instanceof CfgImpl::CfgScopeImpl { }
|
||||
|
||||
/**
|
||||
* A control flow node.
|
||||
*
|
||||
* A control flow node is a node in the control flow graph (CFG). There is a
|
||||
* many-to-one relationship between CFG nodes and AST nodes.
|
||||
*
|
||||
* Only nodes that can be reached from an entry point are included in the CFG.
|
||||
*/
|
||||
class CfgNode extends CfgImpl::Node {
|
||||
/** Gets a successor node of a given type, if any. */
|
||||
final CfgNode getASuccessor(SuccessorType t) { result = super.getASuccessor(t) }
|
||||
|
||||
/** Gets an immediate successor, if any. */
|
||||
final CfgNode getASuccessor() { result = this.getASuccessor(_) }
|
||||
|
||||
/** Gets an immediate predecessor node of a given flow type, if any. */
|
||||
final CfgNode getAPredecessor(SuccessorType t) { result.getASuccessor(t) = this }
|
||||
|
||||
/** Gets an immediate predecessor, if any. */
|
||||
final CfgNode getAPredecessor() { result = this.getAPredecessor(_) }
|
||||
|
||||
/** Gets the basic block that this control flow node belongs to. */
|
||||
BasicBlock getBasicBlock() { result.getANode() = this }
|
||||
|
||||
/** Gets the AST node associated with this CFG node. */
|
||||
AstNode getAstNode() { result = super.getAstNode() }
|
||||
|
||||
/** Gets the CFG scope that this node belongs to. */
|
||||
CfgScope getScope() { result = super.getScope() }
|
||||
}
|
||||
170
php/ql/lib/codeql/php/controlflow/internal/Completion.qll
Normal file
170
php/ql/lib/codeql/php/controlflow/internal/Completion.qll
Normal file
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* Provides classes representing control flow completions.
|
||||
*
|
||||
* A completion represents how a statement or expression terminates.
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import codeql.php.controlflow.ControlFlowGraph
|
||||
private import ControlFlowGraphImpl as CfgImpl
|
||||
|
||||
private newtype TCompletion =
|
||||
TSimpleCompletion() or
|
||||
TBooleanCompletion(boolean b) { b in [false, true] } or
|
||||
TReturnCompletion() or
|
||||
TBreakCompletion() or
|
||||
TContinueCompletion() or
|
||||
TThrowCompletion() or
|
||||
TExitCompletion()
|
||||
|
||||
/**
|
||||
* Holds if `c` is a valid completion for node `n` based on its statement type.
|
||||
*/
|
||||
private predicate completionIsValidForStmt(AstNode n, Completion c) {
|
||||
n instanceof BreakStmt and c = TBreakCompletion()
|
||||
or
|
||||
n instanceof ContinueStmt and c = TContinueCompletion()
|
||||
or
|
||||
n instanceof ReturnStmt and c = TReturnCompletion()
|
||||
or
|
||||
n instanceof ThrowExpr and c = TThrowCompletion()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` is used in a Boolean context. That is, the value
|
||||
* that `n` evaluates to determines a true/false branch successor.
|
||||
*/
|
||||
private predicate inBooleanContext(AstNode n) {
|
||||
// Condition of if/elseif
|
||||
exists(IfStmt ifStmt | n = ifStmt.getCondition())
|
||||
or
|
||||
exists(ElseIfClause clause | n = clause.getCondition())
|
||||
or
|
||||
// Condition of while
|
||||
exists(WhileStmt whileStmt | n = whileStmt.getCondition())
|
||||
or
|
||||
// Condition of do-while
|
||||
exists(DoWhileStmt doWhile | n = doWhile.getCondition())
|
||||
or
|
||||
// Condition of for
|
||||
exists(ForStmt forStmt | n = forStmt.getCondition())
|
||||
or
|
||||
// Condition of ternary
|
||||
exists(ConditionalExpr cond | n = cond.getCondition())
|
||||
or
|
||||
// Logical operators: left operand is always in boolean context
|
||||
exists(BinaryExpr bin |
|
||||
bin.getOperator() = ["&&", "||", "and", "or"] and
|
||||
n = bin.getLeftOperand()
|
||||
)
|
||||
or
|
||||
// Negation operand
|
||||
exists(UnaryExpr unary |
|
||||
unary.getOperator() = "!" and
|
||||
n = unary.getOperand()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a normal completion of `n` must be a Boolean completion.
|
||||
*/
|
||||
private predicate mustHaveBooleanCompletion(AstNode n) { inBooleanContext(n) }
|
||||
|
||||
/** A completion of a statement or an expression. */
|
||||
abstract class Completion extends TCompletion {
|
||||
private predicate isValidForSpecific(AstNode n) {
|
||||
completionIsValidForStmt(n, this)
|
||||
or
|
||||
mustHaveBooleanCompletion(n) and
|
||||
this = TBooleanCompletion(_)
|
||||
}
|
||||
|
||||
/** Holds if this completion is valid for node `n`. */
|
||||
predicate isValidFor(AstNode n) {
|
||||
this.isValidForSpecific(n)
|
||||
or
|
||||
not any(Completion c).isValidForSpecific(n) and
|
||||
this = TSimpleCompletion()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this completion will continue a loop when it is the completion
|
||||
* of a loop body.
|
||||
*/
|
||||
predicate continuesLoop() {
|
||||
this instanceof NormalCompletion or
|
||||
this instanceof ContinueCompletion
|
||||
}
|
||||
|
||||
/** Gets a successor type that matches this completion. */
|
||||
abstract SuccessorType getAMatchingSuccessorType();
|
||||
|
||||
/** Gets a textual representation of this completion. */
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/** A completion that represents normal evaluation. */
|
||||
abstract class NormalCompletion extends Completion { }
|
||||
|
||||
/** A simple (normal) completion. */
|
||||
class SimpleCompletion extends NormalCompletion, TSimpleCompletion {
|
||||
override SuccessorType getAMatchingSuccessorType() { result instanceof DirectSuccessor }
|
||||
|
||||
override string toString() { result = "simple" }
|
||||
}
|
||||
|
||||
/** A Boolean completion. */
|
||||
class BooleanCompletion extends NormalCompletion, TBooleanCompletion {
|
||||
boolean value;
|
||||
|
||||
BooleanCompletion() { this = TBooleanCompletion(value) }
|
||||
|
||||
/** Gets the Boolean value of this completion. */
|
||||
boolean getValue() { result = value }
|
||||
|
||||
override SuccessorType getAMatchingSuccessorType() {
|
||||
result.(BooleanSuccessor).getValue() = value
|
||||
}
|
||||
|
||||
override string toString() { result = "boolean(" + value + ")" }
|
||||
}
|
||||
|
||||
/** A return completion. */
|
||||
class ReturnCompletion extends Completion, TReturnCompletion {
|
||||
override SuccessorType getAMatchingSuccessorType() { result instanceof ReturnSuccessor }
|
||||
|
||||
override string toString() { result = "return" }
|
||||
}
|
||||
|
||||
/** A break completion. */
|
||||
class BreakCompletion extends Completion, TBreakCompletion {
|
||||
override SuccessorType getAMatchingSuccessorType() { result instanceof BreakSuccessor }
|
||||
|
||||
override string toString() { result = "break" }
|
||||
}
|
||||
|
||||
/** A continue completion. */
|
||||
class ContinueCompletion extends Completion, TContinueCompletion {
|
||||
override SuccessorType getAMatchingSuccessorType() { result instanceof ContinueSuccessor }
|
||||
|
||||
override string toString() { result = "continue" }
|
||||
}
|
||||
|
||||
/** A throw completion (exception). */
|
||||
class ThrowCompletion extends Completion, TThrowCompletion {
|
||||
override SuccessorType getAMatchingSuccessorType() { result instanceof ExceptionSuccessor }
|
||||
|
||||
override string toString() { result = "throw" }
|
||||
}
|
||||
|
||||
/** An exit completion (die/exit). */
|
||||
class ExitCompletion extends Completion, TExitCompletion {
|
||||
override SuccessorType getAMatchingSuccessorType() { result instanceof ExitSuccessor }
|
||||
|
||||
override string toString() { result = "exit" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A conditional completion, used for splitting.
|
||||
*/
|
||||
class ConditionalCompletion extends BooleanCompletion { }
|
||||
1248
php/ql/lib/codeql/php/controlflow/internal/ControlFlowGraphImpl.qll
Normal file
1248
php/ql/lib/codeql/php/controlflow/internal/ControlFlowGraphImpl.qll
Normal file
File diff suppressed because it is too large
Load Diff
238
php/ql/lib/codeql/php/dataflow/internal/DataFlowDispatch.qll
Normal file
238
php/ql/lib/codeql/php/dataflow/internal/DataFlowDispatch.qll
Normal file
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* Provides PHP-specific data flow dispatch logic.
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import DataFlowPrivate
|
||||
|
||||
newtype TReturnKind = TNormalReturnKind()
|
||||
|
||||
/**
|
||||
* A return kind. A return kind describes how a value can be returned
|
||||
* from a callable.
|
||||
*/
|
||||
abstract class ReturnKind extends TReturnKind {
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/** A normal return (via `return` statement or expression body). */
|
||||
class NormalReturnKind extends ReturnKind, TNormalReturnKind {
|
||||
override string toString() { result = "return" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that can read the value returned from `call` with return kind `kind`.
|
||||
*/
|
||||
OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { call = result.getCall(kind) }
|
||||
|
||||
newtype TDataFlowCallable =
|
||||
TCallable(Callable c) or
|
||||
TProgram(Program p)
|
||||
|
||||
/** A callable (function, method, closure, arrow function, or file-level program). */
|
||||
class DataFlowCallable extends TDataFlowCallable {
|
||||
Callable asCallable() { this = TCallable(result) }
|
||||
|
||||
Program asProgram() { this = TProgram(result) }
|
||||
|
||||
string toString() {
|
||||
result = this.asCallable().toString()
|
||||
or
|
||||
result = this.asProgram().toString()
|
||||
}
|
||||
|
||||
Location getLocation() {
|
||||
result = this.asCallable().getLocation()
|
||||
or
|
||||
result = this.asProgram().getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
newtype TDataFlowCall = TNormalCall(Call call)
|
||||
|
||||
/** A data flow call. */
|
||||
class DataFlowCall extends TDataFlowCall {
|
||||
Call call;
|
||||
|
||||
DataFlowCall() { this = TNormalCall(call) }
|
||||
|
||||
Call asCall() { result = call }
|
||||
|
||||
DataFlowCallable getEnclosingCallable() {
|
||||
result.asCallable() = call.getParent*().(Callable)
|
||||
or
|
||||
not call.getParent*() instanceof Callable and
|
||||
result.asProgram() = call.getParent*().(Program)
|
||||
}
|
||||
|
||||
string toString() { result = call.toString() }
|
||||
|
||||
Location getLocation() { result = call.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a viable callable for the call `c`.
|
||||
*
|
||||
* Resolves function calls by name, method calls by class hierarchy analysis,
|
||||
* and static calls by class scope.
|
||||
*/
|
||||
DataFlowCallable viableCallable(DataFlowCall c) {
|
||||
// Function call: resolve by name
|
||||
exists(FunctionCallExpr fce, FunctionDef fd |
|
||||
fce = c.asCall() and
|
||||
fd.getNameString() = fce.getFunctionName() and
|
||||
result = TCallable(fd)
|
||||
)
|
||||
or
|
||||
// Method call ($obj->method(...)): resolve by method name across all classes
|
||||
exists(MethodCallExpr mce, MethodDecl md |
|
||||
mce = c.asCall() and
|
||||
md.getNameString() = mce.getMethodNameString() and
|
||||
// If we can determine the class of the receiver, restrict to that class hierarchy
|
||||
(
|
||||
// $this->method(): resolve to methods in the enclosing class and its parents
|
||||
mce.getObject().(VariableName).getValue() = "$this" and
|
||||
exists(ClassDecl cd |
|
||||
mce.getParent*() = cd and
|
||||
md = getMethodInClassHierarchy(cd, mce.getMethodNameString())
|
||||
)
|
||||
or
|
||||
// For other receivers, conservatively resolve by method name
|
||||
not mce.getObject().(VariableName).getValue() = "$this" and
|
||||
md.getNameString() = mce.getMethodNameString()
|
||||
) and
|
||||
result = TCallable(md)
|
||||
)
|
||||
or
|
||||
// Nullsafe method call ($obj?->method(...)): same as method call
|
||||
exists(NullsafeMethodCallExpr mce, MethodDecl md |
|
||||
mce = c.asCall() and
|
||||
md.getNameString() = mce.getMethodNameString() and
|
||||
result = TCallable(md)
|
||||
)
|
||||
or
|
||||
// Scoped (static) call (ClassName::method(...)): resolve by scope and name
|
||||
exists(ScopedCallExpr sce, MethodDecl md |
|
||||
sce = c.asCall() and
|
||||
md.getNameString() = sce.getMethodNameString() and
|
||||
(
|
||||
// Direct class name resolution
|
||||
exists(ClassDecl cd |
|
||||
resolveClassName(sce.getScope()) = cd.getNameString() and
|
||||
md = getMethodInClassHierarchy(cd, sce.getMethodNameString())
|
||||
)
|
||||
or
|
||||
// self/static/parent - resolve from enclosing class
|
||||
exists(ClassDecl enclosing, string scopeName |
|
||||
sce.getParent*() = enclosing and
|
||||
scopeName = resolveScopeName(sce.getScope()) and
|
||||
(
|
||||
scopeName = ["self", "static"] and
|
||||
md = getMethodInClassHierarchy(enclosing, sce.getMethodNameString())
|
||||
or
|
||||
scopeName = "parent" and
|
||||
exists(ClassDecl parent |
|
||||
getBaseClassName(enclosing) = parent.getNameString() and
|
||||
md = getMethodInClassHierarchy(parent, sce.getMethodNameString())
|
||||
)
|
||||
)
|
||||
)
|
||||
or
|
||||
// Fallback: just match by method name
|
||||
not exists(resolveClassName(sce.getScope())) and
|
||||
not exists(resolveScopeName(sce.getScope())) and
|
||||
md.getNameString() = sce.getMethodNameString()
|
||||
) and
|
||||
result = TCallable(md)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string class name from a scope expression, if it is a simple name.
|
||||
*/
|
||||
private string resolveClassName(AstNode scope) {
|
||||
result = scope.(Name).getValue() and
|
||||
not result = ["self", "static", "parent"]
|
||||
or
|
||||
result = scope.(QualifiedName).getValue() and
|
||||
not result = ["self", "static", "parent"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a special scope keyword (self/static/parent) from a scope expression.
|
||||
*/
|
||||
private string resolveScopeName(AstNode scope) {
|
||||
result = scope.(Name).getValue() and
|
||||
result = ["self", "static", "parent"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base class name for `cd` (the class it extends).
|
||||
*/
|
||||
private string getBaseClassName(ClassDecl cd) {
|
||||
exists(BaseClause bc |
|
||||
bc = cd.getBaseClause() and
|
||||
result = bc.getChild(0).(Name).getValue()
|
||||
or
|
||||
bc = cd.getBaseClause() and
|
||||
result = bc.getChild(0).(QualifiedName).getValue()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a method named `methodName` that is declared in `cd` or one of its
|
||||
* ancestor classes.
|
||||
*/
|
||||
private MethodDecl getMethodInClassHierarchy(ClassDecl cd, string methodName) {
|
||||
// Direct declaration
|
||||
exists(DeclarationList body |
|
||||
body = cd.getBody() and
|
||||
result = body.getAMember() and
|
||||
result.getNameString() = methodName
|
||||
)
|
||||
or
|
||||
// Inherited from parent
|
||||
exists(ClassDecl parent |
|
||||
getBaseClassName(cd) = parent.getNameString() and
|
||||
result = getMethodInClassHierarchy(parent, methodName) and
|
||||
// Only inherit if not overridden in cd
|
||||
not exists(MethodDecl override |
|
||||
override = cd.getBody().getAMember() and
|
||||
override.getNameString() = methodName
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate mayBenefitFromCallContext(DataFlowCall call) { none() }
|
||||
|
||||
DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { none() }
|
||||
|
||||
newtype TParameterPosition = TPositionalParameterPosition(int i) { i in [0 .. 20] }
|
||||
|
||||
/** A parameter position. */
|
||||
class ParameterPosition extends TParameterPosition {
|
||||
int pos;
|
||||
|
||||
ParameterPosition() { this = TPositionalParameterPosition(pos) }
|
||||
|
||||
int asPositional() { result = pos }
|
||||
|
||||
string toString() { result = pos.toString() }
|
||||
}
|
||||
|
||||
newtype TArgumentPosition = TPositionalArgumentPosition(int i) { i in [0 .. 20] }
|
||||
|
||||
/** An argument position. */
|
||||
class ArgumentPosition extends TArgumentPosition {
|
||||
int pos;
|
||||
|
||||
ArgumentPosition() { this = TPositionalArgumentPosition(pos) }
|
||||
|
||||
int asPositional() { result = pos }
|
||||
|
||||
string toString() { result = pos.toString() }
|
||||
}
|
||||
|
||||
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
|
||||
ppos.asPositional() = apos.asPositional()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Provides PHP-specific definitions for use in the data flow library.
|
||||
*/
|
||||
|
||||
private import codeql.Locations
|
||||
private import codeql.dataflow.DataFlow
|
||||
|
||||
module Private {
|
||||
import DataFlowPrivate
|
||||
import DataFlowDispatch
|
||||
}
|
||||
|
||||
module Public {
|
||||
import DataFlowPublic
|
||||
}
|
||||
|
||||
module PhpDataFlow implements InputSig<Location> {
|
||||
import Private
|
||||
import Public
|
||||
|
||||
Node exprNode(DataFlowExpr e) { result = Public::exprNode(e) }
|
||||
|
||||
predicate neverSkipInPathGraph = Private::neverSkipInPathGraph/1;
|
||||
|
||||
predicate mayBenefitFromCallContext = Private::mayBenefitFromCallContext/1;
|
||||
|
||||
predicate viableImplInCallContext = Private::viableImplInCallContext/2;
|
||||
}
|
||||
294
php/ql/lib/codeql/php/dataflow/internal/DataFlowPrivate.qll
Normal file
294
php/ql/lib/codeql/php/dataflow/internal/DataFlowPrivate.qll
Normal file
@@ -0,0 +1,294 @@
|
||||
/**
|
||||
* Provides PHP-specific data flow implementation details.
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import DataFlowPublic
|
||||
private import DataFlowDispatch
|
||||
private import SsaImpl as Ssa
|
||||
private import codeql.php.controlflow.ControlFlowGraph as Cfg
|
||||
private import codeql.php.controlflow.BasicBlocks as BasicBlocks
|
||||
private import codeql.php.controlflow.internal.ControlFlowGraphImpl as CfgImpl
|
||||
|
||||
/** Gets the callable in which this node occurs. */
|
||||
DataFlowCallable nodeGetEnclosingCallable(Node n) {
|
||||
result = TCallable(n.asExpr().getParent*().(Callable))
|
||||
or
|
||||
result = TCallable(n.asParameter().getParent*().(Callable))
|
||||
or
|
||||
// File-level code: node is inside a Program but not inside any Callable
|
||||
not n.asExpr().getParent*() instanceof Callable and
|
||||
result = TProgram(n.asExpr().getParent*().(Program))
|
||||
or
|
||||
// SSA definition node: use the scope of the SSA variable
|
||||
exists(Ssa::Definition def, Ssa::SsaSourceVariable v |
|
||||
n = TSsaDefinitionNode(def) and
|
||||
def.definesAt(v, _, _)
|
||||
|
|
||||
result = TCallable(v.getScope().(Callable))
|
||||
or
|
||||
not v.getScope() instanceof Callable and
|
||||
result = TProgram(v.getScope().(Program))
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
|
||||
exists(Callable callable, int i |
|
||||
callable = c.asCallable() and
|
||||
callable.getParameter(i) = p.getParameter() and
|
||||
pos = TPositionalParameterPosition(i)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */
|
||||
predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) {
|
||||
exists(Call call, int i |
|
||||
call = c.asCall() and
|
||||
call.getArgument(i) = arg.asExpr() and
|
||||
pos = TPositionalArgumentPosition(i)
|
||||
)
|
||||
}
|
||||
|
||||
newtype TNode =
|
||||
TExprNode(Expr e) or
|
||||
TParameterNode(Parameter p) or
|
||||
TSsaDefinitionNode(Ssa::Definition def) or
|
||||
TPostUpdateNode(Expr e) { isPostUpdateExpr(e) }
|
||||
|
||||
private predicate isPostUpdateExpr(Expr e) {
|
||||
// Arguments of calls that may be modified
|
||||
exists(Call c | c.getAnArgument() = e)
|
||||
or
|
||||
// Receiver of method calls
|
||||
e = any(MethodCallExpr mc).getObject()
|
||||
or
|
||||
e = any(NullsafeMethodCallExpr mc).getObject()
|
||||
or
|
||||
e = any(MemberAccessExpr ma).getObject()
|
||||
}
|
||||
|
||||
/** The data flow type. */
|
||||
class DataFlowType extends string {
|
||||
DataFlowType() { this = "" }
|
||||
|
||||
string toString() { result = this }
|
||||
}
|
||||
|
||||
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { any() }
|
||||
|
||||
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
|
||||
|
||||
DataFlowType getNodeType(Node node) { exists(node) and result = "" }
|
||||
|
||||
predicate nodeIsHidden(Node node) { node instanceof SsaDefinitionNode }
|
||||
|
||||
/**
|
||||
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local step.
|
||||
*/
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo, string model) {
|
||||
model = "" and
|
||||
(
|
||||
// Assignment: value flows from RHS to LHS
|
||||
exists(AssignExpr assign |
|
||||
nodeFrom.asExpr() = assign.getRightOperand() and
|
||||
nodeTo.asExpr() = assign.getLeftOperand()
|
||||
)
|
||||
or
|
||||
// SSA flow: from a variable write to the SSA definition
|
||||
exists(Ssa::WriteDefinition def, BasicBlocks::BasicBlock bb, int i, VariableName vn |
|
||||
def.definesAt(_, bb, i) and
|
||||
bb.getNode(i).getAstNode() = vn and
|
||||
nodeFrom.asExpr() = vn and
|
||||
nodeTo = TSsaDefinitionNode(def) and
|
||||
exists(AssignExpr assign | assign.getLeftOperand() = vn)
|
||||
)
|
||||
or
|
||||
// SSA flow: from an SSA definition to each read of the same variable
|
||||
exists(Ssa::Definition def, BasicBlocks::BasicBlock bb, int i, VariableName vn |
|
||||
ssaDefReachesRead(def, bb, i) and
|
||||
bb.getNode(i).getAstNode() = vn and
|
||||
nodeFrom = TSsaDefinitionNode(def) and
|
||||
nodeTo.asExpr() = vn
|
||||
)
|
||||
or
|
||||
// SSA flow: phi node from input definitions
|
||||
exists(Ssa::PhiNode phi, Ssa::Definition input |
|
||||
input = Ssa::phiHasInputFromBlock(phi, _) and
|
||||
nodeFrom = TSsaDefinitionNode(input) and
|
||||
nodeTo = TSsaDefinitionNode(phi)
|
||||
)
|
||||
or
|
||||
// Parenthesized expression: value flows through
|
||||
exists(ParenExpr paren |
|
||||
nodeFrom.asExpr() = paren.getExpr() and
|
||||
nodeTo.asExpr() = paren
|
||||
)
|
||||
or
|
||||
// Conditional expression: value flows from branches
|
||||
exists(ConditionalExpr cond |
|
||||
(
|
||||
nodeFrom.asExpr() = cond.getConsequence() or
|
||||
nodeFrom.asExpr() = cond.getAlternative()
|
||||
) and
|
||||
nodeTo.asExpr() = cond
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if SSA definition `def` reaches a read at position `i` in basic block `bb`.
|
||||
*/
|
||||
private predicate ssaDefReachesRead(
|
||||
Ssa::Definition def, BasicBlocks::BasicBlock bb, int i
|
||||
) {
|
||||
exists(Ssa::SsaSourceVariable v |
|
||||
def.definesAt(v, _, _) and
|
||||
Ssa::SsaInput::variableRead(bb, i, v, _) and
|
||||
Ssa::getARead(def) = bb.getNode(i)
|
||||
)
|
||||
}
|
||||
|
||||
/** A type of data-flow content. */
|
||||
newtype TContent =
|
||||
TArrayElementContent() or
|
||||
TPropertyContent(string name) { exists(MemberAccessExpr ma | ma.getName().getValue() = name) }
|
||||
|
||||
/** Data flow content (field, array element, etc.). */
|
||||
class Content extends TContent {
|
||||
string toString() {
|
||||
this = TArrayElementContent() and result = "ArrayElement"
|
||||
or
|
||||
exists(string name | this = TPropertyContent(name) and result = "Property[" + name + "]")
|
||||
}
|
||||
}
|
||||
|
||||
class ContentApprox extends TContent {
|
||||
string toString() { result = this.(Content).toString() }
|
||||
}
|
||||
|
||||
ContentApprox getContentApprox(Content c) { result = c }
|
||||
|
||||
predicate forceHighPrecision(Content c) { none() }
|
||||
|
||||
predicate readStep(Node node1, ContentSet c, Node node2) {
|
||||
// Property read: $obj->prop
|
||||
exists(MemberAccessExpr ma |
|
||||
node1.asExpr() = ma.getObject() and
|
||||
node2.asExpr() = ma and
|
||||
c = TPropertyContent(ma.getName().getValue())
|
||||
)
|
||||
or
|
||||
// Array read: $arr[idx]
|
||||
exists(SubscriptExpr sub |
|
||||
node1.asExpr() = sub.getObject() and
|
||||
node2.asExpr() = sub and
|
||||
c = TArrayElementContent()
|
||||
)
|
||||
}
|
||||
|
||||
predicate storeStep(Node node1, ContentSet c, Node node2) {
|
||||
// Property write: $obj->prop = value
|
||||
exists(AssignExpr assign, MemberAccessExpr ma |
|
||||
ma = assign.getLeftOperand() and
|
||||
node1.asExpr() = assign.getRightOperand() and
|
||||
node2 = TPostUpdateNode(ma.getObject()) and
|
||||
c = TPropertyContent(ma.getName().getValue())
|
||||
)
|
||||
or
|
||||
// Array write: $arr[idx] = value
|
||||
exists(AssignExpr assign, SubscriptExpr sub |
|
||||
sub = assign.getLeftOperand() and
|
||||
node1.asExpr() = assign.getRightOperand() and
|
||||
node2 = TPostUpdateNode(sub.getObject()) and
|
||||
c = TArrayElementContent()
|
||||
)
|
||||
}
|
||||
|
||||
predicate clearsContent(Node n, ContentSet c) { none() }
|
||||
|
||||
predicate expectsContent(Node n, ContentSet c) { none() }
|
||||
|
||||
predicate jumpStep(Node node1, Node node2) { none() }
|
||||
|
||||
class NodeRegion instanceof string {
|
||||
NodeRegion() { this = "NodeRegion" }
|
||||
|
||||
predicate contains(Node n) { none() }
|
||||
|
||||
string toString() { result = this }
|
||||
}
|
||||
|
||||
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { none() }
|
||||
|
||||
predicate allowParameterReturnInSelf(ParameterNode p) { none() }
|
||||
|
||||
predicate localMustFlowStep(Node node1, Node node2) {
|
||||
exists(AssignExpr assign |
|
||||
node1.asExpr() = assign.getRightOperand() and
|
||||
node2.asExpr() = assign.getLeftOperand()
|
||||
)
|
||||
}
|
||||
|
||||
class LambdaCallKind extends string {
|
||||
LambdaCallKind() { this = "closure" }
|
||||
}
|
||||
|
||||
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) { none() }
|
||||
|
||||
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { none() }
|
||||
|
||||
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
|
||||
|
||||
predicate knownSourceModel(Node source, string model) { none() }
|
||||
|
||||
predicate knownSinkModel(Node sink, string model) { none() }
|
||||
|
||||
predicate neverSkipInPathGraph(Node n) { none() }
|
||||
|
||||
class DataFlowSecondLevelScope extends string {
|
||||
DataFlowSecondLevelScope() { this = "" }
|
||||
|
||||
string toString() { result = this }
|
||||
}
|
||||
|
||||
/** The type of data flow expressions. */
|
||||
class DataFlowExpr = Expr;
|
||||
|
||||
/** An argument node. */
|
||||
class ArgumentNode extends ExprNode {
|
||||
private Call call;
|
||||
|
||||
ArgumentNode() { call.getAnArgument() = this.asExpr() }
|
||||
|
||||
predicate argumentOf(DataFlowCall c, ArgumentPosition pos) {
|
||||
exists(int i |
|
||||
call = c.asCall() and
|
||||
call.getArgument(i) = this.getExpr() and
|
||||
pos = TPositionalArgumentPosition(i)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A return node. */
|
||||
class ReturnNode extends ExprNode {
|
||||
ReturnStmt ret;
|
||||
|
||||
ReturnNode() { this.getExpr() = ret.getValue() }
|
||||
|
||||
ReturnKind getKind() { result instanceof NormalReturnKind }
|
||||
}
|
||||
|
||||
/** An out node (at a call site, reading return values). */
|
||||
class OutNode extends ExprNode {
|
||||
OutNode() { this.getExpr() instanceof Call }
|
||||
|
||||
DataFlowCall getCall(ReturnKind kind) {
|
||||
result.asCall() = this.getExpr() and
|
||||
kind instanceof NormalReturnKind
|
||||
}
|
||||
}
|
||||
|
||||
class CastNode extends Node {
|
||||
CastNode() { this.asExpr() instanceof CastExpr }
|
||||
}
|
||||
149
php/ql/lib/codeql/php/dataflow/internal/DataFlowPublic.qll
Normal file
149
php/ql/lib/codeql/php/dataflow/internal/DataFlowPublic.qll
Normal file
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* Provides PHP-specific data flow public API.
|
||||
*/
|
||||
|
||||
private import codeql.php.AST
|
||||
private import DataFlowPrivate
|
||||
private import SsaImpl as Ssa
|
||||
|
||||
/**
|
||||
* An element, viewed as a node in a data flow graph. Either an expression
|
||||
* (`ExprNode`) or a parameter (`ParameterNode`).
|
||||
*/
|
||||
class Node extends TNode {
|
||||
/** Gets the expression corresponding to this node, if any. */
|
||||
Expr asExpr() { this = TExprNode(result) }
|
||||
|
||||
/** Gets the parameter corresponding to this node, if any. */
|
||||
Parameter asParameter() { this = TParameterNode(result) }
|
||||
|
||||
/** Gets a textual representation of this node. */
|
||||
string toString() {
|
||||
result = this.asExpr().toString()
|
||||
or
|
||||
result = this.asParameter().toString()
|
||||
or
|
||||
exists(Ssa::Definition def |
|
||||
this = TSsaDefinitionNode(def) and result = "SSA def(" + def.toString() + ")"
|
||||
)
|
||||
or
|
||||
this instanceof TPostUpdateNode and
|
||||
result = "[post] " + this.(PostUpdateNode).getPreUpdateNode().toString()
|
||||
}
|
||||
|
||||
/** Gets the location of this node. */
|
||||
Location getLocation() {
|
||||
result = this.asExpr().getLocation()
|
||||
or
|
||||
result = this.asParameter().getLocation()
|
||||
or
|
||||
exists(Expr e | this = TPostUpdateNode(e) | result = e.getLocation())
|
||||
or
|
||||
exists(Ssa::Definition def |
|
||||
this = TSsaDefinitionNode(def) and result = def.getLocation()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a local source node from which data may flow to this node in zero or
|
||||
* more local data-flow steps.
|
||||
*/
|
||||
Node getALocalSource() { localFlowStep*(result, this) }
|
||||
|
||||
/**
|
||||
* Gets a data flow node from which data may flow to this node in one local step.
|
||||
*/
|
||||
Node getAPredecessor() { simpleLocalFlowStep(result, this, _) }
|
||||
|
||||
/**
|
||||
* Gets a data flow node to which data may flow from this node in one local step.
|
||||
*/
|
||||
Node getASuccessor() { simpleLocalFlowStep(this, result, _) }
|
||||
}
|
||||
|
||||
/** A data flow node corresponding to an expression. */
|
||||
class ExprNode extends Node, TExprNode {
|
||||
Expr expr;
|
||||
|
||||
ExprNode() { this = TExprNode(expr) }
|
||||
|
||||
/** Gets the underlying expression. */
|
||||
Expr getExpr() { result = expr }
|
||||
}
|
||||
|
||||
/** A data flow node corresponding to a parameter. */
|
||||
class ParameterNode extends Node, TParameterNode {
|
||||
Parameter param;
|
||||
|
||||
ParameterNode() { this = TParameterNode(param) }
|
||||
|
||||
/** Gets the underlying parameter. */
|
||||
Parameter getParameter() { result = param }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node associated with an object after an operation that might have
|
||||
* changed its state.
|
||||
*/
|
||||
class PostUpdateNode extends Node, TPostUpdateNode {
|
||||
Expr expr;
|
||||
|
||||
PostUpdateNode() { this = TPostUpdateNode(expr) }
|
||||
|
||||
/** Gets the node before the state change. */
|
||||
Node getPreUpdateNode() { result = TExprNode(expr) }
|
||||
}
|
||||
|
||||
/** A data flow node corresponding to an SSA definition. */
|
||||
class SsaDefinitionNode extends Node, TSsaDefinitionNode {
|
||||
Ssa::Definition def;
|
||||
|
||||
SsaDefinitionNode() { this = TSsaDefinitionNode(def) }
|
||||
|
||||
/** Gets the underlying SSA definition. */
|
||||
Ssa::Definition getDefinition() { result = def }
|
||||
}
|
||||
|
||||
/** Gets the node corresponding to `e`. */
|
||||
ExprNode exprNode(DataFlowExpr e) { result.getExpr() = e }
|
||||
|
||||
/** Gets the node corresponding to the value of parameter `p` at function entry. */
|
||||
ParameterNode parameterNode(Parameter p) { result.getParameter() = p }
|
||||
|
||||
/**
|
||||
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
|
||||
* (intra-procedural) step.
|
||||
*/
|
||||
predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo, _) }
|
||||
|
||||
/**
|
||||
* Holds if data flows from `source` to `sink` in zero or more local
|
||||
* (intra-procedural) steps.
|
||||
*/
|
||||
predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
|
||||
|
||||
/**
|
||||
* A reference to a local source of data flow.
|
||||
*/
|
||||
class LocalSourceNode extends Node {
|
||||
LocalSourceNode() {
|
||||
not localFlowStep(_, this)
|
||||
or
|
||||
this instanceof ParameterNode
|
||||
}
|
||||
|
||||
/** Holds if this `LocalSourceNode` flows to `sink` in zero or more local steps. */
|
||||
predicate flowsTo(Node sink) { localFlow(this, sink) }
|
||||
}
|
||||
|
||||
/** A content set for use in data flow. */
|
||||
class ContentSet instanceof Content {
|
||||
/** Gets a content that may be stored into when storing into this set. */
|
||||
Content getAStoreContent() { result = this }
|
||||
|
||||
/** Gets a content that may be read from when reading from this set. */
|
||||
Content getAReadContent() { result = this }
|
||||
|
||||
/** Gets a textual representation of this content set. */
|
||||
string toString() { result = super.toString() }
|
||||
}
|
||||
172
php/ql/lib/codeql/php/dataflow/internal/SsaImpl.qll
Normal file
172
php/ql/lib/codeql/php/dataflow/internal/SsaImpl.qll
Normal file
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* Provides an SSA (Static Single Assignment) implementation for PHP.
|
||||
*/
|
||||
|
||||
private import codeql.ssa.Ssa as SsaImplCommon
|
||||
private import codeql.php.AST
|
||||
private import codeql.php.controlflow.ControlFlowGraph as Cfg
|
||||
private import codeql.php.controlflow.BasicBlocks as BasicBlocks
|
||||
private import codeql.php.controlflow.internal.ControlFlowGraphImpl as CfgImpl
|
||||
|
||||
private class BasicBlock = BasicBlocks::Cfg::BasicBlock;
|
||||
|
||||
/**
|
||||
* A local variable, identified by name and scope. In PHP, variables within a function
|
||||
* or program scope are local to that scope; this class provides the source variable
|
||||
* for SSA analysis.
|
||||
*/
|
||||
class PhpLocalVariable extends VariableName {
|
||||
Cfg::CfgScope scope;
|
||||
|
||||
PhpLocalVariable() {
|
||||
scope = CfgImpl::getCfgScope(this)
|
||||
}
|
||||
|
||||
/** Gets the name of this variable. */
|
||||
string getVariableName() { result = this.getValue() }
|
||||
|
||||
/** Gets the scope of this variable. */
|
||||
Cfg::CfgScope getScope() { result = scope }
|
||||
|
||||
/** Gets a textual representation. */
|
||||
override string toString() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A source variable for SSA, identified by variable name and scope.
|
||||
* Multiple `VariableName` AST nodes may refer to the same source variable
|
||||
* if they have the same name and are in the same scope.
|
||||
*/
|
||||
class SsaSourceVariable extends string {
|
||||
Cfg::CfgScope scope;
|
||||
|
||||
SsaSourceVariable() {
|
||||
exists(VariableName vn |
|
||||
this = vn.getValue() and
|
||||
scope = CfgImpl::getCfgScope(vn)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the variable name. */
|
||||
string getVariableName() { result = this }
|
||||
|
||||
/** Gets the scope. */
|
||||
Cfg::CfgScope getScope() { result = scope }
|
||||
|
||||
/** Gets a location for this source variable (the first occurrence). */
|
||||
Location getLocation() {
|
||||
result =
|
||||
min(VariableName vn |
|
||||
vn.getValue() = this and CfgImpl::getCfgScope(vn) = scope
|
||||
|
|
||||
vn.getLocation()
|
||||
order by
|
||||
vn.getLocation().getStartLine(), vn.getLocation().getStartColumn()
|
||||
)
|
||||
}
|
||||
|
||||
string toString() { result = this }
|
||||
}
|
||||
|
||||
/** Gets the source variable for a `VariableName` AST node. */
|
||||
SsaSourceVariable getSourceVariable(VariableName vn) {
|
||||
result = vn.getValue() and
|
||||
result.getScope() = CfgImpl::getCfgScope(vn)
|
||||
}
|
||||
|
||||
module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock> {
|
||||
class SourceVariable = SsaSourceVariable;
|
||||
|
||||
/**
|
||||
* Holds if the CFG node at index `i` of basic block `bb` writes to variable `v`.
|
||||
*/
|
||||
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
exists(Cfg::CfgNode cfgNode, VariableName vn |
|
||||
cfgNode = bb.getNode(i) and
|
||||
vn = cfgNode.getAstNode() and
|
||||
v = getSourceVariable(vn)
|
||||
|
|
||||
// Direct assignment: $x = ...
|
||||
exists(AssignExpr assign | assign.getLeftOperand() = vn)
|
||||
or
|
||||
// Reference assignment: $x =& ...
|
||||
exists(RefAssignExpr assign | assign.getLeftOperand() = vn)
|
||||
or
|
||||
// Augmented assignment: $x += ...
|
||||
exists(AugmentedAssignExpr assign | assign.getLeftOperand() = vn)
|
||||
or
|
||||
// Update expression: $x++ / $x--
|
||||
exists(UpdateExpr upd | upd.getArgument() = vn)
|
||||
or
|
||||
// Foreach value/key variable
|
||||
exists(ForeachStmt foreach | foreach.getChild(_) = vn)
|
||||
or
|
||||
// Catch variable binding
|
||||
exists(CatchClause cc | cc.getVariable() = vn)
|
||||
or
|
||||
// Global declaration
|
||||
exists(GlobalDeclaration gd | gd.getAVariable() = vn)
|
||||
) and
|
||||
certain = true
|
||||
or
|
||||
// Parameter initialization at entry block
|
||||
exists(Cfg::CfgNode cfgNode, VariableName vn, Parameter p |
|
||||
cfgNode = bb.getNode(i) and
|
||||
vn = cfgNode.getAstNode() and
|
||||
v = getSourceVariable(vn) and
|
||||
p.getChild(_) = vn and
|
||||
p.getParent+() instanceof Callable
|
||||
) and
|
||||
certain = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the CFG node at index `i` of basic block `bb` reads variable `v`.
|
||||
*/
|
||||
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
exists(Cfg::CfgNode cfgNode, VariableName vn |
|
||||
cfgNode = bb.getNode(i) and
|
||||
vn = cfgNode.getAstNode() and
|
||||
v = getSourceVariable(vn) and
|
||||
// A read is a use that isn't a pure write target
|
||||
not exists(AssignExpr assign | assign.getLeftOperand() = vn) and
|
||||
not exists(RefAssignExpr assign | assign.getLeftOperand() = vn) and
|
||||
not (
|
||||
exists(AugmentedAssignExpr assign | assign.getLeftOperand() = vn)
|
||||
) and
|
||||
not exists(CatchClause cc | cc.getVariable() = vn) and
|
||||
not exists(GlobalDeclaration gd | gd.getAVariable() = vn)
|
||||
) and
|
||||
certain = true
|
||||
}
|
||||
}
|
||||
|
||||
import SsaImplCommon::Make<Location, BasicBlocks::Cfg, SsaInput> as Impl
|
||||
|
||||
class Definition = Impl::Definition;
|
||||
|
||||
class WriteDefinition = Impl::WriteDefinition;
|
||||
|
||||
class UncertainWriteDefinition = Impl::UncertainWriteDefinition;
|
||||
|
||||
class PhiNode = Impl::PhiNode;
|
||||
|
||||
module Consistency = Impl::Consistency;
|
||||
|
||||
/**
|
||||
* Gets a CFG node that reads the variable defined by `def`.
|
||||
*/
|
||||
Cfg::CfgNode getARead(Definition def) {
|
||||
exists(SsaSourceVariable v, BasicBlocks::BasicBlock bb, int i |
|
||||
Impl::ssaDefReachesRead(v, def, bb, i) and
|
||||
SsaInput::variableRead(bb, i, v, _) and
|
||||
result = bb.getNode(i)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an input definition to phi node `phi` from basic block `bb`.
|
||||
*/
|
||||
Definition phiHasInputFromBlock(PhiNode phi, BasicBlocks::BasicBlock bb) {
|
||||
Impl::phiHasInputFromBlock(phi, result, bb)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Provides PHP-specific definitions for use in the taint tracking library.
|
||||
*/
|
||||
|
||||
private import codeql.Locations
|
||||
private import codeql.dataflow.TaintTracking
|
||||
private import DataFlowImplSpecific
|
||||
|
||||
module PhpTaintTracking implements InputSig<Location, PhpDataFlow> {
|
||||
import TaintTrackingPrivate
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
private import codeql.php.AST
|
||||
private import DataFlowPrivate
|
||||
private import codeql.php.DataFlow
|
||||
|
||||
/**
|
||||
* Holds if `node` should be a sanitizer in all global taint flow configurations
|
||||
* but not in local taint.
|
||||
*/
|
||||
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if default taint tracking configurations should allow implicit reads
|
||||
* of `c` at sinks and inputs to additional taint steps.
|
||||
*/
|
||||
bindingset[node]
|
||||
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the additional step from `src` to `sink` should be considered
|
||||
* as a taint-propagating step in all global taint flow configurations.
|
||||
*/
|
||||
predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink, string model) {
|
||||
model = "" and
|
||||
(
|
||||
// String concatenation propagates taint
|
||||
exists(BinaryExpr binConcat |
|
||||
binConcat.getOperator() = "." and
|
||||
(src.asExpr() = binConcat.getLeftOperand() or src.asExpr() = binConcat.getRightOperand()) and
|
||||
sink.asExpr() = binConcat
|
||||
)
|
||||
or
|
||||
// Augmented string concatenation ($x .= $y) propagates taint
|
||||
exists(AugmentedAssignExpr assign |
|
||||
assign.getOperator() = ".=" and
|
||||
src.asExpr() = assign.getRightOperand() and
|
||||
sink.asExpr() = assign
|
||||
)
|
||||
or
|
||||
// Array element access propagates taint
|
||||
exists(SubscriptExpr sub |
|
||||
src.asExpr() = sub.getObject() and
|
||||
sink.asExpr() = sub
|
||||
)
|
||||
or
|
||||
// Include/require propagates taint
|
||||
exists(IncludeExpr inc |
|
||||
src.asExpr() = inc.getArgument() and
|
||||
sink.asExpr() = inc
|
||||
)
|
||||
or
|
||||
// Encapsed (interpolated) strings propagate taint
|
||||
exists(EncapsedString es |
|
||||
src.asExpr() = es.getAnElement() and
|
||||
sink.asExpr() = es
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint should propagate from `nodeFrom` to `nodeTo` speculatively.
|
||||
*/
|
||||
predicate speculativeTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { none() }
|
||||
@@ -0,0 +1,23 @@
|
||||
private import codeql.php.AST
|
||||
private import DataFlowPrivate
|
||||
private import TaintTrackingPrivate
|
||||
private import codeql.php.DataFlow
|
||||
|
||||
/**
|
||||
* Holds if taint propagates from `source` to `sink` in zero or more local
|
||||
* (intra-procedural) steps.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
|
||||
|
||||
/**
|
||||
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo`.
|
||||
*/
|
||||
predicate localTaintStep = localTaintStepCached/2;
|
||||
|
||||
cached
|
||||
private predicate localTaintStepCached(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
DataFlow::localFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
defaultAdditionalTaintStep(nodeFrom, nodeTo, _)
|
||||
}
|
||||
1822
php/ql/lib/php.dbscheme
Normal file
1822
php/ql/lib/php.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
4
php/ql/lib/php.dbscheme.stats
Normal file
4
php/ql/lib/php.dbscheme.stats
Normal file
@@ -0,0 +1,4 @@
|
||||
<dbstats>
|
||||
<typesizes></typesizes>
|
||||
<stats></stats>
|
||||
</dbstats>
|
||||
7
php/ql/lib/php.qll
Normal file
7
php/ql/lib/php.qll
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Provides classes for working with PHP programs.
|
||||
*/
|
||||
|
||||
import codeql.php.AST as Ast
|
||||
import codeql.php.CFG as Cfg
|
||||
import codeql.php.DataFlow
|
||||
13
php/ql/lib/qlpack.yml
Normal file
13
php/ql/lib/qlpack.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
name: codeql/php-all
|
||||
version: 0.1.0-dev
|
||||
groups: php
|
||||
extractor: php
|
||||
dbscheme: php.dbscheme
|
||||
upgrades: upgrades
|
||||
library: true
|
||||
dependencies:
|
||||
codeql/controlflow: ${workspace}
|
||||
codeql/dataflow: ${workspace}
|
||||
codeql/ssa: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
warnOnImplicitThis: true
|
||||
4
php/ql/src/codeql-suites/php-code-scanning.qls
Normal file
4
php/ql/src/codeql-suites/php-code-scanning.qls
Normal file
@@ -0,0 +1,4 @@
|
||||
- description: Standard Code Scanning queries for PHP
|
||||
- queries: .
|
||||
- apply: code-scanning-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
4
php/ql/src/codeql-suites/php-security-and-quality.qls
Normal file
4
php/ql/src/codeql-suites/php-security-and-quality.qls
Normal file
@@ -0,0 +1,4 @@
|
||||
- description: Security-and-quality queries for PHP
|
||||
- queries: .
|
||||
- apply: security-and-frozen-quality-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
4
php/ql/src/codeql-suites/php-security-extended.qls
Normal file
4
php/ql/src/codeql-suites/php-security-extended.qls
Normal file
@@ -0,0 +1,4 @@
|
||||
- description: Security-extended queries for PHP
|
||||
- queries: .
|
||||
- apply: security-extended-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
12
php/ql/src/qlpack.yml
Normal file
12
php/ql/src/qlpack.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
name: codeql/php-queries
|
||||
version: 0.1.0-dev
|
||||
groups:
|
||||
- php
|
||||
- queries
|
||||
suites: codeql-suites
|
||||
defaultSuiteFile: codeql-suites/php-code-scanning.qls
|
||||
dependencies:
|
||||
codeql/php-all: ${workspace}
|
||||
codeql/suite-helpers: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
warnOnImplicitThis: true
|
||||
51
php/ql/src/queries/PrintAst.ql
Normal file
51
php/ql/src/queries/PrintAst.ql
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @name Print AST
|
||||
* @description Outputs a representation of a file's Abstract Syntax Tree.
|
||||
* @id php/print-ast
|
||||
* @kind graph
|
||||
*/
|
||||
|
||||
import codeql.php.AST
|
||||
|
||||
private predicate shouldPrint(AstNode node) { any() }
|
||||
|
||||
private predicate orderBy(
|
||||
AstNode n, string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
shouldPrint(n) and
|
||||
n.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
private int getOrder(AstNode node) {
|
||||
node =
|
||||
rank[result](AstNode n, string filepath, int startline, int startcolumn, int endline,
|
||||
int endcolumn |
|
||||
orderBy(n, filepath, startline, startcolumn, endline, endcolumn)
|
||||
|
|
||||
n order by filepath, startline, startcolumn, endline, endcolumn
|
||||
)
|
||||
}
|
||||
|
||||
query predicate nodes(AstNode node, string key, string value) {
|
||||
shouldPrint(node) and
|
||||
(
|
||||
key = "semmle.label" and
|
||||
value = "[" + node.getPrimaryQlClasses() + "] " + node.toString()
|
||||
or
|
||||
key = "semmle.order" and value = getOrder(node).toString()
|
||||
)
|
||||
}
|
||||
|
||||
query predicate edges(AstNode source, AstNode target, string key, string value) {
|
||||
shouldPrint(source) and
|
||||
shouldPrint(target) and
|
||||
exists(int index | target = source.getChild(index) |
|
||||
key = "semmle.label" and value = index.toString()
|
||||
or
|
||||
key = "semmle.order" and value = index.toString()
|
||||
)
|
||||
}
|
||||
|
||||
query predicate graphProperties(string key, string value) {
|
||||
key = "semmle.graphKind" and value = "tree"
|
||||
}
|
||||
14
php/ql/src/queries/metrics/FLinesOfCode.ql
Normal file
14
php/ql/src/queries/metrics/FLinesOfCode.ql
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @name Lines of code in files
|
||||
* @kind metric
|
||||
* @description Measures the number of lines of code in each file,
|
||||
* ignoring lines that contain only comments or whitespace.
|
||||
* @metricType file
|
||||
* @id php/lines-of-code-in-files
|
||||
*/
|
||||
|
||||
import codeql.php.AST
|
||||
|
||||
from Program p, int n
|
||||
where n = p.getLocation().getFile().getNumberOfLinesOfCode()
|
||||
select p.getLocation().getFile(), n order by n desc
|
||||
21
php/ql/src/queries/security/DangerousFunctions.ql
Normal file
21
php/ql/src/queries/security/DangerousFunctions.ql
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @name Dangerous function calls
|
||||
* @description Finds calls to dangerous PHP functions like eval, exec, system, etc.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @id php/dangerous-function-calls
|
||||
* @tags security
|
||||
*/
|
||||
|
||||
import codeql.php.ast.internal.TreeSitter
|
||||
|
||||
from Php::FunctionCallExpression call, string name
|
||||
where
|
||||
name = call.getFunction().(Php::Token).getValue() and
|
||||
name =
|
||||
[
|
||||
"eval", "exec", "system", "passthru", "shell_exec", "popen", "proc_open",
|
||||
"assert", "preg_replace", "create_function", "call_user_func",
|
||||
"call_user_func_array", "unserialize"
|
||||
]
|
||||
select call, "Call to dangerous function " + name + "()."
|
||||
16
php/ql/src/queries/security/EvalUseBasic.ql
Normal file
16
php/ql/src/queries/security/EvalUseBasic.ql
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @name Eval use (basic)
|
||||
* @description Finds calls to eval() in PHP code.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id php/eval-use-basic
|
||||
* @tags security
|
||||
*/
|
||||
|
||||
import codeql.php.ast.internal.TreeSitter
|
||||
|
||||
from Php::FunctionCallExpression call, Php::AstNode fn
|
||||
where
|
||||
fn = call.getFunction() and
|
||||
fn.(Php::Token).getValue() = "eval"
|
||||
select call, "Avoid using eval()."
|
||||
92
php/ql/src/queries/security/cwe-022/PathInjection.ql
Normal file
92
php/ql/src/queries/security/cwe-022/PathInjection.ql
Normal file
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* @name Path built from user-controlled sources
|
||||
* @description Using user-controlled data to construct a file path may allow
|
||||
* an attacker to access or modify unintended files.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id php/path-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-022
|
||||
* external/cwe/cwe-023
|
||||
* external/cwe/cwe-036
|
||||
* external/cwe/cwe-073
|
||||
*/
|
||||
|
||||
import codeql.php.AST
|
||||
import codeql.php.DataFlow
|
||||
import codeql.php.TaintTracking
|
||||
|
||||
/**
|
||||
* A source of user input from PHP superglobals.
|
||||
*/
|
||||
class UserInputSource extends DataFlow::ExprNode {
|
||||
UserInputSource() {
|
||||
exists(VariableName v | v = this.asExpr() |
|
||||
v.getValue() = "$_GET" or
|
||||
v.getValue() = "$_POST" or
|
||||
v.getValue() = "$_REQUEST" or
|
||||
v.getValue() = "$_COOKIE"
|
||||
)
|
||||
or
|
||||
exists(SubscriptExpr sub, VariableName v |
|
||||
sub = this.asExpr() and
|
||||
v = sub.getObject() and
|
||||
(
|
||||
v.getValue() = "$_GET" or
|
||||
v.getValue() = "$_POST" or
|
||||
v.getValue() = "$_REQUEST" or
|
||||
v.getValue() = "$_COOKIE"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink that uses a file path.
|
||||
*/
|
||||
class PathSink extends DataFlow::ExprNode {
|
||||
PathSink() {
|
||||
exists(FunctionCallExpr call |
|
||||
call.getFunctionName() =
|
||||
[
|
||||
"fopen", "file_get_contents", "file_put_contents", "readfile", "file", "fread",
|
||||
"fwrite", "unlink", "rename", "copy", "mkdir", "rmdir", "is_file", "is_dir",
|
||||
"realpath", "glob", "move_uploaded_file"
|
||||
] and
|
||||
this.asExpr() = call.getArgument(0)
|
||||
)
|
||||
or
|
||||
// include/require are language constructs, not function calls
|
||||
exists(IncludeExpr inc | this.asExpr() = inc.getArgument())
|
||||
or
|
||||
exists(IncludeOnceExpr inc | this.asExpr() = inc.getArgument())
|
||||
or
|
||||
exists(RequireExpr req | this.asExpr() = req.getArgument())
|
||||
or
|
||||
exists(RequireOnceExpr req | this.asExpr() = req.getArgument())
|
||||
}
|
||||
}
|
||||
|
||||
module PathInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof UserInputSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof PathSink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
exists(FunctionCallExpr call |
|
||||
call.getFunctionName() = ["basename", "realpath"] and
|
||||
node.asExpr() = call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module PathInjectionFlow = TaintTracking::Global<PathInjectionConfig>;
|
||||
|
||||
import PathInjectionFlow::PathGraph
|
||||
|
||||
from PathInjectionFlow::PathNode source, PathInjectionFlow::PathNode sink
|
||||
where PathInjectionFlow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "This path depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
||||
83
php/ql/src/queries/security/cwe-078/CommandInjection.ql
Normal file
83
php/ql/src/queries/security/cwe-078/CommandInjection.ql
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @name Uncontrolled command line
|
||||
* @description Using externally controlled strings in a command line may allow
|
||||
* a malicious user to change the meaning of the command.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.8
|
||||
* @precision medium
|
||||
* @id php/command-line-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-078
|
||||
* external/cwe/cwe-088
|
||||
*/
|
||||
|
||||
import codeql.php.AST
|
||||
import codeql.php.DataFlow
|
||||
import codeql.php.TaintTracking
|
||||
|
||||
/**
|
||||
* A source of user input from PHP superglobals.
|
||||
*/
|
||||
class UserInputSource extends DataFlow::ExprNode {
|
||||
UserInputSource() {
|
||||
exists(VariableName v | v = this.asExpr() |
|
||||
v.getValue() = "$_GET" or
|
||||
v.getValue() = "$_POST" or
|
||||
v.getValue() = "$_REQUEST" or
|
||||
v.getValue() = "$_COOKIE"
|
||||
)
|
||||
or
|
||||
exists(SubscriptExpr sub, VariableName v |
|
||||
sub = this.asExpr() and
|
||||
v = sub.getObject() and
|
||||
(
|
||||
v.getValue() = "$_GET" or
|
||||
v.getValue() = "$_POST" or
|
||||
v.getValue() = "$_REQUEST" or
|
||||
v.getValue() = "$_COOKIE"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink for command execution.
|
||||
*/
|
||||
class CommandSink extends DataFlow::ExprNode {
|
||||
CommandSink() {
|
||||
exists(FunctionCallExpr call |
|
||||
call.getFunctionName() =
|
||||
[
|
||||
"exec", "system", "passthru", "shell_exec", "popen", "proc_open", "pcntl_exec",
|
||||
"eval"
|
||||
] and
|
||||
this.asExpr() = call.getArgument(0)
|
||||
)
|
||||
or
|
||||
// Backtick operator / shell_exec
|
||||
exists(ShellCommandExpr shell | this.asExpr() = shell)
|
||||
}
|
||||
}
|
||||
|
||||
module CommandInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof UserInputSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof CommandSink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
exists(FunctionCallExpr call |
|
||||
call.getFunctionName() = ["escapeshellarg", "escapeshellcmd"] and
|
||||
node.asExpr() = call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module CommandInjectionFlow = TaintTracking::Global<CommandInjectionConfig>;
|
||||
|
||||
import CommandInjectionFlow::PathGraph
|
||||
|
||||
from CommandInjectionFlow::PathNode source, CommandInjectionFlow::PathNode sink
|
||||
where CommandInjectionFlow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "This command depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
||||
84
php/ql/src/queries/security/cwe-079/ReflectedXss.ql
Normal file
84
php/ql/src/queries/security/cwe-079/ReflectedXss.ql
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @name Reflected cross-site scripting
|
||||
* @description Writing user input directly to a web page allows for
|
||||
* a cross-site scripting vulnerability.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.1
|
||||
* @precision medium
|
||||
* @id php/reflected-xss
|
||||
* @tags security
|
||||
* external/cwe/cwe-079
|
||||
* external/cwe/cwe-116
|
||||
*/
|
||||
|
||||
import codeql.php.AST
|
||||
import codeql.php.DataFlow
|
||||
import codeql.php.TaintTracking
|
||||
|
||||
/**
|
||||
* A source of user input from PHP superglobals.
|
||||
*/
|
||||
class UserInputSource extends DataFlow::ExprNode {
|
||||
UserInputSource() {
|
||||
exists(VariableName v | v = this.asExpr() |
|
||||
v.getValue() = "$_GET" or
|
||||
v.getValue() = "$_POST" or
|
||||
v.getValue() = "$_REQUEST" or
|
||||
v.getValue() = "$_COOKIE"
|
||||
)
|
||||
or
|
||||
exists(SubscriptExpr sub, VariableName v |
|
||||
sub = this.asExpr() and
|
||||
v = sub.getObject() and
|
||||
(
|
||||
v.getValue() = "$_GET" or
|
||||
v.getValue() = "$_POST" or
|
||||
v.getValue() = "$_REQUEST" or
|
||||
v.getValue() = "$_COOKIE"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An output sink that writes directly to the response (echo, print, etc).
|
||||
*/
|
||||
class XssSink extends DataFlow::ExprNode {
|
||||
XssSink() {
|
||||
// echo statement arguments
|
||||
exists(EchoStmt echo | this.asExpr() = echo.getAnArgument())
|
||||
or
|
||||
// print expression
|
||||
exists(PrintExpr print | this.asExpr() = print.getArgument())
|
||||
or
|
||||
// printf/vprintf calls
|
||||
exists(FunctionCallExpr call |
|
||||
call.getFunctionName() = ["printf", "vprintf"] and
|
||||
this.asExpr() = call.getArgument(_)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module XssConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof UserInputSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
// htmlspecialchars, htmlentities, strip_tags are sanitizers
|
||||
exists(FunctionCallExpr call |
|
||||
call.getFunctionName() = ["htmlspecialchars", "htmlentities", "strip_tags"] and
|
||||
node.asExpr() = call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module XssFlow = TaintTracking::Global<XssConfig>;
|
||||
|
||||
import XssFlow::PathGraph
|
||||
|
||||
from XssFlow::PathNode source, XssFlow::PathNode sink
|
||||
where XssFlow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to a $@.",
|
||||
source.getNode(), "user-provided value"
|
||||
77
php/ql/src/queries/security/cwe-089/SqlInjection.ql
Normal file
77
php/ql/src/queries/security/cwe-089/SqlInjection.ql
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @name SQL query built from user-controlled sources
|
||||
* @description Building a SQL query from user-controlled sources is vulnerable
|
||||
* to insertion of malicious SQL code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 8.8
|
||||
* @precision medium
|
||||
* @id php/sql-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-089
|
||||
*/
|
||||
|
||||
import codeql.php.AST
|
||||
import codeql.php.DataFlow
|
||||
import codeql.php.TaintTracking
|
||||
|
||||
/**
|
||||
* A source of user input from PHP superglobals (`$_GET`, `$_POST`, `$_REQUEST`, `$_COOKIE`).
|
||||
*/
|
||||
class UserInputSource extends DataFlow::ExprNode {
|
||||
UserInputSource() {
|
||||
exists(VariableName v | v = this.asExpr() |
|
||||
v.getValue() = "$_GET" or
|
||||
v.getValue() = "$_POST" or
|
||||
v.getValue() = "$_REQUEST" or
|
||||
v.getValue() = "$_COOKIE"
|
||||
)
|
||||
or
|
||||
exists(SubscriptExpr sub, VariableName v |
|
||||
sub = this.asExpr() and
|
||||
v = sub.getObject() and
|
||||
(
|
||||
v.getValue() = "$_GET" or
|
||||
v.getValue() = "$_POST" or
|
||||
v.getValue() = "$_REQUEST" or
|
||||
v.getValue() = "$_COOKIE"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a SQL execution function.
|
||||
*/
|
||||
class SqlSink extends DataFlow::ExprNode {
|
||||
SqlSink() {
|
||||
exists(FunctionCallExpr call |
|
||||
call.getFunctionName() =
|
||||
[
|
||||
"mysql_query", "mysqli_query", "pg_query", "sqlite_query", "sqlite_exec",
|
||||
"mssql_query"
|
||||
] and
|
||||
this.asExpr() = call.getArgument(_)
|
||||
)
|
||||
or
|
||||
exists(MethodCallExpr call |
|
||||
call.getMethodNameString() = ["query", "exec", "prepare", "execute"] and
|
||||
this.asExpr() = call.getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module SqlInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof UserInputSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof SqlSink }
|
||||
}
|
||||
|
||||
module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;
|
||||
|
||||
import SqlInjectionFlow::PathGraph
|
||||
|
||||
from SqlInjectionFlow::PathNode source, SqlInjectionFlow::PathNode sink
|
||||
where SqlInjectionFlow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "This SQL query depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
||||
18
php/ql/src/queries/security/cwe-095/EvalUse.ql
Normal file
18
php/ql/src/queries/security/cwe-095/EvalUse.ql
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @name Use of eval
|
||||
* @description Using `eval()` to evaluate arbitrary strings as PHP code
|
||||
* is a security risk and should be avoided.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision high
|
||||
* @id php/eval-use
|
||||
* @tags security
|
||||
* maintainability
|
||||
* external/cwe/cwe-095
|
||||
*/
|
||||
|
||||
import codeql.php.AST
|
||||
|
||||
from FunctionCallExpr call
|
||||
where call.getFunctionName() = "eval"
|
||||
select call, "Avoid using eval()."
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @name Unrestricted file upload
|
||||
* @description Allowing file uploads without proper validation of file type
|
||||
* or content may allow an attacker to upload and execute
|
||||
* malicious code.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 8.8
|
||||
* @precision medium
|
||||
* @id php/unrestricted-file-upload
|
||||
* @tags security
|
||||
* external/cwe/cwe-434
|
||||
*/
|
||||
|
||||
import codeql.php.AST
|
||||
|
||||
from FunctionCallExpr move
|
||||
where
|
||||
move.getFunctionName() = "move_uploaded_file" and
|
||||
not exists(FunctionCallExpr check |
|
||||
check.getLocation().getFile() = move.getLocation().getFile() and
|
||||
(
|
||||
// Common file-type validation functions
|
||||
check.getFunctionName() =
|
||||
[
|
||||
"getimagesize", "finfo_file", "mime_content_type", "pathinfo",
|
||||
"exif_imagetype"
|
||||
]
|
||||
or
|
||||
// Checking file extension via string functions
|
||||
check.getFunctionName() = ["strtolower", "in_array"] and
|
||||
exists(FunctionCallExpr inner |
|
||||
inner.getFunctionName() = ["pathinfo", "substr", "strrpos"] and
|
||||
inner.getLocation().getFile() = move.getLocation().getFile()
|
||||
)
|
||||
)
|
||||
)
|
||||
select move, "Unrestricted file upload without validation of file type or content."
|
||||
68
php/ql/src/queries/security/cwe-601/OpenRedirect.ql
Normal file
68
php/ql/src/queries/security/cwe-601/OpenRedirect.ql
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @name URL redirect from remote source
|
||||
* @description Using user-controlled data in a redirect header may allow an
|
||||
* attacker to redirect clients to a malicious URL.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.1
|
||||
* @precision medium
|
||||
* @id php/open-redirect
|
||||
* @tags security
|
||||
* external/cwe/cwe-601
|
||||
*/
|
||||
|
||||
import codeql.php.AST
|
||||
import codeql.php.DataFlow
|
||||
import codeql.php.TaintTracking
|
||||
|
||||
/**
|
||||
* A source of user input from PHP superglobals.
|
||||
*/
|
||||
class UserInputSource extends DataFlow::ExprNode {
|
||||
UserInputSource() {
|
||||
exists(VariableName v | v = this.asExpr() |
|
||||
v.getValue() = "$_GET" or
|
||||
v.getValue() = "$_POST" or
|
||||
v.getValue() = "$_REQUEST" or
|
||||
v.getValue() = "$_COOKIE"
|
||||
)
|
||||
or
|
||||
exists(SubscriptExpr sub, VariableName v |
|
||||
sub = this.asExpr() and
|
||||
v = sub.getObject() and
|
||||
(
|
||||
v.getValue() = "$_GET" or
|
||||
v.getValue() = "$_POST" or
|
||||
v.getValue() = "$_REQUEST" or
|
||||
v.getValue() = "$_COOKIE"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink that redirects the user via `header()`.
|
||||
*/
|
||||
class RedirectSink extends DataFlow::ExprNode {
|
||||
RedirectSink() {
|
||||
exists(FunctionCallExpr call |
|
||||
call.getFunctionName() = "header" and
|
||||
this.asExpr() = call.getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module OpenRedirectConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof UserInputSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof RedirectSink }
|
||||
}
|
||||
|
||||
module OpenRedirectFlow = TaintTracking::Global<OpenRedirectConfig>;
|
||||
|
||||
import OpenRedirectFlow::PathGraph
|
||||
|
||||
from OpenRedirectFlow::PathNode source, OpenRedirectFlow::PathNode sink
|
||||
where OpenRedirectFlow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "This redirect URL depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
||||
8
php/ql/test/qlpack.yml
Normal file
8
php/ql/test/qlpack.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
name: codeql/php-tests
|
||||
groups: [php, test]
|
||||
dependencies:
|
||||
codeql/php-queries: ${workspace}
|
||||
codeql/php-all: ${workspace}
|
||||
extractor: php
|
||||
tests: .
|
||||
warnOnImplicitThis: true
|
||||
11
php/tools/BUILD.bazel
Normal file
11
php/tools/BUILD.bazel
Normal file
@@ -0,0 +1,11 @@
|
||||
load("//misc/bazel:pkg.bzl", "codeql_pkg_files")
|
||||
|
||||
codeql_pkg_files(
|
||||
name = "tools",
|
||||
excludes = [
|
||||
"BUILD.bazel",
|
||||
],
|
||||
exes = glob(["**/*"]),
|
||||
prefix = "tools",
|
||||
visibility = ["//php:__pkg__"],
|
||||
)
|
||||
5
php/tools/autobuild.cmd
Normal file
5
php/tools/autobuild.cmd
Normal file
@@ -0,0 +1,5 @@
|
||||
@echo off
|
||||
|
||||
type NUL && "%CODEQL_EXTRACTOR_PHP_ROOT%\tools\%CODEQL_PLATFORM%\extractor" autobuild
|
||||
|
||||
exit /b %ERRORLEVEL%
|
||||
3
php/tools/autobuild.sh
Executable file
3
php/tools/autobuild.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
exec "${CODEQL_EXTRACTOR_PHP_ROOT}/tools/${CODEQL_PLATFORM}/extractor" autobuild
|
||||
9
php/tools/index-files.cmd
Normal file
9
php/tools/index-files.cmd
Normal file
@@ -0,0 +1,9 @@
|
||||
@echo off
|
||||
|
||||
type NUL && "%CODEQL_EXTRACTOR_PHP_ROOT%\tools\win64\extractor.exe" ^
|
||||
extract ^
|
||||
--file-list "%1" ^
|
||||
--source-archive-dir "%CODEQL_EXTRACTOR_PHP_SOURCE_ARCHIVE_DIR%" ^
|
||||
--output-dir "%CODEQL_EXTRACTOR_PHP_TRAP_DIR%"
|
||||
|
||||
exit /b %ERRORLEVEL%
|
||||
9
php/tools/index-files.sh
Executable file
9
php/tools/index-files.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
exec "${CODEQL_EXTRACTOR_PHP_ROOT}/tools/${CODEQL_PLATFORM}/extractor" \
|
||||
extract \
|
||||
--file-list "$1" \
|
||||
--source-archive-dir "$CODEQL_EXTRACTOR_PHP_SOURCE_ARCHIVE_DIR" \
|
||||
--output-dir "$CODEQL_EXTRACTOR_PHP_TRAP_DIR"
|
||||
BIN
php/tools/osx64/extractor
Executable file
BIN
php/tools/osx64/extractor
Executable file
Binary file not shown.
13
php/tools/qltest.cmd
Normal file
13
php/tools/qltest.cmd
Normal file
@@ -0,0 +1,13 @@
|
||||
@echo off
|
||||
|
||||
type NUL && "%CODEQL_DIST%\codeql.exe" database index-files ^
|
||||
--prune=**/*.testproj ^
|
||||
--include-extension=.php ^
|
||||
--include-extension=.phtml ^
|
||||
--include-extension=.inc ^
|
||||
--size-limit=5m ^
|
||||
--language=php ^
|
||||
--working-dir=. ^
|
||||
"%CODEQL_EXTRACTOR_PHP_WIP_DATABASE%"
|
||||
|
||||
exit /b %ERRORLEVEL%
|
||||
13
php/tools/qltest.sh
Executable file
13
php/tools/qltest.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
exec "${CODEQL_DIST}/codeql" database index-files \
|
||||
--prune="**/*.testproj" \
|
||||
--include-extension=.php \
|
||||
--include-extension=.phtml \
|
||||
--include-extension=.inc \
|
||||
--size-limit=5m \
|
||||
--language=php \
|
||||
--working-dir=.\
|
||||
"$CODEQL_EXTRACTOR_PHP_WIP_DATABASE"
|
||||
Reference in New Issue
Block a user