Compare commits

..

366 Commits

Author SHA1 Message Date
yoff
0a9946121b Python: migrate src queries to new shared CFG types + reformat
Migrate 27 queries under python/ql/src/ from legacy CFG types
(CallNode/AttrNode/NameNode/etc.) to the shared-CFG-based 'Cfg::'
namespace, matching the dataflow API surface introduced earlier on
this branch. ModificationOfParameterWithDefaultCustomizations.qll
is rewritten on top of BarrierGuard, removing the last legacy ESSA
dependency in that file. UnguardedNextInGenerator.ql still uses
ESSA and bridges to the new CFG via Cfg::CallNode.getNode().

Also reformat 14 library and query files that had drifted from
the formatter.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 21:35:39 +00:00
yoff
cd703dcf0c Python: omit PEP 695 type-param names from FunctionDefExpr/ClassDefExpr children
PEP 695 type-param names (e.g. `T` in `def func[T]:` or `class Box[T]:`)
bind in an annotation scope that nests the function/class body, so
their AST scope is the inner function/class — not the enclosing scope
where the FunctionDefExpr/ClassDefExpr CFG node lives. Visiting them
as children created scope-crossing CFG edges (nonLocalStep violations:
96 across CPython).

Drop them from the children list; the legacy CFG omitted them too.
TypeAliasStmt is unaffected (its type-params share scope with the
alias's enclosing scope).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 17:09:09 +00:00
yoff
350a68d65e Python: migrate remaining query-side files to new Cfg::
Four library/query files still referenced the legacy Flow.qll `ControlFlowNode`
and friends, which no longer match the dataflow library's `Cfg::ControlFlowNode`:

- SubclassFinder.qll: type `value` as `Cfg::ControlFlowNode`.
- ExceptionInfo.qll: replace `EssaNodeDefinition.getDefiningNode()` filter
  with `Cfg::NameNode.defines(_)` (the legacy ESSA class isn't reachable
  through the new dataflow API at the query-pack layer).
- ServerSideRequestForgeryCustomizations.qll: qualify `BinaryExprNode` with
  `Cfg::` and update `stringRestriction` to take `Cfg::ControlFlowNode`.
- TarSlipCustomizations.qll: qualify `CallNode`/`AttrNode`/`NameNode` and
  the `tarFileInfoSanitizer` parameter with `Cfg::`.

The three reblessed `.expected` files are purely cosmetic toString churn
("ControlFlowNode for X" -> "X", "After X"); verified set-equal after
normalising the toString prefixes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:47:42 +00:00
yoff
c91b6c9eaf Python: adapt AstNodeImpl to upstream shared-CFG signature changes
- ForStmt.getInit(int)/getUpdate(int) now return AstNode (was Expr)
- Case.getAPattern() renamed to getPattern(int index)

Both are stubs in Python (no C-style for, single match pattern).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:47:30 +00:00
yoff
091479cd6b Python: drop legacy essa import from ImportResolution
`ImportResolution.qll` was the last new-dataflow file with a direct
`import semmle.python.essa.SsaDefinitions`, used only for the
`SsaSource::init_module_submodule_defn` helper. Inline the 5-line body
as a local private predicate. No functional change — the inlined
predicate is clause-for-clause equivalent (the `f = init.getEntryNode()`
join only constrained `package = init`, since `Scope.getEntryNode()` is
unique per scope; we now express that constraint directly).

All 70 dataflow + ApiGraphs library-tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:44 +00:00
yoff
4ce6131ca3 Python: treat augmented-assignment targets as both load and store
The legacy CFG emitted two ControlFlowNodes for `x[i] += 42` (one load,
one store, with `load.strictlyDominates(store)`). The new CFG collapses
them to a single canonical node, mirroring Java's single-`VarAccess`
model where `isVarRead`/`isVarWrite` are non-disjoint on the same
expression. Reconcile two legacy two-node behaviours with the merged
single-node world:

1. `Cfg::ControlFlowNode.isLoad()` no longer excludes augmented
   targets — both `isLoad` and `isStore` hold on the merged canonical
   node, matching Java. `NameNode.defines` drops the now-redundant
   `not isLoad` guard; `Py::Name.defines` already filters by
   `isDefinition` (Store/Param/AugAssign-target ctx).

2. `LocalFlow::definitionFlowStep` is restricted to NameNode targets,
   matching legacy ESSA's `assignment_definition` which required
   `defn.(NameNode).defines(v)`. Subscript and attribute writes
   (`x[i] = 42`, `obj.attr = 42`) no longer emit a local-flow step
   *into* the LHS expression — that flow is handled by the AttrWrite
   and content-flow machinery. This is essential for keeping augmented
   Subscript/Attribute targets classifiable as `LocalSourceNode` on
   the read side, which the API graph requires for emitting Use edges.

`StoreLoadTest.ql` is updated to filter `isAugLoad` out of the regular
`load` tag, mirroring the pre-existing `not isAugStore` filter on the
`store` tag so augmented-assignment expectations remain
`augload=n augstore=n` (not also `load=n store=n`).

Closes the three remaining ApiGraphs library-test failures
(`getSubscript.ql` semantically, plus cosmetic toString updates in
`ModuleImportWithDots.ql` and `test_crosstalk.ql`).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:44 +00:00
yoff
b6f1421f3c Python: model from X import * as uncertain SSA writes
Add a 4th disjunct to `SsaImplInput::variableWrite` in the shared-SSA
adapter that mirrors legacy ESSA's `ImportStarRefinement`: every
variable whose scope is the import-star's scope, OR which is used in
the import-star's scope, gets an uncertain write at the `import *`
position.

Uncertain writes do not kill prior definitions; shared SSA's
`SsaUncertainWrite` joins the new value with the immediately-preceding
definition via `uncertainWriteDefinitionInput`. This is the equivalent
of legacy ESSA's two-input refinement.

Cannot depend on `ImportStar` / `ImportResolution` (those modules
import `SsaImpl`), so the predicate uses the structural heuristic on
`Cfg::ImportStarNode` directly.

This closes the two remaining failing dataflow library-tests:

- `import-star/global` — `module_export` chains via `from X import *`
  re-exports now resolve: the importing module has an SSA def of every
  re-exported name, so `lastUseVar` finds the read at the use site.
- `typetracking_imports/highlight_problem` — a direct `from .foo import
  foo` immediately followed by `from .other import *` is now correctly
  marked as dead at the direct import.

Two scope-entry-def noise rows in `highlight_problem.expected` are also
dropped — legacy ESSA needed them as refinement inputs, but shared SSA
handles uncertain writes without an explicit prior def. They were
always tagged `no use to normal exit` (dead).

Dataflow library-tests: 62/64 → 64/64 passing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:44 +00:00
yoff
1a2be46cb5 Python: update dataflow tests for new CFG + shared SSA
Test-side changes accompanying the dataflow migration:

  * Test queries (.ql) and shared test harness (TestSummaries,
    TestTaintLib) qualify CFG / SSA types with Cfg:: / SsaImpl::,
    bridge via AST (Name, Call, ...) instead of legacy NameNode /
    CallNode, and switch GlobalSsaVariable / EssaVariable usages
    to the new adapter API.

  * .expected files updated for legitimate precision and toString
    changes:
      - phi-node def-use edges newly exposed in def_use_counts.
      - scope-exit synthetic use surfaces one extra implicit use
        in use-use-counts.
      - For [empty]/[non-empty] outcome rows added in
        EnclosingCallable.
      - SsaSourceVariable / Global Variable label cosmetics
        normalised throughout.

  * Inline annotations:
      - typetracking/test.py: removed MISSING:tracked on lines
        93/95 (now found), added SPURIOUS:tracked on line 108
        (decorator over-reach).
      - global-flow/test.py: added SPURIOUS writes=g_mod on line
        20 (correctly reports immediately-overwritten write).
      - tainttracking/customSanitizer/test.py: marked
        try/except: ensure_tainted(s) cases as MISSING: tainted
        (no-raise CFG abstraction does not connect try body to
        except body).
      - coverage/test.py: marked
        SINK(return_from_inner_scope([])) as
        MISSING: flow=... pending closer investigation.

  * regression/{dataflow,custom_dataflow}.expected: accept two
    if/else cond-correlation over-reaches (documented limitation;
    same imprecision applies under legacy semantics by design).

After this change the dataflow library-tests stand at 62 of 64
passing; the two remaining failures are tracked under the
ImportStarRefinement workstream.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:44 +00:00
yoff
26df3945d3 Python: migrate dataflow library to new CFG + shared SSA
Switches the trunk dataflow library and all in-tree consumers
(frameworks, ApiGraphs, Concepts, regexp, security customisations,
test harness) from the legacy Flow.qll/ESSA stack to the new
shared-CFG facade (Cfg.qll) and the ESSA-shaped adapter on the
shared-SSA library (SsaImpl.qll).

Highlights:

  * DataFlowPublic/Private/Dispatch, Attributes, VariableCapture,
    IterableUnpacking, ImportResolution, ImportStar, LocalSources,
    TaintTrackingPrivate, MatchUnpacking, TypeTrackingImpl,
    SsaImpl, Builtins all now qualify CFG/SSA references with
    Cfg:: / SsaImpl:: and stop pulling in semmle.python.essa.*.

  * AstNodeImpl.qll/Cfg.qll: ImportMember exposes its inner
    ImportExpr, DefinitionNode.getValue covers Alias / AnnAssign /
    AugAssign / AssignExpr / For-target / Parameter-default,
    ForNode is treated as an expression node, AnnotatedExitNode is
    canonical, and BoolExprNode.getAnOperand drops the dominance
    constraint that did not hold for short-circuit BBs.

  * SsaImpl.qll: parameters always get a ParameterDefinition (so
    unused parameters still have SSA defs), scope-entry defs for
    module globals require an actual store somewhere, scope-exit
    has a synthetic use so reaching-defs survives to module
    boundary, and the legacy SsaSourceVariable / EssaVariable
    surface (getName, getScope, getAUse, getASourceUse,
    getAnImplicitUse) is reinstated for downstream queries.

  * DataFlowPublic.qll: GuardNode redesigned around the new
    structural outcome nodes (isAfterTrue / isAfterFalse).  The
    legacy ConditionBlock + flipped indirection is gone;
    controlsBlock walks UP through 'not' / '==True' / 'is False'
    etc. via outcomeOfGuard, accumulating polarity cleanly.  Only
    BarrierGuard<...> is preserved as public API.

  * ModuleVariableNode.getAWrite and LocalFlow::definitionFlowStep
    bypass SSA and consult Cfg::NameNode.defines /
    Cfg::DefinitionNode.getValue directly, so that write defs
    pruned by shared SSA (because the variable has no in-scope
    read) still produce dataflow steps.

  * Frameworks + downstream consumers: replace
    EssaVariable.hasDefiningNode, getAReturnValueFlowNode,
    Parameter.getDefault, Scope.getEntryNode / getANormalExit etc.
    with CFG-side bridges through Cfg::ControlFlowNode.

The legacy Flow.qll / Essa.qll stack is untouched and remains
available for queries that import it directly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:44 +00:00
yoff
3b3bec8825 Python: remove getAFlowNode() — bridge AST→CFG only via CFG-side getNode()
Option 2: eliminates the AST→CFG bridge from the AST layer. Previously
'AstNode.getAFlowNode()' returned a 'ControlFlowNode' from the legacy
'Flow.qll' CFG via 'py_flow_bb_node' — this hardcoded the AST to know
about the legacy CFG, preventing files from cleanly switching to the
new shared CFG.

Removes:
  * 'AstNode.getAFlowNode()' from 'AstExtended.qll'
  * Type-narrowing overrides on 'Attribute' / 'Subscript' / 'Call' /
    'IfExp' / 'Name' / 'NameConstant' / 'ImportMember' (in Exprs.qll
    and Import.qll)

Rewrites ~130 call sites across 'python/ql/lib/' and 'python/ql/src/'
to bridge from the CFG side instead:

  Before:  node = expr.getAFlowNode()
  After:   node.getNode() = expr

  Before:  expr.getAFlowNode().(DefinitionNode).getValue()
  After:   exists(DefinitionNode d | d.getNode() = expr | d.getValue())

  Before:  cn.operands(const.getAFlowNode(), op, x)
  After:   exists(ControlFlowNode c | c.getNode() = const | cn.operands(c, op, x))

This is semantically a no-op — both forms are duals of the same predicate.
Verified by passing all library tests:
  * 64 dataflow tests
  * 28 ControlFlow + dataflow-new-ssa tests
  * 1 essa SSA-compute test
  * 93 tests total in the focused suite

Once committed, files that want to switch from the legacy 'Flow' CFG
to the new 'Cfg' facade only need to change their imports — the
bridge sites are CFG-side and respect whichever ControlFlowNode is in
scope.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:44 +00:00
yoff
6978cecb89 Python: SSA adapter: add MultiAssignmentDefinition, definedBy, useOfDef
Extends the ESSA-shaped adapter on top of the new shared SSA with the
remaining APIs consumed by the dataflow library:

  * MultiAssignmentDefinition: matches the AST pattern 'a, b = ...' where
    the LHS is a Tuple/List and the Name being defined is a sub-element.
    Used by IterableUnpacking.qll to recognise unpacking assignments.

  * EssaNodeDefinition.definedBy(var, defNode): a flatter equivalent of
    'getSourceVariable() = var and getDefiningNode() = defNode', matching
    legacy ESSA's signature. Used by DataFlowPublic.qll's
    ModuleVariableNode to enumerate writes of a global.

  * AdjacentUses::useOfDef(def, use): all reachable uses of a definition
    (firstUse plus transitive use-use adjacency). Used by guards in
    DataFlowPublic.qll.

These complete the API surface enumerated by grep across the dataflow
library. The remaining items (EssaNodeRefinement, EssaImportStep) are
ImportResolution-specific and will need separate treatment, possibly via
a different abstraction since the SSA library does not model heap-state
refinements like 'foo.bar = X'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:43 +00:00
yoff
57fa3ee2d4 Python: SSA: handle closure variables via per-scope entry defs
The new SSA's implicit entry-def predicate previously placed entries in
the variable's defining scope. For closure variables that's the outer
function, so inner functions had no entry def for the captured
variable — reads in the inner scope failed to resolve to any
definition.

Mirrors legacy ESSA's 'NonLocalVariable.getScopeEntryDefinition()':
place an implicit entry def at every reading scope's entry block,
independently of where the variable is *defined*. A closure variable
accessed in two nested functions and the outer one gets three entry
defs (one per reading scope).

Also makes 'ScopeEntryDefinition' extend 'EssaNodeDefinition' (matching
legacy ESSA), with 'getDefiningNode()' returning the scope's entry CFG
node. This requires extending the private 'writeDefNode' helper to
project i=-1 entries to bb.getNode(0).

Updates the new-vs-legacy comparison snapshot: closure-variable reads
('x:32:5'), nested global reads ('GLOBAL:52:1') now resolve. New
'def-only-new' entries appear for unbound names ('sum', 'open',
'compute') — the new SSA uniformly creates scope-entry defs for all
non-local reads, including those that legacy ESSA classifies as
builtin and excludes. This is a more uniform semantic and arguably
cleaner.

Updates the SsaTest 'some_undefined' annotation: previously documented
as a known limitation, now correctly resolves to a scope-entry def.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:43 +00:00
yoff
ac468c8f37 Python: extend new SSA with ESSA-shaped adapter + baseline comparison test
Phase 0.5 - Adapter API on top of the shared SSA:

Adds the legacy-ESSA-shaped class hierarchy that the dataflow library
consumes, layered on the shared 'Ssa::Make' instantiation:

  * EssaDefinition / EssaNodeDefinition: the latter exposes
    'getDefiningNode()' (the CFG node at the def's index in its BB)
    and 'getVariable()' / 'getScope()'.
  * AssignmentDefinition: matches Assign, AnnAssign with value,
    AssignExpr and AugAssign target Names. Exposes 'getValue()'
    pointing at the RHS' CFG node.
  * ParameterDefinition: matches when the defining Name is in
    parameter context.
  * WithDefinition: matches 'with ... as x:' bindings.
  * ScopeEntryDefinition: implicit entry defs at synthetic position
    '-1' of the scope's entry basic block (non-local / global /
    builtin / captured reads).
  * PhiFunction (alias for PhiNode).
  * EssaVariable adapter wrapping a 'Ssa::Definition' with 'getAUse()',
    'getDefinition()', 'getAnUltimateDefinition()', and 'getName()'.
  * AdjacentUses module with 'firstUse' and 'adjacentUseUse' predicates
    bridging to 'Ssa::firstUse' / 'Ssa::adjacentUseUse'.

This is the minimum API the new dataflow's internals call into. The
richer legacy ESSA (refinement nodes, attribute refinements, edge
refinements) stays in 'semmle.python.essa.Essa' for legacy code.

Phase 0.6 - Comparison test:

Adds 'dataflow-new-ssa-vs-legacy/CmpTest.ql' that snapshots the
difference between definitions produced by new SSA vs legacy ESSA on
the same Python source. Baseline output records the current
'def-only-old' mismatches, grouped by category:

  * function/class/global definitions with no in-scope read (intentional;
    SSA is liveness-pruned)
  * captured / closure variables (real gap in new SSA - no
    closure-capture handling yet)
  * module variables __name__ / __package__ / $ (legacy ESSA implicit
    bindings)
  * exception 'as' bindings (depend on raise modelling)

Zero 'def-only-new' mismatches: the new SSA never produces a spurious
definition compared to legacy ESSA on this corpus.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:43 +00:00
yoff
8790f63888 Python: qualify Flow.qll's AST references with Py:: prefix
Prepares Flow.qll for co-existence with the new CFG facade by switching
'import python' to 'import python as Py' and qualifying every AST-class
reference inside Flow.qll's body. Flow.qll's own CFG types
(ControlFlowNode, BasicBlock, CallNode, NameNode, etc.) keep their
unqualified names.

This change is a no-op semantically:
  * all 24 evaluation-order tests still pass,
  * the bindings + store-load + new-CFG-SSA library tests still pass,
  * compilation produces zero errors.

The change enables a follow-up commit to swap python.qll's
'import semmle.python.Flow' for 'import semmle.python.controlflow.internal.Cfg'
without triggering name-clash errors inside Flow.qll itself. Legacy
modules that still want the legacy CFG (essa/, GuardedControlFlow,
LegacyPointsTo, objects/, pointsto/, types/, dataflow/old/) will need a
similar treatment in subsequent commits.

The qualification was applied mechanically via a script that prefixed
every reference to a known AST class. The list includes the standard
AST node types from semmle.python.{Files, Variables, Stmts, Exprs,
Class, Function, Patterns, Comprehensions} plus 'Location' / 'File' /
'Folder' / 'Container' / 'ConditionBlock' / 'Delete' / 'Load'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:43 +00:00
yoff
96de5cf188 Python: bring Cfg.qll's facade to API parity with Flow.qll
Adds the methods and type-narrowing overrides needed for Cfg.qll to be
a drop-in replacement for Flow.qll's CFG API surface:

  * 'override getNode()' type narrowing on all AST-shape subclasses
    (CallNode -> Py::Call, AttrNode -> Py::Attribute, ImportExprNode
    -> Py::ImportExpr, etc.). This lets callers chain methods like
    'iexpr.getNode().isRelative()' that previously failed because
    'getNode()' returned the generic AstNode.

  * 'ControlFlowNode.isBranch()' -- true and/or false successor exists.
  * 'ControlFlowNode.getAChild()' -- CFG-level child traversal via the
    AST's getAChildNode, with dominance constraint.
  * 'ControlFlowNode.strictlyReaches(other)' -- node-level reachability.
  * 'NameNode.isSelf()' -- AST-level approximation: uses the 'Variable'
    that is the first parameter of an enclosing method.
  * 'BinaryExprNode.operands(left, op, right)' + 'getAnOperand()'.
  * 'BoolExprNode.getAnOperand()'.
  * 'ForNode.getSequence()' (alias for 'getIter') and
    'ForNode.iterates(target, sequence)'.
  * 'ForNode' / 'RaiseStmtNode' type-narrowing overrides.
  * 'ExceptFlowNode.getName()' / 'ExceptGroupFlowNode.getName()'
    -- the bound 'as'-name CFG node.
  * 'DictNode.getAKey()' (only 'getAValue' was present).

These additions are independent of the dataflow-migration approach
(option 4 vs option 5). They close the API-parity gap identified
during the Option-5 investigation; with them in place, hundreds of
type-resolution errors that previously appeared when swapping Cfg for
Flow at the python.qll level go away.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:43 +00:00
yoff
f5bf8ae8dd Python: fix augstore for the new CFG and add store/load test
In the legacy CFG the same Python 'Name' that is the target of an
augmented assignment has two distinct CFG nodes — a load node (context
3) earlier in the basic block and a store node (context 5) later.
'augstore(load, store)' relates the pair via dominance.

The new (shared) CFG canonicalises each AST expression to a single
CFG node, so 'load' and 'store' collapse to one. The dominance-based
'augstore' from the legacy implementation no longer holds (it would
require 'load.strictlyDominates(load)'), so 'isAugLoad' / 'isAugStore'
never fired and 'isStore' missed the AugAssign target entirely.

Redefines 'augstore' as reflexive on the AugAssign target's canonical
CFG node. With this change:

  * isAugLoad / isAugStore both fire on the single canonical node.
  * isStore fires (via 'or augstore(_, this)') — matching the legacy
    classification that an augmented-assignment target is a store.
  * isLoad does not fire (excluded by 'not augstore(_, this)').

Adds 'python/ql/test/library-tests/ControlFlow/store-load/' covering
plain load/store/delete, parameters, augmented assignment, tuple
unpacking, attribute and subscript stores. The test asserts the
classification directly on the new-CFG facade.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:43 +00:00
yoff
79db96c717 Python: introduce shared-SSA adapter on the new CFG
Adds 'python/ql/lib/semmle/python/dataflow/new/internal/SsaImpl.qll', a
minimal Python SSA implementation built on the shared SSA library
('codeql.ssa.Ssa::Make<Location, Cfg, Input>'). The structure mirrors
Java's adapter at 'java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll'.

Key design choices:

  * 'SourceVariable' wraps 'Py::Variable'. Only variables that are read
    or deleted somewhere are tracked - write-only variables don't
    benefit from SSA construction.

  * Variable references are positional ('BasicBlock', 'int') pairs
    looked up via 'Cfg::NameNode.defines'/'.uses'/'.deletes' (which
    themselves are one-line bridges to AST-level 'Name.defines' etc.).

  * Parameter writes are not synthesised: parameter Name nodes are
    already wired into the CFG (per the earlier C#-style parameter
    extension in 'AstNodeImpl.qll'), so the regular 'variableWrite'
    path handles them at their natural CFG index.

  * Non-local / captured / global / builtin variables read in a scope
    but not written in it receive a synthetic entry definition at
    index '-1' of the scope's entry basic block. This matches Java's
    'hasEntryDef'.

  * 'del x' is modelled as a certain write at the deletion site.

Includes an inline-expectations test under
'python/ql/test/library-tests/dataflow-new-ssa/' covering:
plain parameter pass-through, simple assignment + read, reassignment
with dead-write pruning, if/else with phi insertion at the join, and
an undefined-name read (currently a known limitation - no SSA flow
without an enclosing definition).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:43 +00:00
yoff
84484891b8 Python: introduce new-CFG facade
Adds 'Cfg.qll' alongside 'AstNodeImpl.qll' in the controlflow internal
package. The facade re-exposes the same API surface as the legacy
'semmle/python/Flow.qll' (ControlFlowNode, BasicBlock, NameNode, CallNode,
AttrNode, ImportExprNode, ImportMemberNode, ImportStarNode, SubscriptNode,
CompareNode, IfExprNode, AssignmentExprNode, BinaryExprNode, BoolExprNode,
UnaryExprNode, DefinitionNode, DeletionNode, ForNode, RaiseStmtNode,
StarredNode, ExceptFlowNode, ExceptGroupFlowNode, TupleNode, ListNode,
SetNode, DictNode, IterableNode, NameConstantNode), but is implemented
on top of the new shared CFG via 'AstNodeImpl.qll'.

The variable-identity predicates ('NameNode.defines', '.uses',
'.deletes', '.isLocal', '.isNonLocal', ...) are one-line bridges to the
underlying AST predicates ('Name.defines', '.uses', '.deletes'),
mirroring the Java pattern.

Re-exports 'EntryBasicBlock' and 'dominatingEdge/2' from the shared
'BB::CfgSig' produced by 'AstNodeImpl.qll', so downstream consumers
(e.g. the SSA adapter) can wire the new CFG into other shared modules
that expect a 'CfgSig' implementation.

This facade is not yet consumed by the dataflow library — that is the
next phase.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:43 +00:00
yoff
3c21bbfbf5 Python: test dead bindings under no-raise CFG abstraction
Adds 'dead_under_no_raise.py' to the bindings test suite, capturing the
three CPython patterns where bindings legitimately have no CFG node
because the surrounding code is unreachable under the 'no expressions
raise' abstraction:

  1. Statements after a 'try: return X; except: pass' block.
  2. The 'else:' clause of a try whose body always raises.
  3. Cache-lookup pattern 'try: return cache[k]; except: pass' followed
     by computation and store.

These bindings intentionally carry no 'cfgdefines=' annotations. If
raise modelling is later added to the CFG, the BindingsTest will surface
the new CFG nodes as unexpected results and this file will need to be
revisited.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:43 +00:00
yoff
01c6b2b262 Python: wire PEP 695 type parameters into the shared CFG (green)
Adds CFG coverage for the binding 'Name's introduced by PEP 695
type-parameter syntax on functions, classes, and 'type' aliases:

  def func[T](...): ...
  class Box[T]: ...
  def multi[T: int, *Ts, **P](...): ...
  type Alias[T] = ...

For each parametrised AST node, the type-parameter names (and, for
'type' aliases, the alias name itself) are added as children of the
enclosing CFG node so that 'Name.defines(v)' has a corresponding
position. Bounds and defaults are intentionally not wired (they have
no SSA-relevant semantics for our purposes).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:42 +00:00
Copilot
f12307278a Python: wire match-pattern bindings into the shared CFG (green)
Adds concrete `Pattern` subclasses in `AstNodeImpl.qll` for every
`MatchPattern` AST kind, with `getChild` overrides that expose
sub-patterns and bound Names. Specifically:

- MatchCapturePattern (`case x:`) -> getVariable()
- MatchAsPattern (`case … as v:`) -> getPattern(), getAlias()
- MatchStarPattern (`case [*rest]:`) -> getTarget()
- MatchSequencePattern (`case [a, b]:`) -> getPattern(i)
- MatchClassPattern (`case Cls(p, q, k=v)`) -> getClass(), positional, keyword
- MatchMappingPattern (`case {k: v}:`) -> getMapping(i)
- MatchKeyValuePattern, MatchKeywordPattern, MatchDoubleStarPattern
- MatchOrPattern, MatchLiteralPattern, MatchValuePattern

Without these, every Name bound by a match pattern lacked a CFG node.
Removes the corresponding MISSING: annotations from match_pattern.py
(all 11 cases).

Verified: all 24 ControlFlow/evaluation-order tests still pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:42 +00:00
Copilot
ba9dc9f5f1 Python: wire import-statement bindings into the shared CFG (green)
Adds `ImportStmt` and `ImportStarStmt` wrappers in `AstNodeImpl.qll`.
For each `Alias` in an import statement, both the value (module/member
expression) and the bound `asname` Name become children of the CFG node
for the import statement, in evaluation order.

Without this, every `Name` introduced by `import` / `from .. import ..`
lacked a CFG node, even though `Name.defines(v)` returns true for it on
the AST side. This was the highest-volume gap: 20,332 missing import
aliases across CPython.

Removes the corresponding MISSING: annotations from imports.py.

Verified: all 24 ControlFlow/evaluation-order tests still pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:42 +00:00
Copilot
768ebc1e2d Python: wire parameters into the shared CFG (C# pattern)
Implements `AstSig::Parameter` and `callableGetParameter(c, i)` in
`AstNodeImpl.qll`, following the C# template
(`csharp/.../ControlFlowGraph.qll:147-156`) rather than Java's
`Parameter() { none() }`.

Each Python parameter (positional, *args, keyword-only, **kwargs) now
becomes a CFG node at a stable position in the enclosing callable's
entry sequence. Defaults still evaluate at function-definition time
via `FunctionDefExpr.getDefault` / `LambdaExpr.getDefault`, so
`Parameter::getDefaultValue()` returns `none()` (the shared CFG
library calls this to model the missing-argument fallback, which
Python does not surface at the CFG level).

The bindings test now exercises parameters (the `py_expr_contexts(_, 4, ...)`
exclusion has been removed). A new `parameters.py` test case covers
positional, defaulted, vararg, kwarg, keyword-only, kitchen-sink,
method (self/cls), lambda, and PEP 570 positional-only parameters.
Several other test files were updated to annotate parameters that the
test had previously hidden (synthetic `.0` comprehension parameter,
method `self`, decorator `f`, etc.).

Verified:
- All 24 ControlFlow/evaluation-order tests still pass.
- CFG consistency query (`python/ql/consistency-queries/CfgConsistency.ql`)
  shows zero violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:42 +00:00
Copilot
5d60a0d7c1 Python: wire AnnAssign into the shared CFG (green)
Adds an `AnnAssignStmt` wrapper in `AstNodeImpl.qll` so that PEP 526
annotated assignments (`x: int = 1`, `x: int`) participate in the
control flow graph. Evaluation order follows CPython: annotation,
optional value, target binding.

Without this, `x: int = 1` had no CFG node for `x` even though
`Name.defines(v)` returns true for it on the AST side. SSA built on
the new CFG would therefore miss every annotated-assignment write.

Removes the corresponding MISSING: annotations from the CFG-binding
gap test:
- annassign.py — all four cases now green.
- match_pattern.py — class-body annotated fields (`x: int`, `y: int`).
- type_params.py — `item: T` inside class.

Verified: all 24 ControlFlow/evaluation-order tests still pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:42 +00:00
Copilot
336c7a44a8 Python: add CFG-binding gap tests (red)
Adds inline-expectation tests for the new shared CFG implementation in
python/ql/lib/semmle/python/controlflow/internal/AstNodeImpl.qll,
covering every Python binding construct that introduces a variable.

The test files use MISSING: annotations to record bindings whose
defining Name AST node is *not* currently reachable from the new CFG.
These are the 'red' half of red-green commit pairs: subsequent commits
will extend AstNodeImpl to cover each construct and remove the
corresponding MISSING: marker.

Confirmed-broken categories:
- Import aliases (from x import a)
- Annotated assignment (x: int = 1)
- Exception handler (except E as e)
- Match patterns (case x, case [a,b], case ... as v)
- PEP 695 type params (def f[T], class C[T])

Confirmed-working (no MISSING:):
- Compound targets, with-as, comprehensions, decorated def/class,
  walrus, starred.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:42 +00:00
Copilot
a70abdd007 Python: project via as* helpers outside characteristic predicates
Style cleanup: avoid naming newtype branch constructors (TPyStmt,
TPyExpr, TBlockStmt, TPattern, TBoolExprPair, TScope) outside the
char-preds that classify their wrappers. Method bodies and helper
predicates now use the as* projections instead:

  // Before: result = TBlockStmt(ifStmt.getBody())
  // After:  result.asStmtList() = ifStmt.getBody()

  // Before: result = TPyStmt(matchStmt.getCase(index))
  // After:  result.asStmt() = matchStmt.getCase(index)

Adds:

- AstNode.asStmtList() - the inverse of TBlockStmt(_).
- BinaryExpr.getIndex() - exposes the synthetic-pair index, used
  internally by getRightOperand to find the next pair without
  naming TBoolExprPair.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:42 +00:00
Copilot
115a762f4c Python: use newtype-branch constructors in characteristic predicates
Style cleanup: when a class's characteristic predicate binds via a
'cast' helper like

  IfStmt() { ifStmt = this.asStmt() }

prefer naming the newtype branch directly:

  IfStmt() { this = TPyStmt(ifStmt) }

This makes the wrapped representation explicit. Apply throughout:
~30 charpreds (every Stmt/Expr leaf wrapper, plus LoopStmt, BreakStmt,
ContinueStmt, BooleanLiteral, UnaryExpr, ArithUnaryExpr, Comprehension).

Method bodies that use asStmt/asExpr to project an underlying
Python AST node (Stmt.toString, BlockStmt.getEnclosingCallable,
UnaryExpr.getOperand, etc.) keep that form - they're projections,
not classifications.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:42 +00:00
Copilot
8f419d1050 Python: introduce TExpr union via newtype-branch alias
Mirror the TStmt refactor for the Expr hierarchy: rename the TExpr
newtype branch to TPyExpr and add

  private class TExpr = TPyExpr or TBoolExprPair;

This lets the public Expr class use TExpr directly:

  class Expr extends AstNodeImpl, TExpr { ... }

instead of

  class Expr extends AstNodeImpl {
    Expr() { this instanceof TExpr or this instanceof TBoolExprPair }
    ...
  }

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:42 +00:00
Copilot
8ca2a30dea Python: simplify TBlockStmt char pred via exclusion list
Replace the 14-disjunct allow-list with a 2-conjunct exclusion list.
Of the 17 Py::StmtList getters in AstGenerated.qll, only Try.getHandlers()
and MatchStmt.getCases() should not be wrapped as BlockStmts (they are
iterated individually by the shared library's Try/Switch logic via
getCatch(int) and getCase(int)). All other StmtLists are imperative
block bodies.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:41 +00:00
Copilot
fe394788d3 Python: introduce TStmt union via newtype-branch alias
Rename the TStmt newtype branch to TPyStmt, and add a private union
type alias

  private class TStmt = TPyStmt or TBlockStmt;

This lets the public Stmt class use TStmt directly in its extends
clause:

  class Stmt extends AstNodeImpl, TStmt { ... }

instead of the previous

  class Stmt extends AstNodeImpl {
    Stmt() { this instanceof TStmt or this instanceof TBlockStmt }
    ...
  }

The same pattern is used in cpp/.../TInstruction.qll and
rust/.../Synth.qll.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:41 +00:00
Copilot
761b3e38a2 Python: use private-abstract + final-alias pattern for AstNode
Convert AstNode from a concrete class with empty default predicates into
a private abstract class plus a final alias, matching the pattern used
in cpp/.../EdgeKind.qll and cpp/.../IRVariable.qll:

  abstract private class AstNodeImpl extends TAstNode {
    abstract string toString();
    abstract Py::Location getLocation();
    abstract Callable getEnclosingCallable();
    ...
  }

  final class AstNode = AstNodeImpl;

This makes the compiler enforce that every concrete subclass implements
toString/getLocation/getEnclosingCallable, replacing the brittle
'empty default + per-branch override' arrangement. Sister classes
inside the module now extend AstNodeImpl instead of AstNode (which is
final and cannot be extended).

The empty Parameter stub gains explicit none() overrides for the
three abstract members, since QL requires them statically even when
the class has no instances.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:41 +00:00
Copilot
72d74ae9dc Python: document why Assignment subclasses are empty
Explain that the shared library's Assignment / CompoundAssignment
hierarchy extends BinaryExpr, so it cannot host Python's statement-
level assignment forms (Assign, AugAssign), and that Python has no
short-circuiting compound operators (&&=, ||=, ??=) so all
subclasses remain empty.

No behaviour change; doc comments only.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:41 +00:00
Copilot
1e51c8250b Python: index TBlockStmt by Py::StmtList instead of (parent, slot)
Replace the two-key TBlockStmt(Py::AstNode parent, string slot) newtype
branch with the simpler TBlockStmt(Py::StmtList sl). Each Py::StmtList
that represents an imperative block (function/class/module body, if/
while/for branch, try/except/finally body, case body, except/except*
body) becomes one BlockStmt directly. The slot string disappears;
toString just defers to Py::StmtList.toString() ('StmtList').

The newtype branch keeps an explicit characteristic predicate listing
the slots that count as block bodies. This excludes Try.getHandlers(),
which is a Py::StmtList of ExceptStmt items already iterated by the
shared library's Try logic via getCatch(int) - including it would
produce parallel CFG edges (verified: a permissive
TBlockStmt(Py::StmtList sl) version regressed CPython to 1720
multipleSuccessors and 584 deadEnds before this restriction).

Drops the getBodyStmtList helper. Caller sites now use the StmtList
accessor directly: TBlockStmt(ifStmt.getBody()),
TBlockStmt(tryStmt.getFinalbody()), etc.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:41 +00:00
Copilot
7176fd8dbc Python: unify Py::BoolExpr handling via TBoolExprPair
Previously a Py::BoolExpr appeared in two newtype branches: as TExpr(be)
(the outermost pair) and TBoolExprPair(be, i) for inner pairs of 3+
operand expressions. This forced BinaryExpr/LogicalAndExpr/LogicalOrExpr
to disjoin two cases, and the synthetic-pair handling spanned multiple
layers.

Restrict TExpr to non-BoolExpr Py::Expr, and extend TBoolExprPair to
cover every operand pair (index 0..n-2). Now every Py::BoolExpr is
represented uniformly as TBoolExprPair(_, 0) for the whole expression
and TBoolExprPair(_, i) for inner pairs.

Extend AstNode.asExpr() to also recover the underlying Py::BoolExpr
from TBoolExprPair(_, 0). This makes asExpr() the inverse of
construction: every 'result = TExpr(e)' turns into 'result.asExpr() = e',
which works uniformly for BoolExprs and non-BoolExprs alike.

Consequences:

- BinaryExpr now extends TBoolExprPair directly with a single uniform
  rule for left/right operands.
- LogicalAndExpr/LogicalOrExpr are one-line char preds via
  getBoolExpr().
- The private BoolExprPair wrapper class folds into BinaryExpr.
- 60+ leaf wrappers now read 'result.asExpr() = py_expr' instead of
  'result = TExpr(py_expr)'.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:41 +00:00
Copilot
19b9aa8ba8 Python: merge T*AstNode wrappers into matching public classes
Five of the six per-newtype-branch wrapper classes had a natural
public class corresponding to that branch:

  TStmtAstNode      -> Stmt        (TStmt subset; BlockStmt overrides for TBlockStmt)
  TExprAstNode      -> Expr        (TExpr subset; BoolExprPair overrides for TBoolExprPair)
  TScopeAstNode     -> Callable    (= TScope exactly)
  TPatternAstNode   -> Pattern     (= TPattern exactly)
  TBlockStmtAstNode -> BlockStmt   (= TBlockStmt exactly)

Move toString/getLocation/getEnclosingCallable onto these classes and
delete the wrappers.

The sixth wrapper (TBoolExprPair) has no exact public counterpart -
BinaryExpr is broader, including TExpr-branch BoolExprs - so it
remains as a small private class, renamed BoolExprPair.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:39 +00:00
Copilot
4dbd904365 Python: dispatch toString/getLocation/getEnclosingCallable per branch
Replace the three big disjunctive predicates on AstNode with empty
defaults plus per-newtype-branch override classes:

  AstNode.toString()              { none() }
  AstNode.getLocation()           { none() }
  AstNode.getEnclosingCallable()  { none() }

Six private subclasses (one per newtype branch — TStmt, TExpr,
TScope, TPattern, TBoolExprPair, TBlockStmt) override these with
the branch-specific implementation. This mirrors the per-class
dispatch already used for getChild.

No behaviour change: all 24 NewCfg evaluation-order tests pass and
all 11 shared-CFG consistency queries still report 0 violations on
CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:39 +00:00
Copilot
372944b4b9 Python: adapt to new shared CFG signature
Main added two new requirements to AstSig:
- A 'Parameter' class with a 'getDefaultValue()' method, plus a
  'callableGetParameter(Callable, int)' predicate.
- A 'CallableContext' class in InputSig1, replacing the previous
  'CallableBodyPartContext'.

Add stub implementations: 'Parameter' is empty (none()) and
'callableGetParameter' returns nothing, mirroring Java's TODO. Rename
'CallableBodyPartContext = Void' to 'CallableContext = Void' in the
Python Input module.

NewCfg evaluation-order tests still pass at the 22/24 baseline; all
11 shared-CFG consistency queries still report 0 violations on
CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:39 +00:00
Copilot
a3270ec9f5 Python: refactor getChild into per-class OO dispatch
Replace the single ~240-line top-level getChild predicate with one
override per AST class. AstNode declares a default

  AstNode getChild(int index) { none() }

and each subclass with children overrides it (41 classes total).
The top-level predicate becomes a one-line dispatch:

  AstNode getChild(AstNode n, int index) { result = n.getChild(index) }

No behavioral change: NewCfg evaluation-order tests still pass at the
same 22/24 baseline, and all 11 shared-CFG consistency queries still
report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:39 +00:00
Copilot
d375900809 Python: include try-else in getChild for completion propagation
The shared CFG library propagates abrupt completions from child to
parent via getChild(parent, _) = child. Python's try.getElse() was
wired into normal step rules but not listed in getChild(TryStmt, ...),
so return/break/continue/raise statements occurring inside a try-else
block had no parent path and ended up as dead-end CFG nodes.

Add the else block at index -2 (alongside finally at -1). This affects
only completion propagation; the normal-flow CFG is unchanged because
TryStmt has explicit step rules.

Verified on a CPython database: all 11 shared-CFG consistency queries
now pass with 0 violations (deadEnd: 244 -> 0).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:39 +00:00
Copilot
577cf4a630 Shared CFG: support for-else and while-else loops
Add two default predicates to AstSig:

  default AstNode getWhileElse(WhileStmt loop) { none() }
  default AstNode getForeachElse(ForeachStmt loop) { none() }

When defined, the explicit-step rules for While/Do and Foreach
route the loop's normal-completion exits through the else block
before reaching the after-loop node:

  - WhileStmt: after-false condition -> before-else -> after-while
    (instead of directly after-while).
  - ForeachStmt: after-collection [empty] and the LoopHeader exit
    are both routed through before-else -> after-foreach.

Python's Ast module overrides the predicates to return the
synthetic BlockStmt for the orelse slot, replacing the previous
customisations in Input::step. This eliminates parallel direct
successors emitted by the previous Python-side step additions
(verified: multipleSuccessors on a CPython database goes from
1340 to 0).

Java and C# CFG tests are unaffected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:39 +00:00
Copilot
158c81c06d Python: compact-renumber FunctionExpr/Lambda defaults
`Args.getDefault(int)` and `Args.getKwDefault(int)` are indexed by
argument position (with gaps for args without defaults), not by
default position. The CFG `getChild` predicate for FunctionDefExpr
and LambdaExpr therefore had gaps at low indices and collisions
where defaults and kwdefaults overlapped, producing parallel
edges before the FunctionExpr.

Use `rank` to compact-renumber `getDefault(n)` and `getKwDefault(n)`
in source order. Verified on a CPython database: removes ~536
`multipleSuccessors` consistency results (1340 -> 804); the rest are
`for/else` and `while/else`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:39 +00:00
Copilot
2de3733fe3 Python: collapse two-layer AstNodeImpl into a single Ast module
Merge the previous `Ast` and `AstSigImpl` modules into a single
`module Ast implements AstSig<Py::Location>`. Classes now use the
signature names (IfStmt, WhileStmt, ForeachStmt, etc.) and signature
predicates (getCondition, getThen, getElse, etc.) directly, with no
intermediate renaming layer.

Drop the TStmtListNode newtype branch entirely. Replace it with a
synthetic TBlockStmt(parent, slot) keyed by a parent AST node and a
slot label string ('body', 'orelse', 'finally'). Py::StmtList no
longer appears in the newtype; the BlockStmt class provides indexed
access to the underlying body items via getStmt(n).

All 22 of 24 evaluation-order tests still pass; the same 2
comprehension-related failures predate this refactor.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 16:32:38 +00:00
yoff
7264483e59 python: add consistency checks
Co-authored-by: aschackmull <aschackmull@github.com>
2026-05-26 16:32:38 +00:00
yoff
0dabf47344 Python: add pattern nodes
Co-authored-by: Copilot <copilot@github.com>
2026-05-26 16:32:38 +00:00
Taus
661a77b415 Cleanup, printCFG
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:38 +00:00
Taus
28567870ac WIP2 2026-05-26 16:32:38 +00:00
Taus
f5629a5583 WIP 2026-05-26 16:32:38 +00:00
Taus
71a547b0d3 Python: Handle dict unpacking in calls
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:38 +00:00
Taus
bac48b4914 Python: Fix exception issue
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:38 +00:00
Taus
852aba880d Python: Fix match
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:38 +00:00
Taus
356907990a Python: Support match
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:38 +00:00
Taus
024702e019 Python: More nodes
Not entirely sure about the `else:` blocks.

Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:37 +00:00
Taus
98637bcdc7 Python: Comprehensions
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:37 +00:00
Taus
abd7c2989d Python: Add with
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:37 +00:00
Taus
6573eed42b Python: More simple statements
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:37 +00:00
Taus
fc3940fb5d Python: assignments
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:37 +00:00
Taus
319e49b955 Python: Attributes
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:37 +00:00
Taus
da663da87b Python: Function calls
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:37 +00:00
Taus
5680477179 Python: Assert statements
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:37 +00:00
Taus
2b3df57eea Python: Support various literals
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:37 +00:00
Taus
75a3168c09 Python: Ignore synthetic CFG nodes
We can only annotate the ones that correspond directly to AST nodes
anyway.

Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:37 +00:00
Taus
2f2c071920 Python: More AstNodeImpl improvements
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:36 +00:00
Taus
49c38dddb7 Python: Instantiate CFG tests with new CFG library
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:36 +00:00
Taus
28ebe21337 Python: Instantiate CFG module fully
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:36 +00:00
Taus
5519570157 Python: Use fields everywhere in new AST classes
Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:36 +00:00
Taus
53f34376c0 Python: First stab at shared control-flow 2026-05-26 16:32:36 +00:00
Taus
166b3226ac Python: Make CFG tests parameterised
Currently we only instantiate them with the old CFG library, but in the
future we'll want to do this with the new library as well.

Co-authored-by: yoff <yoff@github.com>
2026-05-26 16:32:36 +00:00
Taus
66bdd22a14 Python: Add ConsecutiveTimestamps test
This one is potentially a bit iffy -- it checks for a very powerful
propetry (that implies many of the other queries), but as the test
results show, it can produce false positives when there is in fact no
problem. We may want to get rid of it entirely, if it becomes too noisy.
2026-05-26 16:32:36 +00:00
Taus
e21b6b9b2e Python: Add NeverReachable test
This looks for nodes annotated with `t.never` in the test that are
reachable in the CFG. This should not happen (it messes with various
queries, e.g. the "mixed returns" query), but the test shows that in a
few particular cases (involving the `match` statement where all cases
contain `return`s), we _do_ have reachable nodes that shouldn't be.
2026-05-26 16:32:36 +00:00
Taus
500dec3f67 Python: Add BasicBlockOrdering test
This one demonstrates a bug in the current CFG. In a dictionary
comprehension `{k: v for k, v in d.items()}`, we evaluate the value
before the key, which is incorrect. (A fix for this bug has been
implemented in a separate PR.)
2026-05-26 16:32:36 +00:00
Taus
29ce07c204 Python: Add some CFG-validation queries
These use the annotated, self-verifying test files to check various
consistency requirements.

Some of these may be expressing the same thing in different ways, but
it's fairly cheap to keep them around, so I have not attempted to
produce a minimal set of queries for this.
2026-05-26 16:32:36 +00:00
Taus
6e77a45fb3 Python: Add self-validating CFG tests
These tests consist of various Python constructions (hopefully a
somewhat comprehensive set) with specific timestamp annotations
scattered throughout. When the tests are run using the Python 3
interpreter, these annotations are checked and compared to the "current
timestamp" to see that they are in agreement. This is what makes the
tests "self-validating".

There are a few different kinds of annotations: the basic `t[4]` style
(meaning this is executed at timestamp 4), the `t.dead[4]` variant
(meaning this _would_ happen at timestamp 4, but it is in a dead
branch), and `t.never` (meaning this is never executed at all).

In addition to this, there is a query, MissingAnnotations, which checks
whether we have applied these annotations maximally. Many expression
nodes are not actually annotatable, so there is a sizeable list of
excluded nodes for that query.
2026-05-26 16:32:35 +00:00
Óscar San José
491c373e07 Merge pull request #21864 from github/post-release-prep/codeql-cli-2.25.5
Post-release preparation for codeql-cli-2.25.5
2026-05-22 17:41:38 +02:00
Óscar San José
996e79131e Merge branch 'main' into post-release-prep/codeql-cli-2.25.5 2026-05-22 16:32:30 +02:00
Tom Hvitved
688695cd57 Merge pull request #21876 from hvitved/dense-rank-short-circuit
Util: Short-circuit `rank` usage in dense ranking library
2026-05-22 16:08:45 +02:00
Jeroen Ketema
3c4e22a8ba Merge pull request #21870 from jketema/jketema/generated
C++: Add ability to see if one template was generated from another
2026-05-22 15:46:06 +02:00
Tom Hvitved
c70007607a Merge pull request #21850 from hvitved/type-inference-unify-base-type
Type inference: Unify `getABaseTypeMention` and `conditionSatisfiesConstraint`
2026-05-22 13:44:18 +02:00
Tom Hvitved
9685755479 Merge pull request #21865 from hvitved/csharp/compilation-cwd-folder
C#: Ensure that `Folder` entities exist for `Compilation` entities
2026-05-22 13:42:35 +02:00
Mathias Vorreiter Pedersen
a7405bddaa Merge pull request #21856 from MathiasVP/scanf-safe-functions
C++: Model secure versions of `scanf` as flow sources
2026-05-22 12:34:54 +01:00
Jeroen Ketema
8ad461be98 C++: Add change note 2026-05-22 13:13:27 +02:00
Jeroen Ketema
0e6257de2d C++: Fix QLDoc wording 2026-05-22 13:13:25 +02:00
Jeroen Ketema
77f6caca00 C++: Update stats file 2026-05-22 13:13:24 +02:00
Jeroen Ketema
f98dfcd0a5 C++: Add upgrade and downgrade scripts 2026-05-22 13:13:22 +02:00
Jeroen Ketema
a027665ab4 C++: Add ability to see if one template was generated from another 2026-05-22 13:13:21 +02:00
Óscar San José
de1cb26a93 Merge pull request #21890 from github/codeql-spark-run-26283874463
Update changelog documentation site for codeql-cli-2.25.5
2026-05-22 13:11:25 +02:00
github-actions[bot]
9599f01ae0 update codeql documentation 2026-05-22 11:02:30 +00:00
Michael Nebel
5a219d1527 Merge pull request #21845 from michaelnebel/csharp/unaryoperatorcleanup
C#: Unary expression cleanup in the extractor.
2026-05-22 11:06:02 +02:00
Tom Hvitved
ec7e38cd4d C#: Ensure that Folder entities exist for Compilation entities 2026-05-22 11:03:15 +02:00
Michael Nebel
871f307fa4 Merge pull request #21871 from michaelnebel/csharp14/updatedocumentation
C# 14: Update documentation and claim C# 14 / .NET 10 support.
2026-05-22 10:54:36 +02:00
Tom Hvitved
3ee45ff4b9 Apply suggestion from @geoffw0
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2026-05-22 10:07:52 +02:00
Tom Hvitved
6d6e9c0d47 Util: Only compute dense ranks when needed 2026-05-22 08:59:01 +02:00
Owen Mansel-Chan
0ef59dffb4 Merge pull request #21852 from knewbury01/knewbury01/adjust-actions-queries-untrusted-checkout-second-iteration
Actions: Improve actions/ql/src/Security/CWE-829/UntrustedCheckoutX queries further iteration
2026-05-21 17:20:33 +01:00
Kristen Newbury
5503140318 Merge branch 'main' into knewbury01/adjust-actions-queries-untrusted-checkout-second-iteration 2026-05-21 10:49:36 -04:00
Kristen Newbury
a094a8e460 Fix merge conflicts 2026-05-21 10:48:24 -04:00
Kristen Newbury
2f8c0df537 Address review feedback 2026-05-21 10:40:52 -04:00
Óscar San José
c25398ea0c Merge pull request #21868 from github/copilot/bump-jackson-core-to-2150
Bump jackson-core to 2.18.6 in ferstl-depgraph-dependencies (CVE-2025-52999)
2026-05-21 16:18:15 +02:00
Owen Mansel-Chan
7e6b10e8cf Merge pull request #21879 from owen-mc/shared/cfg/simpleleafnode
Shared CFG: update `simpleLeafNode` to exclude those with additional leaf nodes
2026-05-21 14:58:04 +01:00
Owen Mansel-Chan
149bfd19d3 Merge pull request #21880 from owen-mc/shared/cfg/for-loop-stmt-init-update
Shared CFG: Make the init and update parts of a for loop statements
2026-05-21 14:57:44 +01:00
Paolo Tranquilli
153fbb0378 Merge pull request #21878 from github/redsun82/windows-diagnostic-path-tests
Add Windows file path tests for `relativize_for_diagnostic`
2026-05-21 15:30:25 +02:00
Owen Mansel-Chan
039b5927f0 C#: update ForStmt wrapper class 2026-05-21 13:45:30 +01:00
Owen Mansel-Chan
2070dafeb2 Java: add ForStmt wrapper class 2026-05-21 13:41:29 +01:00
Owen Mansel-Chan
c3bafc75ab Shared CFG: allow statements for init and update of for loop 2026-05-21 13:40:26 +01:00
Owen Mansel-Chan
19f93cd18b Shared CFG: update simpleLeafNode to exclude those with additional nodes 2026-05-21 13:31:56 +01:00
Paolo Tranquilli
39becfd7e5 Add Windows file path tests for relativize_for_diagnostic
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-21 14:08:50 +02:00
copilot-swe-agent[bot]
0f3c9ab483 Fix remaining macOS bash 3.2 portability issues in update script (step 5) 2026-05-21 12:07:45 +00:00
Paolo Tranquilli
a84043b627 Merge pull request #21844 from github/redsun82/issue-21802-ruby-absolute-paths-in-sarif-diagnostics-a02887
Use relative paths in tree-sitter extractor diagnostics
2026-05-21 14:00:32 +02:00
Owen Mansel-Chan
2280955136 Merge pull request #21800 from knewbury01/knewbury01/adjust-actions-queries-untrusted-checkout-critical-alert
Actions: Adjust alert location UntrustedCheckoutCritical
2026-05-21 12:40:29 +01:00
Owen Mansel-Chan
4897757b96 Merge pull request #21875 from github/workflow/coverage/update
Update CSV framework coverage reports
2026-05-21 11:09:26 +01:00
copilot-swe-agent[bot]
8170c207bd Fix macOS bash 3.2 heredoc-in-$() portability issue in update script 2026-05-21 09:57:10 +00:00
copilot-swe-agent[bot]
38a2101e11 update-ferstl-depgraph-dependencies.sh: address review feedback
- Use BUILD_REPO/DIST_REPO split so zip contains only runtime deps
  (build-lifecycle plugins, test jars, etc. stay in throwaway BUILD_REPO)
- Minimal inline stub pom.xml (no deps) instead of archetype:generate
  to avoid polluting DIST_REPO with stub project's own dependencies
- Replace grep -oP (PCRE, unavailable on macOS BSD grep) with Python re
- Use version-aware Python version_key() for max POM version selection
  (lexicographic sort fails for e.g. 2.18.10 vs 2.18.6; release > snapshot)
- Write zip to caller's working directory; keep cleanup trap active;
  remove `trap - EXIT` which was leaving WORK_DIR behind
2026-05-21 09:41:57 +00:00
github-actions[bot]
fb04cd2212 Add changed framework coverage reports 2026-05-21 00:54:55 +00:00
Mathias Vorreiter Pedersen
a33af09244 C++: Add models for _fscanf_s_l, fwscanf_s and _fwscanf_s_l. 2026-05-20 18:59:04 +01:00
Mathias Vorreiter Pedersen
25d20399f3 C++: Add models for _scanf_s_l, wscanf_s and _wscanf_s_l. 2026-05-20 18:43:07 +01:00
Mathias Vorreiter Pedersen
e6c5f944ba C++: Add missing format string part in test. 2026-05-20 18:13:35 +01:00
Mathias Vorreiter Pedersen
157424cca3 Merge pull request #21836 from MathiasVP/uncertain-def-more-complete
C++: Support reasoning about whether a phi node overwrites the entire buffer
2026-05-20 13:04:37 +01:00
Óscar San José
b9bf81e463 Merge branch 'main' into copilot/bump-jackson-core-to-2150 2026-05-20 13:09:04 +02:00
Michael Nebel
e408540d36 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-20 11:08:41 +02:00
Michael Nebel
462a7bc423 C#: Add change-note. 2026-05-20 10:59:52 +02:00
Michael Nebel
422a6bd670 C#: Remove the prelim C# 14 footnote from the documentation. 2026-05-20 10:59:10 +02:00
Jack Nørskov Jørgensen
4b095f3129 Merge pull request #21754 from github/jacknojo/add_llm_generated_mads_for_avro
Add MaDs for Apache Avro
2026-05-20 08:24:06 +02:00
Geoffrey White
3aa660663e Merge pull request #21806 from geoffw0/extsensitive
Shared: Improvements to SensitiveDataHeuristics.qll
2026-05-19 16:22:03 +01:00
Paolo Tranquilli
c1e26f9ea5 Merge pull request #21847 from github/redsun82/redsun82-python-absolute-paths-in-diagno
Python extractor: use relative paths in diagnostic locations
2026-05-19 17:03:35 +02:00
Mathias Vorreiter Pedersen
f5113b1932 C++: Fix internal SCC edges and accept test changes. 2026-05-19 15:39:32 +01:00
Mathias Vorreiter Pedersen
f77d426706 C++: Add test demonstrating broken phi cycle certain'ness. 2026-05-19 15:35:20 +01:00
Mathias Vorreiter Pedersen
c6ce13a012 C++: Simplify recursion in 'PhiCycle::isCertain' and do not restrict the definition to be a 'PhiNode'. 2026-05-19 15:27:23 +01:00
Kristen Newbury
bfc6deeb9b Adjust wording helpfiles UntrustedCheckoutX all three files 2026-05-19 10:19:00 -04:00
Kristen Newbury
0a876583e5 Adjust name UntrustedCheckoutHigh wording trusted to privileged 2026-05-19 10:12:04 -04:00
Jack Nørskov Jørgensen
aa136a3282 Add change note entry 2026-05-19 16:09:05 +02:00
Óscar San José
8b799f84ed Do not remove zip file if the process succeeds 2026-05-19 14:30:50 +02:00
Michael Nebel
30a5769e20 C#: Simplify and streamline the implementation of Prefix and Postfix unary expressions. 2026-05-19 14:20:53 +02:00
Michael Nebel
a72cef6fda C#: Rename Unary to PrefixUnary. 2026-05-19 14:20:50 +02:00
Michael Nebel
dc80a029cb C#: Streamline the AddOperatorCall logic for prefix and postfix unary operators. 2026-05-19 14:20:44 +02:00
Michael Nebel
49a435c402 Merge pull request #21827 from michaelnebel/csharp14/userincrementdecrement
C# 14: User increment/decrement support.
2026-05-19 14:18:08 +02:00
Jeroen Ketema
96ef59a22a Merge pull request #21861 from jketema/jketema/swift-6.3.2
Swift: Update to Swift 6.3.2
2026-05-19 14:01:25 +02:00
copilot-swe-agent[bot]
b1615312b8 Bump jackson-core to 2.18.6 in ferstl-depgraph-dependencies (CVE-2025-52999)
- Update 3 maven-fetches.expected files: jackson 2.14.1→2.18.6,
  jackson-parent 2.14→2.18.4, oss-parent 48→69,
  plugin version 4.0.3-CodeQL→4.0.3-CodeQL-2
- Update 2 diagnostics.expected files: plugin version reference
  4.0.3-CodeQL→4.0.3-CodeQL-2
- Add update-ferstl-depgraph-dependencies.sh auto-update script
2026-05-19 11:52:46 +00:00
copilot-swe-agent[bot]
63a09484a0 Initial plan 2026-05-19 11:44:18 +00:00
Michael Nebel
7a1a90b5a4 C#: Address review comment. 2026-05-19 13:23:22 +02:00
Paolo Tranquilli
06c908756f Merge branch 'main' into redsun82/issue-21802-ruby-absolute-paths-in-sarif-diagnostics-a02887 2026-05-19 13:17:23 +02:00
Mathias Vorreiter Pedersen
d93de54397 C++: Consistent use of 'this.getIndirection()' in 'toString'. 2026-05-19 12:16:37 +01:00
Paolo Tranquilli
adf59f3ee5 Merge branch 'main' into redsun82/redsun82-python-absolute-paths-in-diagno 2026-05-19 13:09:04 +02:00
Jeroen Ketema
22a8123ee1 Merge pull request #21860 from jketema/jketema/alias-template
C++: Support alias templates
2026-05-19 10:46:56 +02:00
Jack Nørskov Jørgensen
3119ef6c1a Add MaDs for Apache Avro 2026-05-19 09:27:32 +02:00
Jeroen Ketema
01ff9aa91f Swift: Update to Swift 6.3.2 2026-05-19 06:50:59 +02:00
Mathias Vorreiter Pedersen
0633bc7b91 Merge pull request #21862 from MathiasVP/more-fopen-models
C++: Add two more `fopen`-like models.
2026-05-18 22:43:48 +01:00
Owen Mansel-Chan
ad69cfb721 Merge pull request #21838 from github/copilot/widen-regex-for-pinned-actions
Align `alphaNumericRegex()` with the documented grouped SHA pattern
2026-05-18 17:35:27 +01:00
github-actions[bot]
9f64000962 Post-release preparation for codeql-cli-2.25.5 2026-05-18 15:20:31 +00:00
Mathias Vorreiter Pedersen
2c156994de C++: Add two more 'fopen'-like models. 2026-05-18 14:47:11 +01:00
Mathias Vorreiter Pedersen
19781e53e7 C++: Add change notes. 2026-05-18 14:06:21 +01:00
Mathias Vorreiter Pedersen
5f10a88208 C++: Handle size arguments in 'getOutputArgument'. 2026-05-18 14:06:18 +01:00
Mathias Vorreiter Pedersen
5add24be59 C++: Add scanf_s models. 2026-05-18 14:06:16 +01:00
Mathias Vorreiter Pedersen
16235d7aca C++: Add a 'call' column to 'hasRemoteFlowSource' and 'hasLocalFlowSource' to support modeling of 'scanf_s'. 2026-05-18 14:06:05 +01:00
Jeroen Ketema
5f6553490c Update cpp/ql/lib/change-notes/2026-05-16-alias-template.md 2026-05-18 15:04:52 +02:00
Jeroen Ketema
d14b8064b0 Update cpp/ql/lib/semmle/code/cpp/TypedefType.qll 2026-05-18 15:04:03 +02:00
Jeroen Ketema
7636bf560e Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-18 15:02:34 +02:00
Michael Nebel
9b2b5971fe Merge pull request #21846 from michaelnebel/csharp/updateextractordependencies
C# 14: Update paket and dependencies.
2026-05-18 14:25:55 +02:00
Jeroen Ketema
c2e2770bbf C++: Simplify type alias class naming 2026-05-18 14:22:04 +02:00
Óscar San José
b551e89ea8 Merge pull request #21859 from github/release-prep/2.25.5
Release preparation for version 2.25.5
2026-05-18 14:10:35 +02:00
github-actions[bot]
e38616a2ef Release preparation for version 2.25.5 2026-05-18 12:05:32 +00:00
Jeroen Ketema
e55edf2f1f Merge pull request #21853 from jketema/jketema/template-constants
C++: Update test results after extractor changes
2026-05-18 13:43:54 +02:00
Óscar San José
8a199f963d Merge pull request #21692 from github/copilot/update-codeql-query-for-composite-actions
Extend `actions/unpinned-tag` to analyze composite action metadata (`action.yml` / `action.yaml`)
2026-05-18 12:17:13 +02:00
Mathias Vorreiter Pedersen
2902a19a50 C++: Add more scanf testing. 2026-05-18 10:58:50 +01:00
Mathias Vorreiter Pedersen
fcdce550e8 Merge pull request #21857 from MathiasVP/fix-cleartext-fp
C++: Fix FP on `cpp/cleartext-transmission`
2026-05-18 10:58:13 +01:00
Jeroen Ketema
76f71dd235 Merge pull request #21817 from jketema/go-version
Go: Make version parsing robust in the face of custom Go builds
2026-05-18 10:45:55 +02:00
Tom Hvitved
7f1bebe8ba Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-17 20:29:19 +02:00
Jeroen Ketema
305a63bc38 C++: Update dbscheme stats 2026-05-16 16:10:27 +02:00
Jeroen Ketema
963715884e C++: Add change note 2026-05-16 11:50:00 +02:00
Jeroen Ketema
b6847974f7 C++: Add upgrade and downgrade scripts 2026-05-16 09:26:08 +02:00
Jeroen Ketema
336bbc229e C++: Add support for alias templates
Add other missing cases to `isFromTemplateInstantiationRec` and
`isFromUninstantiatedTemplateRec` while here.
2026-05-16 09:11:54 +02:00
Mathias Vorreiter Pedersen
8ce601b1d7 C++: Add change notes. 2026-05-15 21:22:38 +01:00
Mathias Vorreiter Pedersen
4396e66f35 C++: Fix FP by providing an implementation of 'hasSocketInput'. 2026-05-15 21:12:34 +01:00
Mathias Vorreiter Pedersen
eda33adafd C++: Add FP. 2026-05-15 21:07:45 +01:00
Geoffrey White
a4b2c0f6fd Update change notes (Copilot's suggestions). 2026-05-15 09:24:29 +01:00
Kristen Newbury
3eaf04ef72 Fix expected files for changes to alert messages UntrustedCheckoutCritical and UntrustedCheckoutHigh 2026-05-14 15:05:08 -04:00
Jeroen Ketema
d47ee6bed9 C++: Update test results after extractor changes 2026-05-14 20:22:47 +02:00
Kristen Newbury
914c7e1a7b Improve UntrustedCheckoutX helpfiles 2026-05-14 13:34:59 -04:00
Kristen Newbury
29ffd87bf8 Add full stop to alert messages in UntrustedCheckoutHigh and UntrustedCheckoutCritical 2026-05-14 12:58:20 -04:00
Kristen Newbury
eae9c0ef0e Add one missing changenote actions-queries-untrusted-checkout 2026-05-14 12:06:55 -04:00
Kristen Newbury
c36ad7be37 Adjust untrusted checkout actions queries 2026-05-14 11:59:55 -04:00
Florin Coada
a84332ac15 Merge pull request #21727 from github/docs/customizing-library-models-for-rust
docs: Add 'Customizing library models for Rust' documentation
2026-05-14 15:04:12 +01:00
Geoffrey White
59dbd68a5e Add change notes. 2026-05-14 14:46:05 +01:00
Tom Hvitved
3f7b50ebba Type inference: Unify getABaseTypeMention and conditionSatisfiesConstraint 2026-05-13 16:24:36 +02:00
Owen Mansel-Chan
0c274849be Merge pull request #21842 from github/workflow/coverage/update
Update CSV framework coverage reports
2026-05-13 13:48:35 +01:00
Owen Mansel-Chan
b49b8ff6bd Give slightly more detail in change note 2026-05-13 13:47:53 +01:00
Mathias Vorreiter Pedersen
25c4d9d09b Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-13 13:27:04 +01:00
Mathias Vorreiter Pedersen
07b8d7eba7 C++: Accept test changes in experimental query. 2026-05-13 13:14:25 +01:00
Mathias Vorreiter Pedersen
f40d42c575 C++: Perform an SCC reduction to simulate greatest fixed-point semantics. 2026-05-13 13:14:20 +01:00
Mathias Vorreiter Pedersen
8585bb616d C++: Some writes are always certain regardless of the address. 2026-05-13 13:14:13 +01:00
Mathias Vorreiter Pedersen
fc80a2472d C++: Slightly refactor certainty computation with a newtype. 2026-05-13 13:09:12 +01:00
Mathias Vorreiter Pedersen
6d5d57acca C++: Add missing overrides. 2026-05-13 13:09:10 +01:00
Mathias Vorreiter Pedersen
e77d85f23e C++: Add a new test to test assignment certainty (i.e., whether the entire buffer is overwritten). 2026-05-13 13:09:08 +01:00
Mathias Vorreiter Pedersen
b753e7d228 C++: Make 'toString' on 'Ssa::Definition' more clear. 2026-05-13 13:09:01 +01:00
Mathias Vorreiter Pedersen
8e25240282 C++: Add a FP caused by missing certainty around SSA writes from Uninitialized instructions. 2026-05-13 13:07:56 +01:00
Geoffrey White
c8196e439f Merge branch 'main' into extsensitive 2026-05-13 13:04:48 +01:00
Michael Nebel
c8efc34e8b C#: Update the generated lock, targets and bzl files. 2026-05-13 13:02:14 +02:00
Florin Coada
ab0b492429 Merge branch 'main' into docs/customizing-library-models-for-rust 2026-05-13 11:45:11 +01:00
Florin Coada
8abd3b93c9 Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2026-05-13 11:44:43 +01:00
Paolo Tranquilli
ee13ea0f6b Harden _relative_path for Windows and mixed-form inputs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 11:35:02 +02:00
Paolo Tranquilli
d28792537b Python extractor: use relative paths in diagnostic locations
Diagnostic `Location.file` fields contained absolute filesystem paths,
causing the GitHub UI to generate broken file links with runner paths
like `/home/runner/work/...`. Now paths are relativized against the
source root (`LGTM_SRC` or cwd), falling back to absolute if the file
is outside the source root.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 10:32:05 +02:00
Paolo Tranquilli
c2fc0cf111 Fix Windows path handling in diagnostic relativization
Canonicalize `current_dir()` to match canonicalized file paths (avoids
`\\?\` prefix mismatch on Windows), and normalize backslashes to
forward slashes in relative diagnostic paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 10:31:48 +02:00
Paolo Tranquilli
c3cf7c2bca Use absolute path fallback instead of file: URI
Drop the `url` crate dependency. When a path can't be relativized
against the source root, emit it as a bare absolute path and let the
CLI's SARIF generator handle URI conversion downstream.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 10:28:27 +02:00
Michael Nebel
1e6570ec97 C#: Update paket to 10.3.1. 2026-05-13 10:22:45 +02:00
Asger F
cfa175357b Merge pull request #21815 from asgerf/asgerf/missing-node-kind-error
Shared: Nicer panic message if node kind is missing
2026-05-13 10:11:14 +02:00
Paolo Tranquilli
57ac0192c0 Fix formatting
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 09:48:45 +02:00
Paolo Tranquilli
d16bc36e83 Use relative paths in tree-sitter extractor diagnostics
Diagnostic `location.file` entries were using absolute paths (e.g.
`/home/runner/work/...`), causing broken links in the GitHub UI.
Now relativize against CWD (the source root during extraction), falling
back to a properly percent-encoded `file:` URI for paths outside it.

Fixes https://github.com/github/codeql/issues/21802

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 09:45:37 +02:00
Michael Nebel
fa2d633596 C#: Address co-pilot review comments. 2026-05-13 09:24:59 +02:00
Michael Nebel
5ed3014f7d C#: Add change-note. 2026-05-13 09:24:56 +02:00
Michael Nebel
4bd9005f9a C#: Add data flow testcases for mutation operators. 2026-05-13 09:24:54 +02:00
Michael Nebel
0c3ab803ef C#: Update the dispatch logic to account for all instance operator calls. 2026-05-13 09:24:51 +02:00
Michael Nebel
27e6b5c0fa C#: Introduce a class for instance mutator operator calls. 2026-05-13 09:24:48 +02:00
Michael Nebel
23328e90d4 C#: Add extension increment/decrement examples. 2026-05-13 09:24:46 +02:00
Michael Nebel
9a805080ea C#: Improve the GetCallType method to also take extension operators into account. 2026-05-13 09:24:43 +02:00
Michael Nebel
25274a1df2 C#: Add an increment/decrement operator test case. 2026-05-13 09:24:40 +02:00
Michael Nebel
1c50c0c2c6 C#: Update PrintAst expected output. 2026-05-13 09:24:37 +02:00
Michael Nebel
4ae4d7d78d C#: Update condition for UnaryOperators to also handle user-defined instance increment and decrement operators. 2026-05-13 09:24:35 +02:00
Michael Nebel
3c9d89851d C#: Adjust the extractor to correctly handle names for user defined increment and decrement operators. 2026-05-13 09:24:32 +02:00
Michael Nebel
ac7eb01817 C#: Add Increment/Decrement instance operator test example and update test expected output. 2026-05-13 09:24:29 +02:00
github-actions[bot]
b0e23a73d2 Add changed framework coverage reports 2026-05-13 00:50:12 +00:00
Owen Mansel-Chan
ea29986c4f Fix non-US english by using "parentheses" instead of "brackets"
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-12 22:40:03 +01:00
Owen Mansel-Chan
f58268064e Add change note for alphanumeric regex change 2026-05-12 22:40:03 +01:00
Owen Mansel-Chan
2067113177 Update expected test output 2026-05-12 22:40:03 +01:00
copilot-swe-agent[bot]
562f415f64 Tidy Bash alphaNumericRegex comment spacing 2026-05-12 22:40:03 +01:00
copilot-swe-agent[bot]
0620d348b2 Update Bash alphaNumericRegex to match grouped quantified forms 2026-05-12 22:40:03 +01:00
copilot-swe-agent[bot]
48b1dad959 Add change note for SHA-256 pinned actions support 2026-05-12 22:40:03 +01:00
copilot-swe-agent[bot]
ef1bde7565 Widen pinned SHA regex to support SHA-256 (64-char hex) and add tests 2026-05-12 22:40:03 +01:00
Owen Mansel-Chan
0b808e1170 Merge pull request #21807 from owen-mc/java/improve-qhelp-unsafe-deserialization
Shared: improve qhelp for unsafe deserialization queries
2026-05-12 22:22:49 +01:00
Taus
5508b1576f Merge pull request #21821 from github/tausbn/unified-swift-grammar-cleanup-phase-1
unified: Swift grammar cleanup part 1
2026-05-12 16:12:09 +02:00
Taus
911e59caef unified: regenerate files 2026-05-12 12:57:26 +00:00
Taus
ff5c0b40f1 unified: add supertypes for various kinds of declarations
Hides a bunch of huge unions under (hopefully) sensible supertypes.
2026-05-12 12:57:26 +00:00
Taus
a5a1312e51 unified: regenerate files 2026-05-12 12:57:25 +00:00
Taus
2608db9fd9 unified: Prevent field bleed-through from _if_let_binding
Same procedure as before -- we change the anonymous node to a named
node, and the problem magically goes away.
2026-05-12 12:57:25 +00:00
Taus
f9e7f90896 unified: regenerate files 2026-05-12 12:57:25 +00:00
Taus
31386f566c unified: drop element field on _parenthesized_type
Same pattern we've seen many times before: a field on an anonymous node
gets attached to the parent node instead.

I'm not 100% sure this is the right solution, but it seemed wrong to
just make `_parenthesized_type` named instead (we don't usually name
parentheticals). At the very least, this cleans up the spurious
navigation_expression.element and tuple_type_item.element fields.
2026-05-12 12:57:25 +00:00
Taus
e9822f67ee unified: regenerate files 2026-05-12 12:57:25 +00:00
Taus
994b27bdbd unified: convert _type into a named rule
Because `_type` was anonymous, its body was inlined in all of the places
it appeared. Because this body contained a `name` field, this field was
_also_ inlined. This caused a bunch of nodes to have spurious `name`
fields, and for some of them (that already had such a field) it caused
that field have multiplicity greater than one.

To fix this, we make the `_type` node named, which prevents the errant
field from escaping.
2026-05-12 12:57:25 +00:00
Taus
a720e258ac unified: regenerate files 2026-05-12 12:57:25 +00:00
Taus
8b977ef8e1 unified: Get rid of some "." bleed
Adds a new type `nested_type_identifier`, which contains the
choice-branch that previously allowed those tokens to bleed through into
the closest parent field.
2026-05-12 12:57:25 +00:00
Taus
caa9b04ad8 unified: regenerate files 2026-05-12 12:57:25 +00:00
Taus
91a46f0340 unified: stop "!" bleeding through
You know the drill. We just make an anonymous node named instead. In
this case, however, we have to be a bit more clever about how to rewrite
it. We turn the sequence of a type followed by an optional ! into a
_choice_ between mere type or type followed by bang (the latter being
our new named node).
2026-05-12 12:57:24 +00:00
Taus
37e1e3c879 unified: regenerate files 2026-05-12 12:57:24 +00:00
Taus
70f3fd1158 unified: make unannotated_type named and supertype
Gets rid of a bunch of ad-hoc node type unions.
2026-05-12 12:57:24 +00:00
Taus
9abfaca98c unified: regenerate files 2026-05-12 12:57:24 +00:00
Taus
38473f9e0b unified: make expression named and a supertype
Supertypes are a honking great idea. We should use more of them.

This massively cleans up the node types, without polluting the AST with
`expression` nodes.
2026-05-12 12:57:24 +00:00
Taus
c7c6e45254 unified: regenerate files 2026-05-12 12:57:24 +00:00
Taus
c0efc52cc7 unified: make if-condition nodes named, to stop bleed
Before, the `condition` field of an if statement supposedly could
contain things like parentheses and commas, due to bleeding from
referenced anonymous nodes. Making the node named makes this issue go
away.
2026-05-12 12:57:24 +00:00
Taus
5c16b0faf9 unified: regenerate files 2026-05-12 12:57:24 +00:00
Taus
7854a534fd unified: stop operators bleeding through everywhere
We make _referenceable_operator a named node. This prevents it from
bleeding through to the _expression definition. It likely also makes the
output easier to deal with, as bare operators used as arguments now have
a named node wrapping them in the AST.

Also removes a duplicated inclusion of _comparison_operator that served
no purpose.
2026-05-12 12:57:24 +00:00
Taus
76a1a87c41 unified: regenerate files 2026-05-12 12:57:23 +00:00
Taus
9062bba168 unified: get rid of undesirable self-recursion in _expression
This caused any field containing an _expression to appear as if it could
countain any number of such nodes. It also threw away the information
that there was a `?` marker there.

To fix it, we simply move the definition into its own named node.
2026-05-12 12:57:23 +00:00
Taus
e709650449 unified: Rebuild generated files
The astute reader will note that we seem to _lose_ some node types in
the process. Apparently, these were unreachable in the grammar, and the
newer version of tree-sitter removes such "dead code".
2026-05-12 12:57:23 +00:00
Taus
513c7bb30b unified: Add scripts for automatically rebuilding Swift grammar 2026-05-12 12:57:23 +00:00
Taus
9c958a420a Merge pull request #21819 from github/tausbn/unified-vendor-in-tree-sitter-swift
unified: use a vendored-in copy of tree-sitter-swift
2026-05-12 14:55:35 +02:00
Taus
2e9de7878b unified: update build dependencies 2026-05-12 11:25:15 +00:00
Taus
c5ae315dbe unified: auto-generate parser files
Uses the `tree-sitter-generate` crate to generate these files on the
fly.
2026-05-12 11:24:35 +00:00
Owen Mansel-Chan
592c7c0437 Merge pull request #21826 from AriehSchneier/fix/go-extractor-root-test-files
Go: Fix extractor to extract root internal test files
2026-05-12 10:34:42 +01:00
Owen Mansel-Chan
c0798f7b1d Merge pull request #21829 from owen-mc/static/update-framework-report-sink-kinds
C#, Go, Java: Use all path injection sinks when generating docs
2026-05-12 10:16:31 +01:00
Geoffrey White
51dae161a7 Merge branch 'main' into extsensitive 2026-05-12 09:29:32 +01:00
Jeroen Ketema
cac7262a45 Merge pull request #21831 from jketema/jketema/swift-declared-interface-type
Swift: Expose the declared interface type of a type decl
2026-05-12 09:47:39 +02:00
Owen Mansel-Chan
6b65866ff4 Merge branch 'main' into fix/go-extractor-root-test-files 2026-05-11 17:18:43 +01:00
Jeroen Ketema
73a210a442 Swift: Add change note 2026-05-11 17:24:09 +02:00
Owen Mansel-Chan
0aaa7d0631 Update expected test output 2026-05-11 16:15:50 +01:00
Jeroen Ketema
f212efbe5b Swift: Expose the declared interface type of a type decl 2026-05-11 17:05:45 +02:00
Arieh Schneier
aa1d322fe7 Address PR feedback
Changes based on code review:

1. Remove redundant strings.Contains check in isExactTestPackage
   The equality check on the next line handles both cases, making
   the early return unnecessary.

2. Extract package selection logic into selectBestPackages function
   This reduces code duplication and allows the test to call the
   actual implementation rather than copying the logic.

3. Add TestSelectBestPackages to test the new function
   Comprehensive test covering single packages, test vs production,
   exact vs nested tests, and multiple packages.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-11 21:07:39 +10:00
Arieh Schneier
151a332f0a Add Bazel build target for extractor_test.go
Generated by manually applying the output from CI's Gazelle check.
This adds the go_test target for the new extractor_test.go file.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-11 20:55:11 +10:00
Owen Mansel-Chan
974e7cc319 Merge pull request #21825 from github/dependabot/go_modules/go/extractor/extractor-dependencies-0e0a523006
Bump the extractor-dependencies group in /go/extractor with 2 updates
2026-05-11 11:35:14 +01:00
Asger F
f91482810d Merge pull request #21816 from github/tausbn/yeast-mutate-in-place
yeast: Two minor performance optimisations
2026-05-11 11:08:24 +02:00
Owen Mansel-Chan
ec8ff6ff68 Use all path injection sinks when generating docs 2026-05-11 09:56:02 +01:00
Geoffrey White
af0124f0f1 Merge branch 'main' into extsensitive 2026-05-11 09:47:29 +01:00
Arieh Schneier
b94ab8d186 Add integration test for root internal test extraction
This test verifies that root internal test files (package foo, not
foo_test) are correctly extracted when the repository has both:
1. Root-level internal tests (main_test.go with package main)
2. Nested packages with tests (nested/nested_test.go)

This scenario reproduces the bug that was fixed: the old extractor
would select the wrong package variant and miss root internal test
files.

The test ensures:
- main_test.go (root internal test) is extracted
- nested/nested_test.go (nested test) is extracted
- All test functions from both files are present in the database

This prevents regression of the bug fix.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-11 15:18:15 +10:00
Arieh Schneier
3ef4a5836c Fix Go extractor to extract root internal test files
When CODEQL_EXTRACTOR_GO_OPTION_EXTRACT_TESTS=true is set, the Go
extractor was incorrectly skipping internal test files (package foo)
at repository roots when the project contains nested test packages.

Root Cause:
The extractor selected package variants by longest ID string, but this
heuristic fails when nested packages have tests. For a package like
"github.com/go-git/go-git/v6", packages.Load returns multiple variants:

1. "github.com/go-git/go-git/v6" (19 files, production only)
2. "github.com/go-git/go-git/v6 [github.com/go-git/go-git/v6.test]"
   (39 files, production + 20 root tests) ← Should select this
3. "github.com/go-git/go-git/v6 [github.com/go-git/go-git/v6/plumbing/format/packfile.test]"
   (19 files, test dependency) ← Was incorrectly selected (longest string)

The old logic selected variant #3 (76 chars) over #2 (68 chars),
causing 20 root test files to be missing from the database.

Fix:
Replace string length comparison with a better heuristic that prefers:
1. Exact test packages (e.g., "pkg [pkg.test]") over nested dependencies
2. Packages with more Syntax nodes (more files to extract)
3. String length as a tiebreaker

This ensures the extractor selects the variant with the most complete
test coverage, particularly for root-level internal tests.

Testing:
- Added comprehensive unit tests covering the selection logic
- Tests simulate the real-world go-git scenario
- All tests pass

Impact:
Root-level external tests (package foo_test) were already extracted
correctly. This fix ensures internal tests (package foo) at the root
are now also extracted when they exist alongside nested test packages.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-11 13:42:17 +10:00
dependabot[bot]
8f9d5c5217 Bump the extractor-dependencies group in /go/extractor with 2 updates
Bumps the extractor-dependencies group in /go/extractor with 2 updates: [golang.org/x/mod](https://github.com/golang/mod) and [golang.org/x/tools](https://github.com/golang/tools).


Updates `golang.org/x/mod` from 0.35.0 to 0.36.0
- [Commits](https://github.com/golang/mod/compare/v0.35.0...v0.36.0)

Updates `golang.org/x/tools` from 0.44.0 to 0.45.0
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.44.0...v0.45.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-version: 0.36.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: extractor-dependencies
- dependency-name: golang.org/x/tools
  dependency-version: 0.45.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: extractor-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-11 03:06:30 +00:00
Taus
60d6429b5d unified: update build dependencies 2026-05-08 13:41:45 +00:00
Taus
9f6bd88171 unified: vendor in tree-sitter-swift 2026-05-08 13:41:14 +00:00
Owen Mansel-Chan
a5ef036465 Note that common standard library types can be vulnerable to gadget-chain attacks 2026-05-08 14:18:54 +01:00
Jeroen Ketema
e38303b922 Go: Make version parsing robust in the face of custom Go builds
cf. afcf04cb64/src/go/version/version.go (L20)
2026-05-08 15:15:42 +02:00
Owen Mansel-Chan
93e05db394 Python: remove doubles spaces from qhelp 2026-05-08 14:06:48 +01:00
Owen Mansel-Chan
ed9477aac9 Ruby: Clarify that deserialization following a schema is safe 2026-05-08 14:06:16 +01:00
Owen Mansel-Chan
4e47f7706d C#: Clarify that deserialization following a schema is safe 2026-05-08 14:06:07 +01:00
Owen Mansel-Chan
e2874ac252 Python: Clarify that deserialization following a schema is safe 2026-05-08 14:05:55 +01:00
Taus
15936a5f8d yeast: Take fields by ownership in apply_rules_inner
Previously, apply_rules_inner snapshotted a node's fields by cloning
the BTreeMap into a Vec<(FieldId, Vec<Id>)>, then built a fresh
BTreeMap of new_fields for the rewritten Ids. For a node with N
fields, this allocated 2N+1 things per visit (the snapshot Vec, N
cloned children Vecs, the new BTreeMap entries) — even when nothing
in the subtree was rewritten.

Use std::mem::take to swap the parent's fields out by ownership: the
recursion can mutate the AST (including pushing new nodes from rule
firings) without any conflict, since we hold the owned BTreeMap
locally. Iterate values_mut() and only allocate a fresh children Vec
on the first divergence (lazy alloc): unchanged children stay in the
existing slot. When done, swap the fields back.

For a subtree with no rewrites, this is now zero allocations per node
(modulo the recursion itself). For nodes with rewrites, it's one Vec
allocation per field that contains a rewritten child, instead of two
plus the BTreeMap rebuild.
2026-05-08 12:48:10 +00:00
Taus
7bd27b83e0 yeast: Mutate parent fields in place; remove redundant Node::id
apply_rules_inner used to handle the "child was rewritten, so the
parent needs new field IDs" case by cloning the parent node, swapping
in the new fields, pushing the clone onto the arena, and returning the
new Id. Every ancestor on the path from the rewrite up to the root was
duplicated this way, with the originals retained as garbage in the
arena.

Switch to in-place mutation: assign `ast.nodes[id].fields = new_fields`
and return the same Id. Rule firings still produce genuinely new nodes
via BuildCtx (their structure differs from the input), but the
ancestor-rebuild spine no longer copies anything.

This is safe because apply_rules_inner already works entirely by Id:
the field snapshot is cloned out before recursing, no &Node references
are held across mutations of the arena, and captures are scoped to a
single rule firing so the now-stable Ids do not break anything.

Memory effect: a desugaring pass that rewrites R leaves of a tree of
average depth d previously appended R*d ancestor clones to the arena.
Now appends 0.

With Ids stable for the lifetime of an Ast, the Node::id field becomes
truly redundant and is removed (along with the Node::id() accessor).
AstCursor switches from caching `node: &Node` to tracking `node_id:
Id` and looking the node up via the arena on each access; ChildrenIter
now yields Ids directly. A new AstCursor::node_id() method gives
callers access to the cursor position by Id.
2026-05-08 12:47:22 +00:00
Asger F
9a1c2da5d9 Fix clippy: inline variable in format string
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-08 14:22:01 +02:00
Owen Mansel-Chan
36554d160c Merge pull request #21741 from MarkLee131/fix/path-injection-read-subkind
Fix/path injection read subkind
2026-05-08 12:38:16 +01:00
Taus
5a4dee50f7 Merge pull request #21810 from github/tausbn/yeast-forward-scan-queries
yeast: Align query semantics more closely with tree-sitter
2026-05-08 13:30:43 +02:00
Asger F
638dc9380c Shared: Nicer panic message if node kind is missing
Still panics, just with a better message
2026-05-08 13:23:35 +02:00
Asger F
fdef477138 Merge pull request #21812 from asgerf/asgerf/swift-yeast-1
Add tree-sitter-swift extractor scaffolding and YEAST desugaring
2026-05-08 13:21:17 +02:00
Anders Schack-Mulligen
81e1ab7aab Merge pull request #21808 from aschackmull/cfg/switch-pattern-eval
Cfg: Rework CFG for switch case patterns.
2026-05-08 12:48:44 +02:00
Paolo Tranquilli
8cc6d788c5 Merge pull request #21814 from github/codeql-spark-run-25547718006
Update changelog documentation site for codeql-cli-2.25.4
2026-05-08 11:45:26 +02:00
github-actions[bot]
26e13055c8 update codeql documentation 2026-05-08 09:24:10 +00:00
Asger F
33e89ea123 Address review comments 2026-05-08 09:03:18 +02:00
Asger F
9a2b7bac8f Fix Bazel glob to include subdirectories
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-08 08:56:40 +02:00
Anders Schack-Mulligen
048411e168 Apply suggestions from code review
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2026-05-08 08:11:32 +02:00
Asger F
2802819170 Use new YEAST API after rebasing 2026-05-07 21:37:42 +02:00
Asger F
a1447075e8 Add AGENTS.md with build/test instructions 2026-05-07 21:35:51 +02:00
Asger F
cd457a7d6b Move Swift language into its own module 2026-05-07 21:35:50 +02:00
Asger F
4e12a8c8d2 Add basic YEAST dependency and rule 2026-05-07 21:35:48 +02:00
Asger F
0210c970f2 Add tree-sitter for Swift (called 'unified') 2026-05-07 21:35:46 +02:00
Geoffrey White
36946313d9 Shared: Autoformat. 2026-05-07 17:21:13 +01:00
MarkLee131
26af52897d Merge branch 'main' into fix/path-injection-read-subkind 2026-05-07 23:48:42 +08:00
Taus
af6e921da5 yeast: Forward-scan bare child patterns instead of strict positional
Previously, a bare child pattern in a query took whatever the next
child of the iterator was and either matched or failed: it would not
scan ahead to find a match. So `(foo ("baz"))` against a `foo` whose
implicit `child` field was `["bar", "baz"]` would fail (the pattern
took "bar" first).

Switch to forward-scan semantics: a SingleNode matcher advances through
the iterator until it finds a child that matches its sub-query. Patterns
that are named-only continue to skip past unnamed children for free.
Order is preserved across multiple bare patterns at the same level —
each pattern advances the shared iterator past whatever it consumed —
so a query cannot match children out of source order.

Captures from a failed match attempt are rolled back via a snapshot, so
partial captures from a complex sub-query do not leak across attempts.

Add two regression tests against the `do` body wrapper in a Ruby
for-loop, whose implicit `child` field contains [do, identifier, end]:
- a query for ("end") matches by skipping past `do` and the identifier
- a query for ("end") then ("do") fails, demonstrating order preservation
2026-05-07 15:08:22 +00:00
Taus
6f643a3604 yeast: Use canonical ID when registering unnamed kinds in Schema
Schema::from_language registered unnamed kinds via or_insert(id), where
`id` came from iterating 0..node_kind_count. For names with multiple
unnamed IDs (notably "end" in tree-sitter-ruby has IDs 0 and 13, where
ID 0 is the reserved error token), this picked the first encountered
ID — typically the wrong one.

The visitor sets node.kind via language.id_for_node_kind(name, false),
which returns the canonical ID. So a query for ("end") would compare
node.kind=13 against schema=0 and silently fail to match, with no
diagnostic.

Use language.id_for_node_kind(name, false) to obtain the canonical ID
when registering, mirroring the named-kind path that already does the
same with id_for_node_kind(name, true).
2026-05-07 15:08:21 +00:00
Taus
a4df96aad6 yeast: Support capturing unnamed nodes in queries
Three improvements to the query parser, all aimed at allowing query
patterns to refer to unnamed tokens:

1. Bare-literal capture: `"=" @op` now captures the unnamed `=` token,
   matching the parenthesized form `("=") @op`. Previously the literal
   branch in parse_query_list skipped the maybe_wrap_capture call, so
   the `@op` was a leftover token and would error.

2. Bare `_` matches any node, named or unnamed. Previously bare `_` and
   `(_)` both produced QueryNode::Any with the same matches_named_only
   behaviour, so bare `_` would skip unnamed children. Now Any carries a
   match_unnamed flag: false for `(_)` (named-only, tree-sitter default)
   and true for bare `_` (any node).

3. Named fields and bare child patterns may be intermixed in any order.
   Previously, once parse_query_fields saw a bare pattern it would stop
   accepting named fields. The fix accumulates bare patterns into the
   implicit `child` field and keeps parsing.

Each named field independently selects its target field for matching, so
the source-order of fields in the query is purely cosmetic and intermixing
is safe.

Add tests covering parenthesized capture, bare-literal capture, and the
named-vs-any distinction between `(_)` and bare `_`. Update query-syntax
docs to reflect all three.
2026-05-07 15:08:21 +00:00
Owen Mansel-Chan
f9240e7058 Fix QL formatting 2026-05-07 15:57:33 +01:00
Geoffrey White
df37b50051 Shared: Small adjustment to the encrypt not-sensitive regex. 2026-05-07 14:22:31 +01:00
Anders Schack-Mulligen
6b6df374fa C#/Java: Accept test changes. 2026-05-07 15:07:31 +02:00
Anders Schack-Mulligen
072166ba88 C#/Java: Adjust Guards instantiations. 2026-05-07 13:46:52 +02:00
Anders Schack-Mulligen
48785a0a76 Cfg: Rework CFG for switch case patterns. 2026-05-07 13:07:07 +02:00
MarkLee131
e8553c7449 Merge branch 'main' into fix/path-injection-read-subkind 2026-05-07 18:11:45 +08:00
Owen Mansel-Chan
33035dbfc8 Fix yaml formatting 2026-05-07 11:06:43 +01:00
Owen Mansel-Chan
f2ea3b98d8 Do not make such a strong security claim
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-07 10:58:35 +01:00
Owen Mansel-Chan
427b73ec9d Clarify that deserialization that follows a schema is safe 2026-05-07 10:51:20 +01:00
Owen Mansel-Chan
7aa3fd859a Remove double spaces from qhelp 2026-05-07 10:42:50 +01:00
Geoffrey White
1c704a0912 Python: Accept test changes (improvement). 2026-05-07 10:28:19 +01:00
Geoffrey White
ea711b032b Javascript: Accept test changes (regression). 2026-05-07 10:13:09 +01:00
Geoffrey White
0f8b0a7fdd Swift: Accept test changes (improvement). 2026-05-07 10:12:48 +01:00
Geoffrey White
7c728981f1 Merge remote-tracking branch 'upstream/main' into extsensitive 2026-05-07 10:02:15 +01:00
Geoffrey White
809da0f8e7 Shared: Autoformat. 2026-05-07 10:01:56 +01:00
Geoffrey White
f2f4f4cce3 Shared: Add 'security_code' sensitive data heuristic. 2026-05-06 14:48:55 +01:00
Geoffrey White
5ed78d1a4a Shared: Fix and simplify the exclusion for 'encrypted' values. 2026-05-06 14:43:52 +01:00
Geoffrey White
6e2fb6f0ff Shared: Fix for 'coauthor'. 2026-05-06 14:34:18 +01:00
Geoffrey White
213ab902cd Shared: Fix for 'api_tok'. 2026-05-06 14:34:15 +01:00
Geoffrey White
b60ce3cf04 Shared: Fix for 'profile'. 2026-05-06 14:33:25 +01:00
Geoffrey White
cb84e633fa Shared: Fix for 'wildcard'. 2026-05-06 14:32:24 +01:00
Geoffrey White
07d4df18b9 Shared: Add 'card.?no' sensitive data heuristic. 2026-05-06 14:32:21 +01:00
Geoffrey White
d95001f406 Rust: Additional test cases for sensitive data heuristics. 2026-05-06 14:31:47 +01:00
Geoffrey White
dc863c39a9 Swift: Add test cases for an alternative pattern of calls to Insecure.MD5.hash. 2026-05-06 10:27:54 +01:00
Geoffrey White
b6155ff443 Swift: Test spacing. 2026-05-06 10:27:06 +01:00
Kristen Newbury
3f44a23cf2 Adjust alert location UntrustedCheckoutCritical 2026-05-05 13:35:52 -04:00
MarkLee131
467394123c Merge branch 'main' into fix/path-injection-read-subkind 2026-05-04 18:56:12 +08:00
MarkLee131
49e5886a06 Update java/ql/lib/ext/org.apache.commons.io.model.yml
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2026-05-04 12:56:11 +08:00
MarkLee131
c10a05f26a Update java/ql/lib/ext/org.apache.commons.io.model.yml
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2026-05-03 14:14:48 +08:00
MarkLee131
8710e63011 Update java/ql/lib/ext/javax.servlet.model.yml
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2026-05-03 14:14:15 +08:00
MarkLee131
dbc9d0de4a Update java/ql/lib/ext/org.apache.commons.io.model.yml
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2026-05-03 14:14:07 +08:00
MarkLee131
9194cdad9c Update java/ql/lib/ext/java.nio.file.model.yml
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2026-05-03 14:08:31 +08:00
MarkLee131
7050241a54 Update java/ql/lib/ext/java.nio.file.model.yml
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2026-05-03 14:08:21 +08:00
MarkLee131
62a0a3e384 Update java/ql/lib/ext/java.nio.file.model.yml
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2026-05-03 14:08:12 +08:00
MarkLee131
3ad2d8ca3d Update java/ql/lib/ext/java.nio.file.model.yml
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2026-05-03 14:04:35 +08:00
MarkLee131
bafa892116 Merge branch 'main' into fix/path-injection-read-subkind 2026-05-01 16:06:35 +08:00
MarkLee131
119994b59f Java: move File inspection methods to path-injection[read]
Per review feedback on #21741: File.canRead/canWrite/canExecute,
exists/isDirectory/isFile/isHidden only inspect a path, so move them
under the path-injection[read] sub-kind. Update TaintedPath.expected
and the experimental CWE-073 expected to match.
2026-05-01 16:04:29 +08:00
MarkLee131
936f0c650c Address review comments on path-injection[read] sub-kind
- shared/mad/codeql/mad/ModelValidation.qll: shorten the comment
  for `path-injection[%]` to `// Java-only currently`, matching the
  style of other language-scoped entries and dropping API examples
  and the java/zipslip reference.
- java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll: replace
  the `File.exists` example in the QLDoc with `FileReader`, since
  `File.exists` is still labelled plain `path-injection`, not
  `path-injection[read]`.
2026-04-30 19:06:04 +08:00
MarkLee131
90741b15e2 Merge branch 'main' into fix/path-injection-read-subkind 2026-04-30 18:37:12 +08:00
Florin Coada
d5b690caf8 Apply suggestions from code review
Co-authored-by: Sarita Iyer <66540150+saritai@users.noreply.github.com>
2026-04-27 15:54:20 +01:00
Florin Coada
870ce1be5c Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Sarita Iyer <66540150+saritai@users.noreply.github.com>
2026-04-27 15:53:06 +01:00
Florin Coada
dbd851e64d Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Sarita Iyer <66540150+saritai@users.noreply.github.com>
2026-04-27 15:52:32 +01:00
Florin Coada
81d7fc2611 Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Sarita Iyer <66540150+saritai@users.noreply.github.com>
2026-04-27 15:51:12 +01:00
Florin Coada
e3fa8b031b Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Sarita Iyer <66540150+saritai@users.noreply.github.com>
2026-04-27 15:50:55 +01:00
Florin Coada
9692671213 Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Sarita Iyer <66540150+saritai@users.noreply.github.com>
2026-04-27 15:50:41 +01:00
Florin Coada
909d9cb805 Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Sarita Iyer <66540150+saritai@users.noreply.github.com>
2026-04-27 15:50:28 +01:00
Florin Coada
a44883486a Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2026-04-21 16:44:12 +01:00
Florin Coada
0866e8dc21 Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2026-04-21 16:43:59 +01:00
Florin Coada
d60a30d1f2 Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2026-04-21 16:43:40 +01:00
Florin Coada
da88268943 Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2026-04-21 16:43:25 +01:00
Florin Coada
af32ae2ba5 Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2026-04-21 16:42:41 +01:00
Kaixuan Li
07e97e20d8 Merge branch 'github:main' into fix/path-injection-read-subkind 2026-04-21 22:59:53 +10:00
MarkLee131
6d10b1582f Java: update regression-test expectations for path-injection[read]
The sink-model generator and the experimental java/file-path-injection
query now observe the new path-injection[read] sub-kind for the
FileInputStream and Files.copy source-argument models.

- CWE-073 FilePathInjection.expected: refresh the models table for the
  renamed kind on FileInputStream(File); alerts unchanged.
- modelgenerator Sinks.java: update the inline sink annotation for
  copyFileToDirectory(Path,Path,CopyOption[]) Argument[0] to the new
  path-injection[read] sub-kind, mirroring the library change.
2026-04-21 19:45:13 +08:00
Florin Coada
2429e7b792 Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2026-04-21 09:36:48 +01:00
MarkLee131
c336a1595d Java: split read-only path sinks into path-injection[read]
Introduce a new Models-as-Data sink sub-kind path-injection[read] for
models that only read from or inspect a path. The general
java/path-injection query and its PathInjectionSanitizer barrier
continue to consider both path-injection and path-injection[read]
sinks, so no alerts are lost. The java/zipslip query deliberately
selects only path-injection sinks, since read-only accesses such as
ClassLoader.getResource or FileInputStream are outside the archive
extraction threat model.

Addresses https://github.com/github/codeql/issues/21606 along the lines
proposed on the issue thread: prefer path-injection[read] over a
[create] sub-kind so that miscategorizing a sink causes a false
positive (easy to spot) rather than a false negative.

- shared/mad/codeql/mad/ModelValidation.qll: allow path-injection[...]
  as a valid sink kind.
- java/ql/lib/ext/*.model.yml: relabel the models that PR #12916
  migrated from the historical read-file kind (plus the newer
  ClassLoader resource-lookup variants that share the same read-only
  semantics).
- java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll and
  PathSanitizer.qll: select both path-injection and
  path-injection[read] sinks/barriers.
- java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll: keep only
  path-injection, with a comment explaining why path-injection[read]
  is excluded.
- java/ql/test/query-tests/security/CWE-022/semmle/tests/ZipTest.java:
  add m7 regression covering the Dubbo-style classpath lookup from
  issue #21606 and assert no alert is produced.
- Update TaintedPath.expected for the renamed kinds in the models list.
- Add change-notes under java/ql/lib/change-notes and
  java/ql/src/change-notes.
2026-04-21 09:17:36 +10:00
copilot-swe-agent[bot]
b2046034f1 Update UnpinnedActionsTag query metadata scope
Agent-Logs-Url: https://github.com/github/codeql/sessions/5425ff86-b998-4c7b-9447-52c8ae74a7a2

Co-authored-by: oscarsj <1410188+oscarsj@users.noreply.github.com>
2026-04-20 11:01:57 +00:00
Óscar San José
ca68274ec3 Add changelog 2026-04-20 12:43:25 +02:00
Óscar San José
e598c56c64 update and fix tests 2026-04-20 12:38:06 +02:00
Florin Coada
1c8b90e9b1 Add model pack publishing section to Rust docs
Add the 'Publish data extension files in a CodeQL model pack to share'
section, matching the structure used in C#, C++, Go, and Java docs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 15:18:00 +01:00
Florin Coada
7c9dd05edd Update docs/codeql/codeql-language-guides/codeql-for-rust.rst
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2026-04-17 15:11:58 +01:00
Florin Coada
73695db668 Update docs/codeql/codeql-language-guides/customizing-library-models-for-rust.rst
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2026-04-17 15:11:15 +01:00
Florin Coada
08aced85ba Add barrier and barrier guard documentation for Rust
Add barrierModel and barrierGuardModel sections to the Rust library
models documentation, following the pattern established in PR #21523
for other languages.

Includes:
- New extensible predicate descriptions in the overview
- Example: barrier for SQL injection using escape_sql
- Example: barrier guard for path injection using is_safe_path
- Reference material for both barrierModel and barrierGuardModel

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 11:09:46 +01:00
Florin Coada
6c83ec6e61 docs: Add 'Customizing library models for Rust' documentation
Add documentation for customizing library models for Rust using data
extension files. This follows the pattern of existing documentation for
other languages (Java, Python, Ruby, Go, C#, C++, JavaScript).

The documentation covers:
- Rust-specific extensible predicates (sourceModel, sinkModel,
  summaryModel, neutralModel) with their simplified schema
- Canonical path syntax for identifying Rust functions and methods
- Examples using real models from the codebase (sqlx, reqwest,
  std::env, std::path, Iterator::map)
- Access path token reference (Argument, Parameter, ReturnValue,
  Element, Field, Reference, Future)
- Source and sink kind reference
- Threat model integration

Also updates codeql-for-rust.rst to include the new page in the
toctree.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 10:02:34 +01:00
copilot-swe-agent[bot]
ec12035ac2 Extend unpinned-tag query to scan composite action metadata
Agent-Logs-Url: https://github.com/github/codeql/sessions/c52790be-00f6-4250-b46b-38c05365ddd7

Co-authored-by: oscarsj <1410188+oscarsj@users.noreply.github.com>
2026-04-10 11:20:36 +00:00
copilot-swe-agent[bot]
386872c668 Initial plan 2026-04-10 11:16:42 +00:00
806 changed files with 70271 additions and 10652 deletions

396
Cargo.lock generated
View File

@@ -140,6 +140,26 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bindgen"
version = "0.72.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
dependencies = [
"bitflags 2.9.4",
"cexpr",
"clang-sys",
"itertools 0.12.1",
"log 0.4.28",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash 2.1.1",
"shlex",
"syn",
]
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -250,6 +270,15 @@ dependencies = [
"shlex",
]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.3"
@@ -328,7 +357,7 @@ dependencies = [
"chalk-derive 0.103.0",
"chalk-ir 0.103.0",
"ena",
"indexmap 2.11.4",
"indexmap 2.14.0",
"itertools 0.12.1",
"petgraph",
"rustc-hash 1.1.0",
@@ -349,6 +378,17 @@ dependencies = [
"windows-link 0.2.0",
]
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "4.5.48"
@@ -438,6 +478,25 @@ dependencies = [
"tree-sitter-ruby",
]
[[package]]
name = "codeql-extractor-unified"
version = "0.1.0"
dependencies = [
"clap",
"codeql-extractor",
"encoding",
"lazy_static",
"rayon",
"regex",
"serde_json",
"tracing",
"tracing-subscriber",
"tree-sitter",
"tree-sitter-embedded-template",
"tree-sitter-swift",
"yeast",
]
[[package]]
name = "codeql-rust"
version = "0.1.0"
@@ -486,6 +545,15 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
name = "convert_case"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
@@ -739,6 +807,12 @@ dependencies = [
"typeid",
]
[[package]]
name = "fastrand"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]]
name = "figment"
version = "0.10.19"
@@ -787,6 +861,12 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "foldhash"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
[[package]]
name = "form_urlencoded"
version = "1.2.2"
@@ -871,9 +951,26 @@ checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash",
"foldhash 0.1.5",
]
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash 0.2.0",
]
[[package]]
name = "hashbrown"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "hashlink"
version = "0.10.0"
@@ -1060,16 +1157,25 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.11.4"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.15.5",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
[[package]]
name = "indoc"
version = "2.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
dependencies = [
"rustversion",
]
[[package]]
name = "inlinable_string"
version = "0.1.15"
@@ -1199,6 +1305,16 @@ version = "0.2.175"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
[[package]]
name = "libloading"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
dependencies = [
"cfg-if",
"windows-link 0.2.0",
]
[[package]]
name = "line-index"
version = "0.1.2"
@@ -1264,6 +1380,12 @@ dependencies = [
"autocfg",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
@@ -1310,6 +1432,16 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "notify"
version = "8.2.0"
@@ -1437,6 +1569,12 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "pathdiff"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
[[package]]
name = "pear"
version = "0.2.9"
@@ -1492,7 +1630,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
dependencies = [
"fixedbitset",
"indexmap 2.11.4",
"indexmap 2.14.0",
]
[[package]]
name = "phf"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
dependencies = [
"phf_shared",
"serde",
]
[[package]]
name = "phf_generator"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
dependencies = [
"fastrand",
"phf_shared",
]
[[package]]
name = "phf_shared"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
dependencies = [
"siphasher",
]
[[package]]
@@ -1537,6 +1704,25 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "prettyplease"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro-crate"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
dependencies = [
"toml_edit 0.25.11+spec-1.1.0",
]
[[package]]
name = "proc-macro2"
version = "1.0.101"
@@ -1668,7 +1854,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e876bb2c3e52a8d4e6684526a2d4e81f9d028b939ee4dc5dc775fe10deb44d59"
dependencies = [
"dashmap",
"indexmap 2.11.4",
"indexmap 2.14.0",
"la-arena",
"ra_ap_cfg",
"ra_ap_intern",
@@ -1710,7 +1896,7 @@ checksum = "ebffdc134eccabc17209d7760cfff7fd12ed18ab6e21188c5e084b97aa38504c"
dependencies = [
"arrayvec",
"either",
"indexmap 2.11.4",
"indexmap 2.14.0",
"itertools 0.14.0",
"ra_ap_base_db",
"ra_ap_cfg",
@@ -1740,7 +1926,7 @@ dependencies = [
"drop_bomb",
"either",
"fst",
"indexmap 2.11.4",
"indexmap 2.14.0",
"itertools 0.14.0",
"la-arena",
"ra-ap-rustc_abi",
@@ -1809,7 +1995,7 @@ dependencies = [
"cov-mark",
"either",
"ena",
"indexmap 2.11.4",
"indexmap 2.14.0",
"itertools 0.14.0",
"la-arena",
"oorandom",
@@ -1847,7 +2033,7 @@ dependencies = [
"crossbeam-channel",
"either",
"fst",
"indexmap 2.11.4",
"indexmap 2.14.0",
"itertools 0.14.0",
"line-index",
"memchr",
@@ -1949,7 +2135,7 @@ version = "0.0.301"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45db9e2df587d56f0738afa89fb2c100ff7c1e9cbe49e07f6a8b62342832211b"
dependencies = [
"indexmap 2.11.4",
"indexmap 2.14.0",
"ra_ap_intern",
"ra_ap_paths",
"ra_ap_span",
@@ -2108,7 +2294,7 @@ checksum = "6c174d6b9b7a7f54687df7e00c3e75ed6f082a7943a9afb1d54f33c0c12773de"
dependencies = [
"crossbeam-channel",
"fst",
"indexmap 2.11.4",
"indexmap 2.14.0",
"nohash-hasher",
"ra_ap_paths",
"ra_ap_stdx",
@@ -2240,6 +2426,15 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
[[package]]
name = "relative-path"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bca40a312222d8ba74837cb474edef44b37f561da5f773981007a10bbaa992b0"
dependencies = [
"serde",
]
[[package]]
name = "rowan"
version = "0.15.15"
@@ -2253,6 +2448,57 @@ dependencies = [
"text-size",
]
[[package]]
name = "rquickjs"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a135375fbac5ba723bb6a48f432a72f81539cedde422f0121a86c7c4e96d8e0d"
dependencies = [
"rquickjs-core",
"rquickjs-macro",
]
[[package]]
name = "rquickjs-core"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bccb7121a123865c8ace4dea42e7ed84d78b90cbaf4ca32c59849d8d210c9672"
dependencies = [
"hashbrown 0.16.1",
"phf",
"relative-path",
"rquickjs-sys",
]
[[package]]
name = "rquickjs-macro"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89f93602cc3112c7f30bf5f29e722784232138692c7df4c52ebbac7e035d900d"
dependencies = [
"convert_case",
"fnv",
"ident_case",
"indexmap 2.14.0",
"phf_generator",
"phf_shared",
"proc-macro-crate",
"proc-macro2",
"quote",
"rquickjs-core",
"syn",
]
[[package]]
name = "rquickjs-sys"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57b1b6528590d4d65dc86b5159eae2d0219709546644c66408b2441696d1d725"
dependencies = [
"bindgen",
"cc",
]
[[package]]
name = "rust-extractor-macros"
version = "0.1.0"
@@ -2318,7 +2564,7 @@ dependencies = [
"crossbeam-utils",
"hashbrown 0.15.5",
"hashlink",
"indexmap 2.11.4",
"indexmap 2.14.0",
"intrusive-collections",
"papaya",
"parking_lot",
@@ -2407,11 +2653,12 @@ dependencies = [
[[package]]
name = "semver"
version = "1.0.26"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
dependencies = [
"serde",
"serde_core",
]
[[package]]
@@ -2471,7 +2718,7 @@ version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
dependencies = [
"indexmap 2.11.4",
"indexmap 2.14.0",
"itoa",
"memchr",
"ryu",
@@ -2507,7 +2754,7 @@ dependencies = [
"chrono",
"hex",
"indexmap 1.9.3",
"indexmap 2.11.4",
"indexmap 2.14.0",
"schemars 0.9.0",
"schemars 1.0.4",
"serde",
@@ -2535,7 +2782,7 @@ version = "0.9.34+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [
"indexmap 2.11.4",
"indexmap 2.14.0",
"itoa",
"ryu",
"serde",
@@ -2557,6 +2804,18 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "siphasher"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
[[package]]
name = "smallbitvec"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b0e903ee191d8f7a8fbf0d712c3a1699d19e04ceba5ad1eb673053c7d938a09"
[[package]]
name = "smallvec"
version = "1.15.1"
@@ -2633,18 +2892,18 @@ checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d"
[[package]]
name = "thiserror"
version = "2.0.16"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.16"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
@@ -2709,7 +2968,7 @@ dependencies = [
"serde",
"serde_spanned 0.6.9",
"toml_datetime 0.6.11",
"toml_edit",
"toml_edit 0.22.27",
]
[[package]]
@@ -2718,13 +2977,13 @@ version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0"
dependencies = [
"indexmap 2.11.4",
"indexmap 2.14.0",
"serde_core",
"serde_spanned 1.0.2",
"toml_datetime 0.7.2",
"toml_parser",
"toml_writer",
"winnow",
"winnow 0.7.13",
]
[[package]]
@@ -2745,27 +3004,48 @@ dependencies = [
"serde_core",
]
[[package]]
name = "toml_datetime"
version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_edit"
version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap 2.11.4",
"indexmap 2.14.0",
"serde",
"serde_spanned 0.6.9",
"toml_datetime 0.6.11",
"toml_write",
"winnow",
"winnow 0.7.13",
]
[[package]]
name = "toml_edit"
version = "0.25.11+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b"
dependencies = [
"indexmap 2.14.0",
"toml_datetime 1.1.1+spec-1.1.0",
"toml_parser",
"winnow 1.0.2",
]
[[package]]
name = "toml_parser"
version = "1.0.3"
version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627"
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
dependencies = [
"winnow",
"winnow 1.0.2",
]
[[package]]
@@ -2780,6 +3060,12 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109"
[[package]]
name = "topological-sort"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
[[package]]
name = "tracing"
version = "0.1.41"
@@ -2876,6 +3162,30 @@ dependencies = [
"tree-sitter-language",
]
[[package]]
name = "tree-sitter-generate"
version = "0.26.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fb2e1bdb1d5f9d23cd5fa68cf98b3bedbd223c92a2edd60bbcf30bcf7180a5"
dependencies = [
"bitflags 2.9.4",
"dunce",
"indexmap 2.14.0",
"indoc",
"log 0.4.28",
"pathdiff",
"regex",
"regex-syntax",
"rquickjs",
"rustc-hash 2.1.1",
"semver",
"serde",
"serde_json",
"smallbitvec",
"thiserror",
"topological-sort",
]
[[package]]
name = "tree-sitter-json"
version = "0.24.8"
@@ -2922,6 +3232,15 @@ dependencies = [
"tree-sitter-language",
]
[[package]]
name = "tree-sitter-swift"
version = "0.7.2"
dependencies = [
"cc",
"tree-sitter-generate",
"tree-sitter-language",
]
[[package]]
name = "triomphe"
version = "0.1.14"
@@ -2971,6 +3290,12 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
[[package]]
name = "unicode-segmentation"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c"
[[package]]
name = "unicode-xid"
version = "0.2.6"
@@ -3360,6 +3685,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "winnow"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0"
dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen"
version = "0.45.1"

View File

@@ -7,6 +7,8 @@ members = [
"shared/yeast",
"shared/yeast-macros",
"ruby/extractor",
"unified/extractor",
"unified/extractor/tree-sitter-swift",
"rust/extractor",
"rust/extractor/macros",
"rust/ast-generator",

View File

@@ -102,6 +102,7 @@ use_repo(
tree_sitter_extractors_deps,
"vendor_ts__anyhow-1.0.100",
"vendor_ts__argfile-0.2.1",
"vendor_ts__cc-1.2.61",
"vendor_ts__chalk-ir-0.104.0",
"vendor_ts__chrono-0.4.42",
"vendor_ts__clap-4.5.48",
@@ -149,7 +150,9 @@ use_repo(
"vendor_ts__tracing-subscriber-0.3.20",
"vendor_ts__tree-sitter-0.26.8",
"vendor_ts__tree-sitter-embedded-template-0.25.0",
"vendor_ts__tree-sitter-generate-0.26.8",
"vendor_ts__tree-sitter-json-0.24.8",
"vendor_ts__tree-sitter-language-0.1.5",
"vendor_ts__tree-sitter-python-0.23.6",
"vendor_ts__tree-sitter-ql-0.23.1",
"vendor_ts__tree-sitter-ruby-0.23.1",

View File

@@ -8,5 +8,5 @@
import actions
from UsesStep uses
where uses.getVersion().regexpMatch("^[A-Fa-f0-9]{40}$")
where uses.getVersion().regexpMatch("^[A-Fa-f0-9]{40}([A-Fa-f0-9]{24})?$")
select uses, "This 'uses' step has a pinned SHA version."

View File

@@ -1,3 +1,9 @@
## 0.4.36
### Minor Analysis Improvements
* Altered 2 patterns in the `poisonable_steps` modelling. Extra sinks are detected in the following cases: scripts executed via python modules and `go run` in directories are detected as potential mechanisms of injection. For the go execution pattern, the pattern is updated to now ignore flags that occur between go and the specific command. This change may lead to more results being detected by the following queries: `actions/untrusted-checkout/high`, `actions/untrusted-checkout/critical`, `actions/untrusted-checkout-toctou/high`, `actions/untrusted-checkout-toctou/critical`, `actions/cache-poisoning/poisonable-step`, `actions/cache-poisoning/direct-cache` and `actions/artifact-poisoning/path-traversal`.
## 0.4.35
No user-facing changes.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.

View File

@@ -1,4 +1,5 @@
---
category: minorAnalysis
---
* Altered 2 patterns in the `poisonable_steps` modelling. Extra sinks are detected in the following cases: scripts executed via python modules and `go run` in directories are detected as potential mechanisms of injection. For the go execution pattern, the pattern is updated to now ignore flags that occur between go and the specific command. This change may lead to more results being detected by the following queries: `actions/untrusted-checkout/high`, `actions/untrusted-checkout/critical`, `actions/untrusted-checkout-toctou/high`, `actions/untrusted-checkout-toctou/critical`, `actions/cache-poisoning/poisonable-step`, `actions/cache-poisoning/direct-cache` and `actions/artifact-poisoning/path-traversal`.
## 0.4.36
### Minor Analysis Improvements
* Altered 2 patterns in the `poisonable_steps` modelling. Extra sinks are detected in the following cases: scripts executed via python modules and `go run` in directories are detected as potential mechanisms of injection. For the go execution pattern, the pattern is updated to now ignore flags that occur between go and the specific command. This change may lead to more results being detected by the following queries: `actions/untrusted-checkout/high`, `actions/untrusted-checkout/critical`, `actions/untrusted-checkout-toctou/high`, `actions/untrusted-checkout-toctou/critical`, `actions/cache-poisoning/poisonable-step`, `actions/cache-poisoning/direct-cache` and `actions/artifact-poisoning/path-traversal`.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.35
lastReleaseVersion: 0.4.36

View File

@@ -785,7 +785,22 @@ module Bash {
/**
* Holds if the given regex is used to match an alphanumeric string
* eg: `^[0-9a-zA-Z]{40}$`, `^[0-9]+$` or `^[a-zA-Z0-9_]+$`
* eg: `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$`, `^[0-9]+$` or `^[a-zA-Z0-9_]+$`
*/
string alphaNumericRegex() { result = "^\\^\\[([09azAZ_-]+)\\](\\+|\\{\\d+\\})\\$$" }
string alphaNumericRegex() {
exists(string r1, string r2, string r3, string r4 |
// An alphanumeric character class
r1 = "\\[([09azAZ_-]+)\\]" and
// The same as above, followed by a quantifier like `+` or `{20}`
r2 = r1 + "(\\+|\\{\\d+\\})" and
// The same as above, possibly with parentheses around it
r3 = "\\(?" + r2 + "\\)?" and
// The same as above, possibly with a `?` after it
r4 = r3 + "\\??"
|
// The same as above, repeated one or more times, and with `^` at the
// beginning and `$` at the end
result = "^\\^(" + r4 + ")+\\$$"
)
}
}

View File

@@ -1,5 +1,5 @@
name: codeql/actions-all
version: 0.4.36-dev
version: 0.4.37-dev
library: true
warnOnImplicitThis: true
dependencies:

View File

@@ -1,3 +1,17 @@
## 0.6.28
### Query Metadata Changes
* Adjusted the name of `actions/untrusted-checkout/high` to more clearly describe which parts of the scenario are in a privileged context.
### Minor Analysis Improvements
* The `actions/unpinned-tag` query now analyzes composite action metadata (`action.yml`/`action.yaml` files) in addition to workflow files, providing more comprehensive detection of unpinned action references across the entire Actions ecosystem.
### Bug Fixes
* Fixed help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Previously the messages were unclear as to why and how the vulnerabilities could occur.
## 0.6.27
No user-facing changes.

View File

@@ -1,5 +1,5 @@
/**
* @name Unpinned tag for a non-immutable Action in workflow
* @name Unpinned tag for a non-immutable Action in workflow or composite action
* @description Using a tag for a non-immutable Action that is not pinned to a commit can lead to executing an untrusted Action through a supply chain attack.
* @kind problem
* @security-severity 5.0
@@ -15,7 +15,9 @@ import actions
import codeql.actions.security.UseOfUnversionedImmutableAction
bindingset[version]
private predicate isPinnedCommit(string version) { version.regexpMatch("^[A-Fa-f0-9]{40}$") }
private predicate isPinnedCommit(string version) {
version.regexpMatch("^[A-Fa-f0-9]{40}([A-Fa-f0-9]{24})?$")
}
bindingset[nwo]
private predicate isTrustedOwner(string nwo) {
@@ -31,15 +33,26 @@ private predicate isPinnedContainer(string version) {
bindingset[nwo]
private predicate isContainerImage(string nwo) { nwo.regexpMatch("^docker://.+") }
from UsesStep uses, string nwo, string version, Workflow workflow, string name
private predicate getStepContainerName(UsesStep uses, string name) {
exists(Workflow workflow |
uses.getEnclosingWorkflow() = workflow and
(
workflow.getName() = name
or
not exists(workflow.getName()) and workflow.getLocation().getFile().getBaseName() = name
)
)
or
exists(CompositeAction action |
uses.getEnclosingCompositeAction() = action and
name = action.getLocation().getFile().getBaseName()
)
}
from UsesStep uses, string nwo, string version, string name
where
uses.getCallee() = nwo and
uses.getEnclosingWorkflow() = workflow and
(
workflow.getName() = name
or
not exists(workflow.getName()) and workflow.getLocation().getFile().getBaseName() = name
) and
getStepContainerName(uses, name) and
uses.getVersion() = version and
not isTrustedOwner(nwo) and
not (if isContainerImage(nwo) then isPinnedContainer(version) else isPinnedCommit(version)) and

View File

@@ -27,7 +27,7 @@ Certain triggers automatically grant a workflow elevated privileges:
* An attacker forks the repository and adds malicious code (e.g., in the build script)
* The attacker opens a PR from the fork, and, if needed, comments on the PR
* The workflow in the base repository checks out the forked code
* The workflow runs, (e.g. the build script etc.), which contains the malicious code
* The workflow runs the malicious code
Please note that not only build scripts can be malicious code vectors. There is a large number of other possibilities. Some of them are listed in the [LOTP](https://boostsecurityio.github.io/lotp/) catalog.
@@ -41,6 +41,8 @@ The best practice is to handle the potentially untrusted pull request via the **
The artifacts downloaded from the first workflow should be considered untrusted and must be verified.
Additionally, ensure that least privilege are used both at the workflow level (through event triggers and workflow permissions) and job level (through job permissions).
## Example
### Incorrect Usage
@@ -163,4 +165,5 @@ jobs:
- GitHub Security Lab Research: [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
- Mitigating risks of untrusted checkout: [GitHub Docs](https://docs.github.com/en/enterprise-cloud@latest/actions/reference/security/secure-use#mitigating-the-risks-of-untrusted-code-checkout).
- Securing with least privilege: [Workflow secure use](https://docs.github.com/en/actions/reference/security/secure-use).
- Living Off the Pipeline: [LOTP](https://boostsecurityio.github.io/lotp/).

View File

@@ -51,5 +51,6 @@ where
event.getName() = checkoutTriggers() and
not exists(ControlCheck check | check.protects(checkout, event, "untrusted-checkout")) and
not exists(ControlCheck check | check.protects(poisonable, event, "untrusted-checkout"))
select poisonable, checkout, poisonable,
"Potential execution of untrusted code on a privileged workflow ($@)", event, event.getName()
select checkout, checkout, poisonable,
"Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@).",
event, event.getName()

View File

@@ -27,7 +27,7 @@ Certain triggers automatically grant a workflow elevated privileges:
* An attacker forks the repository and adds malicious code (e.g., in the build script)
* The attacker opens a PR from the fork, and, if needed, comments on the PR
* The workflow in the base repository checks out the forked code
* The workflow runs, (e.g. the build script etc.), which contains the malicious code
* The workflow runs the malicious code
Please note that not only build scripts can be malicious code vectors. There is a large number of other possibilities. Some of them are listed in the [LOTP](https://boostsecurityio.github.io/lotp/) catalog.
@@ -41,6 +41,8 @@ The best practice is to handle the potentially untrusted pull request via the **
The artifacts downloaded from the first workflow should be considered untrusted and must be verified.
Additionally, ensure that least privilege are used both at the workflow level (through event triggers and workflow permissions) and job level (through job permissions).
## Example
### Incorrect Usage
@@ -163,4 +165,5 @@ jobs:
- GitHub Security Lab Research: [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
- Mitigating risks of untrusted checkout: [GitHub Docs](https://docs.github.com/en/enterprise-cloud@latest/actions/reference/security/secure-use#mitigating-the-risks-of-untrusted-code-checkout).
- Securing with least privilege: [Workflow secure use](https://docs.github.com/en/actions/reference/security/secure-use).
- Living Off the Pipeline: [LOTP](https://boostsecurityio.github.io/lotp/).

View File

@@ -1,5 +1,5 @@
/**
* @name Checkout of untrusted code in privileged context without privileged context use
* @name Checkout of untrusted code in a privileged context
* @description Privileged workflows have read/write access to the base repository and access to secrets.
* By explicitly checking out and running the build script from a fork the untrusted code is running in an environment
* that is able to push to the base repository and to access secrets.
@@ -42,5 +42,6 @@ where
not event.getName() = "issue_comment" and
not exists(ControlCheck check | check.protects(checkout, event, "untrusted-checkout"))
)
select checkout, "Potential execution of untrusted code on a privileged workflow ($@)", event,
event.getName()
select checkout,
"Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@).",
event, event.getName()

View File

@@ -27,7 +27,7 @@ Certain triggers automatically grant a workflow elevated privileges:
* An attacker forks the repository and adds malicious code (e.g., in the build script)
* The attacker opens a PR from the fork, and, if needed, comments on the PR
* The workflow in the base repository checks out the forked code
* The workflow runs, (e.g. the build script etc.), which contains the malicious code
* The workflow runs the malicious code
Please note that not only build scripts can be malicious code vectors. There is a large number of other possibilities. Some of them are listed in the [LOTP](https://boostsecurityio.github.io/lotp/) catalog.
@@ -41,6 +41,8 @@ The best practice is to handle the potentially untrusted pull request via the **
The artifacts downloaded from the first workflow should be considered untrusted and must be verified.
Additionally, ensure that least privilege are used both at the workflow level (through event triggers and workflow permissions) and job level (through job permissions).
## Example
### Incorrect Usage
@@ -163,4 +165,5 @@ jobs:
- GitHub Security Lab Research: [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
- Mitigating risks of untrusted checkout: [GitHub Docs](https://docs.github.com/en/enterprise-cloud@latest/actions/reference/security/secure-use#mitigating-the-risks-of-untrusted-code-checkout).
- Securing with least privilege: [Workflow secure use](https://docs.github.com/en/actions/reference/security/secure-use).
- Living Off the Pipeline: [LOTP](https://boostsecurityio.github.io/lotp/).

View File

@@ -1,5 +1,5 @@
/**
* @name Checkout of untrusted code in trusted context
* @name Checkout of untrusted code in a trusted context
* @description Privileged workflows have read/write access to the base repository and access to secrets.
* By explicitly checking out and running the build script from a fork the untrusted code is running in an environment
* that is able to push to the base repository and to access secrets.

View File

@@ -1,4 +0,0 @@
---
category: fix
---
* Fixed help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Previously the messages were unclear as to why and how the vulnerabilities could occur.

View File

@@ -1,4 +0,0 @@
---
category: queryMetadata
---
* Adjusted the name of `actions/untrusted-checkout/high` to more clearly describe which parts of the scenario are in a privileged context.

View File

@@ -0,0 +1,4 @@
---
category: majorAnalysis
---
* Adjusted `actions/untrusted-checkout/critical` to align more with other untrusted resource queries, where the alert location is the location where the artifact is obtained from (the checkout point). This aligns with the other 2 related queries. This will cause the same alerts to re-open for closed alerts of this query.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `actions/unpinned-tag` query now recognizes 64-character SHA-256 commit hashes as properly pinned references, in addition to 40-character SHA-1 hashes.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Altered the alert message for clarity for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`.

View File

@@ -0,0 +1,4 @@
---
category: fix
---
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.

View File

@@ -0,0 +1,4 @@
---
category: queryMetadata
---
* Reversed adjustment of the name of `actions/untrusted-checkout/high`, but kept the portion of the previous change for the word "trusted" to "privileged". Added a missing "a" to phrasing in `actions/untrusted-checkout/high` and `actions/untrusted-checkout/medium`.

View File

@@ -0,0 +1,13 @@
## 0.6.28
### Query Metadata Changes
* Adjusted the name of `actions/untrusted-checkout/high` to more clearly describe which parts of the scenario are in a privileged context.
### Minor Analysis Improvements
* The `actions/unpinned-tag` query now analyzes composite action metadata (`action.yml`/`action.yaml` files) in addition to workflow files, providing more comprehensive detection of unpinned action references across the entire Actions ecosystem.
### Bug Fixes
* Fixed help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Previously the messages were unclear as to why and how the vulnerabilities could occur.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.6.27
lastReleaseVersion: 0.6.28

View File

@@ -1,5 +1,5 @@
name: codeql/actions-queries
version: 0.6.28-dev
version: 0.6.29-dev
library: false
warnOnImplicitThis: true
groups: [actions, queries]

View File

@@ -0,0 +1,6 @@
name: Composite unpinned tag test
runs:
using: "composite"
steps:
- uses: foo/bar@v2
- uses: foo/bar@25b062c917b0c75f8b47d8469aff6c94ffd89abb

View File

@@ -11,3 +11,9 @@ jobs:
- uses: foo/bar@25b062c917b0c75f8b47d8469aff6c94ffd89abb
- uses: docker://foo/bar@latest
- uses: docker://foo/bar@sha256:887a259a5a534f3c4f36cb02dca341673c6089431057242cdc931e9f133147e9
# SHA-256 pinned (64 hex chars) - should NOT be flagged
- uses: foo/bar@25b062c917b0c75f8b47d8469aff6c94ffd89abb25b062c917b0c75f8b47d84d
# SHA-1 pinned (40 hex chars) regression - should NOT be flagged
- uses: foo/bar@a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
# Invalid 50-char hex string - should be flagged
- uses: foo/bar@a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2a1b2c3d4e5

View File

@@ -1,3 +1,4 @@
| .github/actions/unpinned-tag/action.yml:5:13:5:22 | foo/bar@v2 | Unpinned 3rd party Action 'action.yml' step $@ uses 'foo/bar' with ref 'v2', not a pinned commit hash | .github/actions/unpinned-tag/action.yml:5:7:6:4 | Uses Step | Uses Step |
| .github/workflows/actor_trusted_checkout.yml:19:13:19:36 | completely/fakeaction@v2 | Unpinned 3rd party Action 'actor_trusted_checkout.yml' step $@ uses 'completely/fakeaction' with ref 'v2', not a pinned commit hash | .github/workflows/actor_trusted_checkout.yml:19:7:23:4 | Uses Step | Uses Step |
| .github/workflows/actor_trusted_checkout.yml:23:13:23:37 | fakerepo/comment-on-pr@v1 | Unpinned 3rd party Action 'actor_trusted_checkout.yml' step $@ uses 'fakerepo/comment-on-pr' with ref 'v1', not a pinned commit hash | .github/workflows/actor_trusted_checkout.yml:23:7:26:21 | Uses Step | Uses Step |
| .github/workflows/artifactpoisoning21.yml:13:15:13:49 | dawidd6/action-download-artifact@v2 | Unpinned 3rd party Action 'Pull Request Open' step $@ uses 'dawidd6/action-download-artifact' with ref 'v2', not a pinned commit hash | .github/workflows/artifactpoisoning21.yml:13:9:18:6 | Uses Step | Uses Step |
@@ -33,3 +34,4 @@
| .github/workflows/test18.yml:37:21:37:63 | sonarsource/sonarcloud-github-action@master | Unpinned 3rd party Action 'Sonar' step $@ uses 'sonarsource/sonarcloud-github-action' with ref 'master', not a pinned commit hash | .github/workflows/test18.yml:36:15:40:58 | Uses Step | Uses Step |
| .github/workflows/unpinned_tags.yml:10:13:10:22 | foo/bar@v1 | Unpinned 3rd party Action 'unpinned_tags.yml' step $@ uses 'foo/bar' with ref 'v1', not a pinned commit hash | .github/workflows/unpinned_tags.yml:10:7:11:4 | Uses Step | Uses Step |
| .github/workflows/unpinned_tags.yml:12:13:12:35 | docker://foo/bar@latest | Unpinned 3rd party Action 'unpinned_tags.yml' step $@ uses 'docker://foo/bar' with ref 'latest', not a pinned commit hash | .github/workflows/unpinned_tags.yml:12:7:13:4 | Uses Step | Uses Step |
| .github/workflows/unpinned_tags.yml:19:13:19:70 | foo/bar@a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2a1b2c3d4e5 | Unpinned 3rd party Action 'unpinned_tags.yml' step $@ uses 'foo/bar' with ref 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2a1b2c3d4e5', not a pinned commit hash | .github/workflows/unpinned_tags.yml:19:7:19:71 | Uses Step | Uses Step |

View File

@@ -8,6 +8,7 @@ edges
| .github/actions/download-artifact/action.yaml:25:7:29:4 | Run Step | .github/actions/download-artifact/action.yaml:29:7:32:18 | Run Step |
| .github/actions/download-artifact/action.yaml:29:7:32:18 | Run Step | .github/workflows/artifactpoisoning91.yml:19:9:25:6 | Run Step: metadata |
| .github/actions/download-artifact/action.yaml:29:7:32:18 | Run Step | .github/workflows/resolve-args.yml:22:9:36:13 | Run Step: resolve-step |
| .github/actions/unpinned-tag/action.yml:5:7:6:4 | Uses Step | .github/actions/unpinned-tag/action.yml:6:7:6:61 | Uses Step |
| .github/workflows/actor_trusted_checkout.yml:9:7:14:4 | Uses Step | .github/workflows/actor_trusted_checkout.yml:14:7:15:4 | Uses Step |
| .github/workflows/actor_trusted_checkout.yml:14:7:15:4 | Uses Step | .github/workflows/actor_trusted_checkout.yml:15:7:19:4 | Run Step |
| .github/workflows/actor_trusted_checkout.yml:15:7:19:4 | Run Step | .github/workflows/actor_trusted_checkout.yml:19:7:23:4 | Uses Step |
@@ -311,7 +312,10 @@ edges
| .github/workflows/unpinned_tags.yml:9:7:10:4 | Uses Step | .github/workflows/unpinned_tags.yml:10:7:11:4 | Uses Step |
| .github/workflows/unpinned_tags.yml:10:7:11:4 | Uses Step | .github/workflows/unpinned_tags.yml:11:7:12:4 | Uses Step |
| .github/workflows/unpinned_tags.yml:11:7:12:4 | Uses Step | .github/workflows/unpinned_tags.yml:12:7:13:4 | Uses Step |
| .github/workflows/unpinned_tags.yml:12:7:13:4 | Uses Step | .github/workflows/unpinned_tags.yml:13:7:13:101 | Uses Step |
| .github/workflows/unpinned_tags.yml:12:7:13:4 | Uses Step | .github/workflows/unpinned_tags.yml:13:7:15:4 | Uses Step |
| .github/workflows/unpinned_tags.yml:13:7:15:4 | Uses Step | .github/workflows/unpinned_tags.yml:15:7:17:4 | Uses Step |
| .github/workflows/unpinned_tags.yml:15:7:17:4 | Uses Step | .github/workflows/unpinned_tags.yml:17:7:19:4 | Uses Step |
| .github/workflows/unpinned_tags.yml:17:7:19:4 | Uses Step | .github/workflows/unpinned_tags.yml:19:7:19:71 | Uses Step |
| .github/workflows/untrusted_checkout2.yml:7:9:14:6 | Run Step: pr_number | .github/workflows/untrusted_checkout2.yml:14:9:19:72 | Run Step |
| .github/workflows/untrusted_checkout3.yml:11:9:12:6 | Uses Step | .github/workflows/untrusted_checkout3.yml:12:9:13:6 | Uses Step |
| .github/workflows/untrusted_checkout3.yml:12:9:13:6 | Uses Step | .github/actions/dangerous-git-checkout/action.yml:6:7:11:4 | Uses Step |
@@ -334,42 +338,42 @@ edges
| .github/workflows/workflow_run_untrusted_checkout_2.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout_2.yml:16:9:18:31 | Uses Step |
| .github/workflows/workflow_run_untrusted_checkout_3.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout_3.yml:16:9:18:31 | Uses Step |
#select
| .github/workflows/auto_ci.yml:32:9:37:6 | Run Step | .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:32:9:37:6 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/auto_ci.yml:48:9:52:2 | Run Step | .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:48:9:52:2 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/auto_ci.yml:79:9:84:6 | Run Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:79:9:84:6 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/auto_ci.yml:84:9:93:6 | Run Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:84:9:93:6 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/dependabot3.yml:3:5:3:23 | pull_request_target | pull_request_target |
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/reusable_caller1.yaml:4:3:4:21 | pull_request_target | pull_request_target |
| .github/workflows/gitcheckout.yml:21:11:23:22 | Run Step | .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | .github/workflows/gitcheckout.yml:21:11:23:22 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/gitcheckout.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/label_trusted_checkout2.yml:17:7:21:4 | Run Step | .github/workflows/label_trusted_checkout2.yml:12:7:16:4 | Uses Step | .github/workflows/label_trusted_checkout2.yml:17:7:21:4 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/label_trusted_checkout2.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/level0.yml:107:9:112:2 | Run Step | .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:107:9:112:2 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/level0.yml:5:3:5:15 | issue_comment | issue_comment |
| .github/workflows/level0.yml:107:9:112:2 | Run Step | .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:107:9:112:2 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/level0.yml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/level0.yml:133:9:135:23 | Run Step | .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:133:9:135:23 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/level0.yml:5:3:5:15 | issue_comment | issue_comment |
| .github/workflows/level0.yml:133:9:135:23 | Run Step | .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:133:9:135:23 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/level0.yml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/poc2.yml:42:9:47:6 | Uses Step | .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:42:9:47:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/poc2.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/poc2.yml:52:9:58:24 | Run Step | .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:52:9:58:24 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/poc2.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/pr-workflow.yml:222:9:227:6 | Uses Step | .github/workflows/pr-workflow.yml:216:9:222:6 | Uses Step | .github/workflows/pr-workflow.yml:222:9:227:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:256:9:261:6 | Uses Step | .github/workflows/pr-workflow.yml:250:9:256:6 | Uses Step | .github/workflows/pr-workflow.yml:256:9:261:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:290:9:295:6 | Uses Step | .github/workflows/pr-workflow.yml:284:9:290:6 | Uses Step | .github/workflows/pr-workflow.yml:290:9:295:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:391:9:395:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:391:9:395:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:395:9:404:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:395:9:404:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:404:9:414:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:404:9:414:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:414:9:423:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:414:9:423:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:423:9:432:2 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:423:9:432:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/reusable_local.yml:26:9:29:7 | Run Step | .github/workflows/reusable_local.yml:23:9:26:6 | Uses Step | .github/workflows/reusable_local.yml:26:9:29:7 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/reusable_caller3.yaml:4:3:4:21 | pull_request_target | pull_request_target |
| .github/workflows/test7.yml:33:9:36:6 | Run Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:33:9:36:6 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:36:9:39:6 | Run Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:36:9:39:6 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:49:9:59:6 | Run Step: benchmark-pr | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:49:9:59:6 | Run Step: benchmark-pr | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:59:9:60:6 | Run Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:59:9:60:6 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:60:9:60:37 | Run Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:60:9:60:37 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test10.yml:25:9:30:2 | Run Step | .github/workflows/test10.yml:20:9:25:6 | Uses Step | .github/workflows/test10.yml:25:9:30:2 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test10.yml:8:3:8:21 | pull_request_target | pull_request_target |
| .github/workflows/test11.yml:90:7:93:54 | Uses Step | .github/workflows/test11.yml:84:7:90:4 | Uses Step | .github/workflows/test11.yml:90:7:93:54 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test11.yml:5:3:5:15 | issue_comment | issue_comment |
| .github/workflows/test17.yml:19:15:23:58 | Uses Step | .github/workflows/test17.yml:12:15:19:12 | Uses Step | .github/workflows/test17.yml:19:15:23:58 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test17.yml:3:5:3:16 | workflow_run | workflow_run |
| .github/workflows/test27.yml:21:9:22:16 | Run Step | .github/workflows/test27.yml:18:9:21:6 | Uses Step | .github/workflows/test27.yml:21:9:22:16 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test26.yml:4:3:4:14 | workflow_run | workflow_run |
| .github/workflows/test29.yml:14:7:21:11 | Uses Step | .github/workflows/test29.yml:8:7:14:4 | Uses Step | .github/workflows/test29.yml:14:7:21:11 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test29.yml:1:5:1:23 | pull_request_target | pull_request_target |
| .github/workflows/untrusted_checkout3.yml:13:9:13:23 | Run Step | .github/actions/dangerous-git-checkout/action.yml:6:7:11:4 | Uses Step | .github/workflows/untrusted_checkout3.yml:13:9:13:23 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout3.yml:4:3:4:14 | workflow_run | workflow_run |
| .github/workflows/untrusted_checkout4.yml:35:7:41:4 | Run Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:35:7:41:4 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout4.yml:41:7:47:4 | Run Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:41:7:47:4 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout4.yml:47:7:51:46 | Run Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:47:7:51:46 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout.yml:15:9:18:2 | Run Step | .github/workflows/untrusted_checkout.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout.yml:15:9:18:2 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/untrusted_checkout.yml:30:9:32:23 | Run Step | .github/workflows/untrusted_checkout.yml:23:9:26:6 | Uses Step | .github/workflows/untrusted_checkout.yml:30:9:32:23 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/actions/dangerous-git-checkout/action.yml:6:7:11:4 | Uses Step | .github/actions/dangerous-git-checkout/action.yml:6:7:11:4 | Uses Step | .github/workflows/untrusted_checkout3.yml:13:9:13:23 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout3.yml:4:3:4:14 | workflow_run | workflow_run |
| .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:32:9:37:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:48:9:52:2 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:79:9:84:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:84:9:93:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/dependabot3.yml:3:5:3:23 | pull_request_target | pull_request_target |
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/reusable_caller1.yaml:4:3:4:21 | pull_request_target | pull_request_target |
| .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | .github/workflows/gitcheckout.yml:21:11:23:22 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/gitcheckout.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/label_trusted_checkout2.yml:12:7:16:4 | Uses Step | .github/workflows/label_trusted_checkout2.yml:12:7:16:4 | Uses Step | .github/workflows/label_trusted_checkout2.yml:17:7:21:4 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/label_trusted_checkout2.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:107:9:112:2 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/level0.yml:5:3:5:15 | issue_comment | issue_comment |
| .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:107:9:112:2 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/level0.yml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:133:9:135:23 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/level0.yml:5:3:5:15 | issue_comment | issue_comment |
| .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:133:9:135:23 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/level0.yml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:42:9:47:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/poc2.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:52:9:58:24 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/poc2.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/pr-workflow.yml:216:9:222:6 | Uses Step | .github/workflows/pr-workflow.yml:216:9:222:6 | Uses Step | .github/workflows/pr-workflow.yml:222:9:227:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:250:9:256:6 | Uses Step | .github/workflows/pr-workflow.yml:250:9:256:6 | Uses Step | .github/workflows/pr-workflow.yml:256:9:261:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:284:9:290:6 | Uses Step | .github/workflows/pr-workflow.yml:284:9:290:6 | Uses Step | .github/workflows/pr-workflow.yml:290:9:295:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:391:9:395:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:395:9:404:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:404:9:414:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:414:9:423:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:423:9:432:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/reusable_local.yml:23:9:26:6 | Uses Step | .github/workflows/reusable_local.yml:23:9:26:6 | Uses Step | .github/workflows/reusable_local.yml:26:9:29:7 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/reusable_caller3.yaml:4:3:4:21 | pull_request_target | pull_request_target |
| .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:33:9:36:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:36:9:39:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:49:9:59:6 | Run Step: benchmark-pr | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:59:9:60:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:60:9:60:37 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test10.yml:20:9:25:6 | Uses Step | .github/workflows/test10.yml:20:9:25:6 | Uses Step | .github/workflows/test10.yml:25:9:30:2 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test10.yml:8:3:8:21 | pull_request_target | pull_request_target |
| .github/workflows/test11.yml:84:7:90:4 | Uses Step | .github/workflows/test11.yml:84:7:90:4 | Uses Step | .github/workflows/test11.yml:90:7:93:54 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test11.yml:5:3:5:15 | issue_comment | issue_comment |
| .github/workflows/test17.yml:12:15:19:12 | Uses Step | .github/workflows/test17.yml:12:15:19:12 | Uses Step | .github/workflows/test17.yml:19:15:23:58 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test17.yml:3:5:3:16 | workflow_run | workflow_run |
| .github/workflows/test27.yml:18:9:21:6 | Uses Step | .github/workflows/test27.yml:18:9:21:6 | Uses Step | .github/workflows/test27.yml:21:9:22:16 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test26.yml:4:3:4:14 | workflow_run | workflow_run |
| .github/workflows/test29.yml:8:7:14:4 | Uses Step | .github/workflows/test29.yml:8:7:14:4 | Uses Step | .github/workflows/test29.yml:14:7:21:11 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test29.yml:1:5:1:23 | pull_request_target | pull_request_target |
| .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:35:7:41:4 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:41:7:47:4 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:47:7:51:46 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout.yml:15:9:18:2 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/untrusted_checkout.yml:23:9:26:6 | Uses Step | .github/workflows/untrusted_checkout.yml:23:9:26:6 | Uses Step | .github/workflows/untrusted_checkout.yml:30:9:32:23 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | pull_request_target |

View File

@@ -1,23 +1,23 @@
| .github/workflows/issue_comment_direct.yml:12:9:16:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_direct.yml:20:9:24:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_direct.yml:28:9:32:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_direct.yml:35:9:40:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_direct.yml:43:9:46:126 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_heuristic.yml:28:9:33:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_heuristic.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_heuristic.yml:48:7:50:46 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_heuristic.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit2.yml:27:9:31:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit2.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:26:9:30:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:30:9:35:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:57:9:62:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:79:9:83:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:95:9:100:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:109:9:114:66 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/pr-workflow.yml:103:9:109:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:139:9:144:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:444:9:449:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/test13.yml:20:7:25:4 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test13.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout2.yml:14:9:19:72 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout2.yml:1:5:1:17 | issue_comment | issue_comment |
| .github/workflows/workflow_run_untrusted_checkout.yml:13:9:16:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/workflow_run_untrusted_checkout.yml:2:3:2:14 | workflow_run | workflow_run |
| .github/workflows/workflow_run_untrusted_checkout.yml:16:9:18:31 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/workflow_run_untrusted_checkout.yml:2:3:2:14 | workflow_run | workflow_run |
| .github/workflows/workflow_run_untrusted_checkout_2.yml:13:9:16:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/workflow_run_untrusted_checkout_2.yml:2:3:2:14 | workflow_run | workflow_run |
| .github/workflows/workflow_run_untrusted_checkout_2.yml:16:9:18:31 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/workflow_run_untrusted_checkout_2.yml:2:3:2:14 | workflow_run | workflow_run |
| .github/workflows/issue_comment_direct.yml:12:9:16:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_direct.yml:20:9:24:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_direct.yml:28:9:32:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_direct.yml:35:9:40:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_direct.yml:43:9:46:126 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_heuristic.yml:28:9:33:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_heuristic.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_heuristic.yml:48:7:50:46 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_heuristic.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit2.yml:27:9:31:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit2.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:26:9:30:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:30:9:35:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:57:9:62:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:79:9:83:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:95:9:100:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:109:9:114:66 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/pr-workflow.yml:103:9:109:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:139:9:144:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:444:9:449:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/test13.yml:20:7:25:4 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test13.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout2.yml:14:9:19:72 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout2.yml:1:5:1:17 | issue_comment | issue_comment |
| .github/workflows/workflow_run_untrusted_checkout.yml:13:9:16:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/workflow_run_untrusted_checkout.yml:2:3:2:14 | workflow_run | workflow_run |
| .github/workflows/workflow_run_untrusted_checkout.yml:16:9:18:31 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/workflow_run_untrusted_checkout.yml:2:3:2:14 | workflow_run | workflow_run |
| .github/workflows/workflow_run_untrusted_checkout_2.yml:13:9:16:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/workflow_run_untrusted_checkout_2.yml:2:3:2:14 | workflow_run | workflow_run |
| .github/workflows/workflow_run_untrusted_checkout_2.yml:16:9:18:31 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/workflow_run_untrusted_checkout_2.yml:2:3:2:14 | workflow_run | workflow_run |

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
description: Support alias templates
compatibility: full
is_alias_template.rel: delete
alias_instantiation.rel: delete
alias_template_argument.rel: delete
alias_template_argument_value.rel: delete

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
description: Capture information about one template being generated from another
compatibility: full
class_template_generated_from.rel: delete
function_template_generated_from.rel: delete
variable_template_generated_from.rel: delete
alias_template_generated_from.rel: delete

View File

@@ -1,3 +1,9 @@
## 10.1.1
### Minor Analysis Improvements
* The `RemoteFlowSourceFunction` model for `fscanf` (and variants) now implements `hasSocketInput` to reflect that these functions may read from a socket.
## 10.1.0
### New Features

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* Added flow source models for `scanf_s` and related functions.
* Added a `Call` column to `LocalFlowSourceFunction::hasLocalFlowSource` and `RemoteFlowSourceFunction::hasRemoteFlowSource`. The old predicates without a `Call` column continue to be supported.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added `AliasTemplateType` and `AliasTemplateInstantiationType` classes, representing C++ alias templates and their instantiations.

View File

@@ -0,0 +1,4 @@
---
category: deprecated
---
* The `UsingAliasTypedefType` class has been deprecated. Use `TypeAliasType` instead.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added a `getOriginalTemplate` predicate to `TemplateClass`, `TemplateFunction`, `TemplateVariable`, and `AliasTemplateType`, which yields the class member template the template was generated from. The predicates only have results for templates that are members of class template instantiations.

View File

@@ -0,0 +1,5 @@
## 10.1.1
### Minor Analysis Improvements
* The `RemoteFlowSourceFunction` model for `fscanf` (and variants) now implements `hasSocketInput` to reflect that these functions may read from a socket.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 10.1.0
lastReleaseVersion: 10.1.1

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 10.1.1-dev
version: 10.1.2-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -856,8 +856,10 @@ class AbstractClass extends Class {
/**
* A class template (this class also finds partial specializations
* of class templates). For example in the following code there is a
* `MyTemplateClass<T>` template:
* of class templates).
*
* For example in the following code there is a `MyTemplateClass<T>`
* template:
* ```
* template<class T>
* class MyTemplateClass {
@@ -893,6 +895,29 @@ class TemplateClass extends Class {
}
override string getAPrimaryQlClass() { result = "TemplateClass" }
/**
* Gets the class member template this template was generated from.
*
* This predicate only has results for templates that are members of class
* template instantiations. For example, for `MyTemplateClass<int>::C<S>`
* in the following code, the result is `MyTemplateClass<T>::C<S>`.
* ```cpp
* template<class T>
* class MyTemplateClass {
* template<class S>
* class C {
* ...
* };
* };
*
* template
* class MyTemplateClass<int>;
* ```
*/
TemplateClass getOriginalTemplate() {
class_template_generated_from(underlyingElement(this), unresolveElement(result))
}
}
/**

View File

@@ -278,6 +278,8 @@ class Declaration extends Locatable, @declaration {
or
variable_template_argument(underlyingElement(this), index, unresolveElement(result))
or
alias_template_argument(underlyingElement(this), index, unresolveElement(result))
or
template_template_argument(underlyingElement(this), index, unresolveElement(result))
or
concept_template_argument(underlyingElement(this), index, unresolveElement(result))
@@ -290,6 +292,8 @@ class Declaration extends Locatable, @declaration {
or
variable_template_argument_value(underlyingElement(this), index, unresolveElement(result))
or
alias_template_argument_value(underlyingElement(this), index, unresolveElement(result))
or
template_template_argument_value(underlyingElement(this), index, unresolveElement(result))
or
concept_template_argument_value(underlyingElement(this), index, unresolveElement(result))

View File

@@ -278,6 +278,15 @@ private predicate isFromTemplateInstantiationRec(Element e, Element instantiatio
instantiation.(Variable).isConstructedFrom(_) and
e = instantiation
or
instantiation.(TypeAliasType).isConstructedFrom(_) and
e = instantiation
or
instantiation.(TemplateTemplateParameterInstantiation).isConstructedFrom(_) and
e = instantiation
or
exists(instantiation.(ConceptIdExpr).getConcept()) and
e = instantiation
or
isFromTemplateInstantiationRec(e.getEnclosingElement(), instantiation)
}
@@ -291,6 +300,15 @@ private predicate isFromUninstantiatedTemplateRec(Element e, Element template) {
is_variable_template(unresolveElement(template)) and
e = template
or
is_alias_template(unresolveElement(template)) and
e = template
or
usertypes(unresolveElement(template), _, 8) and // template template parameter
e = template
or
template instanceof @concept_template and
e = template
or
isFromUninstantiatedTemplateRec(e.getEnclosingElement(), template)
}

View File

@@ -828,6 +828,27 @@ class TemplateFunction extends Function {
* such things -- see FunctionTemplateSpecialization for further details.
*/
FunctionTemplateSpecialization getASpecialization() { result.getPrimaryTemplate() = this }
/**
* Gets the class member template this template was generated from.
*
* This predicate only has results for templates that are members of class
* template instantiations. For example, for `MyTemplateClass<int>::f<S>`
* in the following code, the result is `MyTemplateClass<T>::f<S>`.
* ```cpp
* template<class T>
* class MyTemplateClass {
* template<class S>
* S f();
* };
*
* template
* class MyTemplateClass<int>;
* ```
*/
TemplateFunction getOriginalTemplate() {
function_template_generated_from(underlyingElement(this), unresolveElement(result))
}
}
/**

View File

@@ -64,23 +64,123 @@ class CTypedefType extends TypedefType {
}
/**
* A using alias C++ typedef type. For example the type declared in the following code:
* DEPRECATED: Use `TypeAlias` instead.
*
* A C++ type alias or alias template.
*
* For example the type declared in the following code:
* ```
* using my_int2 = int;
* ```
*/
class UsingAliasTypedefType extends TypedefType {
UsingAliasTypedefType() { usertype_alias_kind(underlyingElement(this), 1) }
deprecated class UsingAliasTypedefType = TypeAliasType;
override string getAPrimaryQlClass() { result = "UsingAliasTypedefType" }
/**
* A C++ type alias or alias template.
*
* For example the type declared in the following code:
* ```
* using my_int2 = int;
* ```
*/
class TypeAliasType extends TypedefType {
TypeAliasType() { usertype_alias_kind(underlyingElement(this), 1) }
override string getAPrimaryQlClass() { result = "TypeAliasType" }
override string explain() {
result = "using {" + this.getBaseType().explain() + "} as \"" + this.getName() + "\""
}
/**
* Holds if this alias is constructed from another alias as a result of
* template instantiation.
*/
predicate isConstructedFrom(TypeAliasType t) {
alias_instantiation(underlyingElement(this), unresolveElement(t))
}
}
/**
* A C++ `typedef` type that is directly enclosed by a function. For example the type declared inside the function `foo` in
* A C++ alias template.
*
* For example the type declared in the following code:
* ```
* template <typename T>
* using my_type = T;
* ```
*/
class AliasTemplateType extends TypeAliasType {
AliasTemplateType() { is_alias_template(underlyingElement(this)) }
override string getAPrimaryQlClass() { result = "AliasTemplateType" }
/**
* Gets an alias instantiated from this template.
*
* For example for `MyAliasTemplate<T>` in the following code, the results are
* `MyAliasTemplate<int>` and `MyAliasTemplate<long>`:
* ```
* template<typename T>
* using MyAliasTemplate = ...;
*
* MyAliasTemplate<int> instance1;
*
* MyAliasTemplate<long> instance2;
* ```
*/
TypeAliasType getAnInstantiation() { result.isConstructedFrom(this) }
/**
* Gets the class member template this template was generated from.
*
* This predicate only has results for templates that are members of class
* template instantiations. For example, for `MyTemplateClass<int>::t<S>`
* in the following code, the result is `MyTemplateClass<T>::t<S>`.
* ```cpp
* template<class T>
* class MyTemplateClass {
* template<class S>
* using t = S;
* };
*
* template
* class MyTemplateClass<int>;
* ```
*/
AliasTemplateType getOriginalTemplate() {
alias_template_generated_from(underlyingElement(this), unresolveElement(result))
}
}
/**
* A C++ alias template instantiation.
*
* For example the `my_int_type` type declared in the following code:
* ```
* template <typename T>
* using my_type = T;
*
* using my_int_type = my_type<int>;
* ```
*/
class AliasTemplateInstantiationType extends TypeAliasType {
AliasTemplateType at;
AliasTemplateInstantiationType() { at.getAnInstantiation() = this }
override string getAPrimaryQlClass() { result = "AliasTemplateInstantiationType" }
/**
* Gets the alias template from which this instantiation was instantiated.
*/
AliasTemplateType getTemplate() { result = at }
}
/**
* A C++ `typedef` type that is directly enclosed by a function.
*
* For example the type declared inside the function `foo` in
* the following code:
* ```
* int foo(void) { typedef int local; }

View File

@@ -614,6 +614,27 @@ class TemplateVariable extends Variable {
result.isConstructedFrom(this) and
not result.isSpecialization()
}
/**
* Gets the class member template this template was generated from.
*
* This predicate only has results for templates that are members of class
* template instantiations. For example, for `MyTemplateClass<int>::x<S>`
* in the following code, the result is `MyTemplateClass<T>::x<S>`.
* ```cpp
* template<class T>
* class MyTemplateClass {
* template<class S>
* static S x;
* };
*
* template
* class MyTemplateClass<int>;
* ```
*/
TemplateVariable getOriginalTemplate() {
variable_template_generated_from(underlyingElement(this), unresolveElement(result))
}
}
/**

View File

@@ -25,6 +25,15 @@ abstract class ScanfFunction extends Function {
* (rather than a `char*`).
*/
predicate isWideCharDefault() { exists(this.getName().indexOf("wscanf")) }
/** Holds if this is one of the `scanf_s` variants. */
predicate isSVariant() {
exists(string name | name = this.getName() |
name.matches("%\\_s")
or
name.matches("%\\_s\\_l")
)
}
}
/**
@@ -34,8 +43,12 @@ class Scanf extends ScanfFunction instanceof TopLevelFunction {
Scanf() {
this.hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...)
this.hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...)
this.hasGlobalOrStdOrBslName("scanf_s") or // scanf_s(format, args...)
this.hasGlobalOrStdOrBslName("wscanf_s") or // wscanf_s(format, args...)
this.hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...)
this.hasGlobalName("_wscanf_l")
this.hasGlobalName("_wscanf_l") or // _wscanf_l(format, locale, args...)
this.hasGlobalName("_scanf_s_l") or // _scanf_s_l(format, locale, args...)
this.hasGlobalName("_wscanf_s_l") // _wscanf_s_l(format, locale, args...)
}
override int getInputParameterIndex() { none() }
@@ -50,8 +63,12 @@ class Fscanf extends ScanfFunction instanceof TopLevelFunction {
Fscanf() {
this.hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...)
this.hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...)
this.hasGlobalOrStdOrBslName("fscanf_s") or // fscanf_s(src_stream, format, args...)
this.hasGlobalOrStdOrBslName("fwscanf_s") or // fwscanf_s(src_stream, format, args...)
this.hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...)
this.hasGlobalName("_fwscanf_l")
this.hasGlobalName("_fwscanf_l") or // _fwscanf_l(src_stream, format, locale, args...)
this.hasGlobalName("_fscanf_s_l") or // _fscanf_s_l(src_stream, format, locale, args...)
this.hasGlobalName("_fwscanf_s_l") // _fwscanf_s_l(src_stream, format, locale, args...)
}
override int getInputParameterIndex() { result = 0 }
@@ -66,8 +83,12 @@ class Sscanf extends ScanfFunction instanceof TopLevelFunction {
Sscanf() {
this.hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...)
this.hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...)
this.hasGlobalOrStdOrBslName("sscanf_s") or // sscanf_s(src, format, args...)
this.hasGlobalOrStdOrBslName("swscanf_s") or // swscanf_s(src, format, args...)
this.hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...)
this.hasGlobalName("_swscanf_l")
this.hasGlobalName("_swscanf_l") or // _swscanf_l(src, format, locale, args...)
this.hasGlobalName("_sscanf_s_l") or // _sscanf_s_l(src, format, locale, args...)
this.hasGlobalName("_swscanf_s_l") // _swscanf_s_l(src, format, locale, args...)
}
override int getInputParameterIndex() { result = 0 }
@@ -97,6 +118,14 @@ class Snscanf extends ScanfFunction instanceof TopLevelFunction {
int getInputLengthParameterIndex() { result = 1 }
}
private predicate isCharLike(Type t) { t instanceof CharType or t instanceof Wchar_t }
private predicate isStringLike(Type t) {
isCharLike(t.(PointerType).getBaseType())
or
isCharLike(t.(ArrayType).getBaseType())
}
/**
* A call to one of the `scanf` functions.
*/
@@ -130,14 +159,40 @@ class ScanfFunctionCall extends FunctionCall {
*/
predicate isWideCharDefault() { this.getScanfFunction().isWideCharDefault() }
bindingset[this, k]
pragma[inline_late]
private predicate isSizeArgument(int k) {
// The first vararg is never the size argument since a size argument must
// always follow a string buffer argument.
k > 0 and
isStringLike(this.getArgument(this.getScanfFunction().getNumberOfParameters() + k - 1)
.getUnspecifiedType())
}
/**
* Gets the output argument at position `n` in the vararg list of this call.
*
* The range of `n` is from `0` to `this.getNumberOfOutputArguments() - 1`.
*/
Expr getOutputArgument(int n) {
result = this.getArgument(this.getTarget().getNumberOfParameters() + n) and
n >= 0
exists(ScanfFunction target | target = this.getScanfFunction() |
// If this is an S variant then every string buffer argument has a
// corresponding size argument immediately following it, so we need to
// skip over those size arguments when counting the output arguments.
if target.isSVariant()
then
result =
rank[n + 1](Expr arg, int k |
k >= 0 and
arg = this.getArgument(target.getNumberOfParameters() + k) and
not this.isSizeArgument(k)
|
arg order by k
)
else (
n >= 0 and result = this.getArgument(target.getNumberOfParameters() + n)
)
)
}
/**

View File

@@ -136,7 +136,9 @@ private module SourceVariables {
NormalSourceVariable() { this = TNormalSourceVariable(base, ind) }
final override string toString() {
result = repeatStars(this.getIndirection()) + base.toString()
if this.getIndirection() = 0
then result = "&" + base.toString()
else result = repeatStars(this.getIndirection() - 1) + base.toString()
}
}
@@ -157,7 +159,9 @@ private module SourceVariables {
}
final override string toString() {
result = repeatStars(this.getIndirection()) + base.toString() + " [before crement]"
if this.getIndirection() = 0
then result = "&" + base.toString() + " [before crement]"
else result = repeatStars(this.getIndirection() - 1) + base.toString() + " [before crement]"
}
/**
@@ -1353,6 +1357,52 @@ class PhiNode extends Definition instanceof SsaImpl::PhiNode {
final predicate hasInputFromBlock(Definition input, IRBlock bb) {
phiHasInputFromBlock(this, input, bb)
}
override int getIndirection() { result = this.getSourceVariable().getIndirection() }
override predicate isCertain() {
// If this phi node is part of a phi cycle of phi nodes the least
// fixed-point semantics of datalog means we don't get the right answer.
// So we perform an SCC reduction to simulate greatest fixed-point semantics.
getCycle(this).isCertain()
or
// If there is no cycle we get the right semantics through traditional
// recursion.
not exists(getCycle(this)) and
forex(Definition inp | inp = this.getAnInput() | inp.isCertain())
}
final override Declaration getFunction() {
result = SsaImpl::PhiNode.super.getBasicBlock().getEnclosingFunction()
}
}
private PhiNode getAnInput(PhiNode phi) { result = phi.getAnInput() }
private predicate sccEdge(PhiNode phi1, PhiNode phi2) {
getAnInput(phi1) = phi2 and getAnInput+(phi2) = phi1
}
private module PhiCycleEquivalence = QlBuiltins::EquivalenceRelation<PhiNode, sccEdge/2>;
private PhiCycle getCycle(PhiNode phi) { result.getAPhiNode() = phi }
private class PhiCycle extends PhiCycleEquivalence::EquivalenceClass {
PhiNode getAPhiNode() { PhiCycleEquivalence::getEquivalenceClass(result) = this }
predicate hasPhiNode(PhiNode phi) { this.getAPhiNode() = phi }
pragma[nomagic]
Definition getAnInput() {
result = this.getAPhiNode().getAnInput() and not this.hasPhiNode(result)
}
string toString() { result = strictconcat(this.getAPhiNode().toString(), ", ") }
predicate isCertain() {
// A phi cycle is certain if all of the inputs into the phi cycle is certain.
forex(Definition inp | inp = this.getAnInput() | inp.isCertain())
}
}
/** An static single assignment (SSA) definition. */

View File

@@ -147,7 +147,7 @@ abstract class Indirection extends Type {
*
* `certain` is `true` if this write is guaranteed to write to the address.
*/
predicate isAdditionalWrite(Node0Impl value, Operand address, boolean certain) { none() }
predicate isAdditionalWrite(Node0Impl value, Operand address, Certainty certain) { none() }
/**
* Gets the base type of this indirection, after specifiers have been deeply
@@ -198,11 +198,11 @@ private module IteratorIndirections {
baseType = super.getValueType()
}
override predicate isAdditionalWrite(Node0Impl value, Operand address, boolean certain) {
override predicate isAdditionalWrite(Node0Impl value, Operand address, Certainty certain) {
exists(CallInstruction call | call.getArgumentOperand(0) = value.asOperand() |
this = call.getStaticCallTarget().(Function).getClassAndName("operator=") and
address = call.getThisArgumentOperand() and
certain = false
certain instanceof AlwaysUncertain
)
}
@@ -271,30 +271,62 @@ predicate isDereference(Instruction deref, Operand address, boolean additional)
additional = false
}
predicate isWrite(Node0Impl value, Operand address, boolean certain) {
private newtype TCertainty =
TCertainWhenAddressIsCertain() or
TAlwaysCertain() or
TAlwaysUncertain()
abstract private class Certainty extends TCertainty {
abstract predicate isCertain(boolean addressIsCertain);
abstract string toString();
}
private class CertainWhenAddressIsCertain extends Certainty, TCertainWhenAddressIsCertain {
override predicate isCertain(boolean addressIsCertain) { addressIsCertain = true }
override string toString() { result = "CertainWhenAddressIsCertain" }
}
private class AlwaysCertain extends Certainty, TAlwaysCertain {
override predicate isCertain(boolean addressIsCertain) {
addressIsCertain = true or addressIsCertain = false
}
override string toString() { result = "AlwaysCertain" }
}
private class AlwaysUncertain extends Certainty, TAlwaysUncertain {
override predicate isCertain(boolean addressIsCertain) { none() }
override string toString() { result = "AlwaysUncertain" }
}
predicate isWrite(Node0Impl value, Operand address, Certainty certain) {
any(Indirection ind).isAdditionalWrite(value, address, certain)
or
certain = true and
(
exists(StoreInstruction store |
value.asInstruction() = store and
address = store.getDestinationAddressOperand()
)
or
exists(InitializeParameterInstruction init |
value.asInstruction() = init and
address = init.getAnOperand()
)
or
exists(InitializeDynamicAllocationInstruction init |
value.asInstruction() = init and
address = init.getAllocationAddressOperand()
)
or
exists(UninitializedInstruction uninitialized |
value.asInstruction() = uninitialized and
address = uninitialized.getAnOperand()
)
exists(StoreInstruction store |
value.asInstruction() = store and
address = store.getDestinationAddressOperand() and
certain instanceof CertainWhenAddressIsCertain
)
or
exists(InitializeParameterInstruction init |
value.asInstruction() = init and
address = init.getAnOperand() and
certain instanceof AlwaysCertain
)
or
exists(InitializeDynamicAllocationInstruction init |
value.asInstruction() = init and
address = init.getAllocationAddressOperand() and
certain instanceof AlwaysCertain
)
or
exists(UninitializedInstruction uninitialized |
value.asInstruction() = uninitialized and
address = uninitialized.getAnOperand() and
certain instanceof AlwaysCertain
)
}
@@ -718,16 +750,18 @@ private module Cached {
int indirectionIndex
) {
exists(
boolean writeIsCertain, boolean addressIsCertain, int ind0, CppType type, int lower, int upper
Certainty writeIsCertain, boolean addressIsCertain, int ind0, CppType type, int lower,
int upper
|
isWrite(value, address, writeIsCertain) and
isDefImpl(address, base, ind0, addressIsCertain) and
certain = writeIsCertain.booleanAnd(addressIsCertain) and
type = getLanguageType(address) and
upper = countIndirectionsForCppType(type) and
ind = ind0 + [lower .. upper] and
indirectionIndex = ind - (ind0 + lower) and
lower = getMinIndirectionsForType(any(Type t | type.hasUnspecifiedType(t, _)))
|
if writeIsCertain.isCertain(addressIsCertain) then certain = true else certain = false
)
}

View File

@@ -11,7 +11,9 @@ private class Fopen extends Function, AliasFunction, SideEffectFunction, TaintFu
Fopen() {
this.hasGlobalOrStdName(["fopen", "fopen_s", "freopen"])
or
this.hasGlobalName(["_open", "_wfopen", "_fsopen", "_wfsopen", "_wopen"])
this.hasGlobalName([
"_open", "_wfopen", "_fsopen", "_wfsopen", "_wopen", "_sopen_s", "_wsopen_s"
])
}
override predicate hasOnlySpecificWriteSideEffects() { any() }
@@ -46,6 +48,10 @@ private class Fopen extends Function, AliasFunction, SideEffectFunction, TaintFu
this.hasGlobalName(["_open", "_wopen"]) and
i = 0 and
buffer = true
or
this.hasGlobalName(["_sopen_s", "_wsopen_s"]) and
i = 1 and
buffer = true
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -64,5 +70,9 @@ private class Fopen extends Function, AliasFunction, SideEffectFunction, TaintFu
this.hasGlobalName(["_open", "_wopen"]) and
input.isParameterDeref(0) and
output.isReturnValue()
or
this.hasGlobalName(["_sopen_s", "_wsopen_s"]) and
input.isParameterDeref(1) and
output.isParameterDeref(0)
}
}

View File

@@ -30,7 +30,10 @@ abstract private class ScanfFunctionModel extends ArrayFunction, TaintFunction,
(
if exists(this.getLengthParameterIndex())
then result = this.getLengthParameterIndex() + 2
else result = 2
else
if exists(this.(ScanfFunction).getInputParameterIndex())
then result = 2
else result = 1
)
}
@@ -69,13 +72,24 @@ abstract private class ScanfFunctionModel extends ArrayFunction, TaintFunction,
}
}
private predicate hasFlowSource(
ScanfFunction func, ScanfFunctionCall call, FunctionOutput output, string description
) {
exists(int n, Expr arg |
call.getScanfFunction() = func and
call.getOutputArgument(_) = arg and
call.getArgument(n) = arg and
output.isParameterDeref(n) and
description = "value read by " + func.getName()
)
}
/**
* The standard function `scanf` and its assorted variants
*/
private class ScanfModel extends ScanfFunctionModel, LocalFlowSourceFunction instanceof Scanf {
override predicate hasLocalFlowSource(FunctionOutput output, string description) {
output.isParameterDeref(any(int i | i >= this.getArgsStartPosition())) and
description = "value read by " + this.getName()
override predicate hasLocalFlowSource(Call call, FunctionOutput output, string description) {
hasFlowSource(this, call, output, description)
}
}
@@ -83,9 +97,12 @@ private class ScanfModel extends ScanfFunctionModel, LocalFlowSourceFunction ins
* The standard function `fscanf` and its assorted variants
*/
private class FscanfModel extends ScanfFunctionModel, RemoteFlowSourceFunction instanceof Fscanf {
override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
output.isParameterDeref(any(int i | i >= this.getArgsStartPosition())) and
description = "value read by " + this.getName()
override predicate hasRemoteFlowSource(Call call, FunctionOutput output, string description) {
hasFlowSource(this, call, output, description)
}
override predicate hasSocketInput(FunctionInput input) {
input.isParameterDeref(super.getInputParameterIndex())
}
}

View File

@@ -18,7 +18,17 @@ abstract class RemoteFlowSourceFunction extends Function {
/**
* Holds if remote data described by `description` flows from `output` of a call to this function.
*/
abstract predicate hasRemoteFlowSource(FunctionOutput output, string description);
predicate hasRemoteFlowSource(FunctionOutput output, string description) {
this.hasRemoteFlowSource(_, output, description)
}
/**
* Holds if remote data described by `description` flows from `output` of `call` to this function.
*/
predicate hasRemoteFlowSource(Call call, FunctionOutput output, string description) {
call.getTarget() = this and
this.hasRemoteFlowSource(output, description)
}
/**
* Holds if remote data from this source comes from a socket or stream
@@ -35,7 +45,17 @@ abstract class LocalFlowSourceFunction extends Function {
/**
* Holds if data described by `description` flows from `output` of a call to this function.
*/
abstract predicate hasLocalFlowSource(FunctionOutput output, string description);
predicate hasLocalFlowSource(FunctionOutput output, string description) {
this.hasLocalFlowSource(_, output, description)
}
/**
* Holds if data described by `description` flows from `output` of `call` to this function.
*/
predicate hasLocalFlowSource(Call call, FunctionOutput output, string description) {
call.getTarget() = this and
this.hasLocalFlowSource(output, description)
}
}
/** A library function that sends data over a network connection. */

View File

@@ -28,8 +28,7 @@ private class RemoteModelSource extends RemoteFlowSource {
RemoteModelSource() {
exists(CallInstruction call, RemoteFlowSourceFunction func, FunctionOutput output |
call.getStaticCallTarget() = func and
func.hasRemoteFlowSource(output, sourceType) and
func.hasRemoteFlowSource(call.getConvertedResultExpression(), output, sourceType) and
this = callOutput(call, output)
)
}
@@ -46,7 +45,7 @@ private class LocalModelSource extends LocalFlowSource {
LocalModelSource() {
exists(CallInstruction call, LocalFlowSourceFunction func, FunctionOutput output |
call.getStaticCallTarget() = func and
func.hasLocalFlowSource(output, sourceType) and
func.hasLocalFlowSource(call.getConvertedResultExpression(), output, sourceType) and
this = callOutput(call, output)
)
}

View File

@@ -912,6 +912,10 @@ class_template_argument_value(
int index: int ref,
int arg_value: @expr ref
);
class_template_generated_from(
unique int template: @usertype ref,
int from: @usertype ref
)
@user_or_decltype = @usertype | @decltype;
@@ -943,6 +947,10 @@ function_template_argument_value(
int index: int ref,
int arg_value: @expr ref
);
function_template_generated_from(
unique int template: @function ref,
int from: @function ref
);
is_variable_template(unique int id: @variable ref);
variable_instantiation(
@@ -959,6 +967,30 @@ variable_template_argument_value(
int index: int ref,
int arg_value: @expr ref
);
variable_template_generated_from(
unique int template: @variable ref,
int from: @variable ref
);
is_alias_template(unique int id: @usertype ref);
alias_instantiation(
unique int to: @usertype ref,
int from: @usertype ref
);
alias_template_argument(
int type_id: @usertype ref,
int index: int ref,
int arg_type: @type ref
);
alias_template_argument_value(
int type_id: @usertype ref,
int index: int ref,
int arg_value: @expr ref
);
alias_template_generated_from(
unique int template: @usertype ref,
int from: @usertype ref
);
template_template_instantiation(
int to: @usertype ref,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Support alias templates
compatibility: backwards

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Capture information about one template being generated from another
compatibility: backwards

View File

@@ -1,3 +1,9 @@
## 1.6.3
### Minor Analysis Improvements
* The 'Cleartext transmission of sensitive information' query (`cpp/cleartext-transmission`) no longer raises an alert on calls to `fscanf` (and variants) when the call reads from an "obviously local" `FILE` stream such as `stdin`.
## 1.6.2
No user-facing changes.

View File

@@ -44,10 +44,7 @@ class ExternalApiDataNode extends DataFlow::Node {
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(RemoteFlowSourceFunction remoteFlow |
remoteFlow = source.asExpr().(Call).getTarget() and
remoteFlow.hasRemoteFlowSource(_, _)
)
any(RemoteFlowSourceFunction remoteFlow).hasRemoteFlowSource(source.asExpr(), _, _)
}
predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }

View File

@@ -94,9 +94,8 @@ class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
}
override Expr getDataExpr(Call call) {
call.getTarget() = this and
exists(FunctionOutput output, int arg |
super.hasRemoteFlowSource(output, _) and
super.hasRemoteFlowSource(call, output, _) and
output.isParameterDeref(arg) and
result = call.getArgument(arg)
)

View File

@@ -0,0 +1,5 @@
## 1.6.3
### Minor Analysis Improvements
* The 'Cleartext transmission of sensitive information' query (`cpp/cleartext-transmission`) no longer raises an alert on calls to `fscanf` (and variants) when the call reads from an "obviously local" `FILE` stream such as `stdin`.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.6.2
lastReleaseVersion: 1.6.3

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.6.3-dev
version: 1.6.4-dev
groups:
- cpp
- queries

View File

@@ -21,11 +21,7 @@ edges
| test.cpp:85:21:85:36 | buf | test.cpp:87:5:87:31 | access to array | provenance | Config |
| test.cpp:85:21:85:36 | buf | test.cpp:88:5:88:27 | access to array | provenance | Config |
| test.cpp:85:34:85:36 | buf | test.cpp:85:21:85:36 | buf | provenance | |
| test.cpp:92:9:92:11 | definition of arr | test.cpp:96:13:96:18 | access to array | provenance | Config |
| test.cpp:96:13:96:15 | arr | test.cpp:96:13:96:18 | access to array | provenance | Config |
| test.cpp:102:9:102:11 | definition of arr | test.cpp:111:17:111:22 | access to array | provenance | Config |
| test.cpp:102:9:102:11 | definition of arr | test.cpp:115:35:115:40 | access to array | provenance | Config |
| test.cpp:102:9:102:11 | definition of arr | test.cpp:119:17:119:22 | access to array | provenance | Config |
| test.cpp:111:17:111:19 | arr | test.cpp:111:17:111:22 | access to array | provenance | Config |
| test.cpp:111:17:111:19 | arr | test.cpp:115:35:115:40 | access to array | provenance | Config |
| test.cpp:111:17:111:19 | arr | test.cpp:119:17:119:22 | access to array | provenance | Config |
@@ -35,55 +31,41 @@ edges
| test.cpp:119:17:119:19 | arr | test.cpp:111:17:111:22 | access to array | provenance | Config |
| test.cpp:119:17:119:19 | arr | test.cpp:115:35:115:40 | access to array | provenance | Config |
| test.cpp:119:17:119:19 | arr | test.cpp:119:17:119:22 | access to array | provenance | Config |
| test.cpp:125:11:125:13 | definition of arr | test.cpp:128:9:128:14 | access to array | provenance | Config |
| test.cpp:128:9:128:11 | arr | test.cpp:128:9:128:14 | access to array | provenance | Config |
| test.cpp:134:25:134:27 | arr | test.cpp:136:9:136:16 | ... += ... | provenance | Config |
| test.cpp:136:9:136:16 | ... += ... | test.cpp:136:9:136:16 | ... += ... | provenance | |
| test.cpp:136:9:136:16 | ... += ... | test.cpp:138:13:138:15 | arr | provenance | |
| test.cpp:142:10:142:13 | definition of asdf | test.cpp:143:18:143:21 | asdf | provenance | |
| test.cpp:143:18:143:21 | asdf | test.cpp:134:25:134:27 | arr | provenance | |
| test.cpp:143:18:143:21 | asdf | test.cpp:143:18:143:21 | asdf | provenance | |
| test.cpp:146:26:146:26 | *p | test.cpp:147:4:147:9 | -- ... | provenance | |
| test.cpp:146:26:146:26 | *p | test.cpp:147:4:147:9 | -- ... | provenance | |
| test.cpp:154:7:154:9 | definition of buf | test.cpp:156:12:156:18 | ... + ... | provenance | Config |
| test.cpp:156:12:156:14 | buf | test.cpp:156:12:156:18 | ... + ... | provenance | Config |
| test.cpp:156:12:156:18 | ... + ... | test.cpp:156:12:156:18 | ... + ... | provenance | |
| test.cpp:156:12:156:18 | ... + ... | test.cpp:158:17:158:18 | *& ... | provenance | |
| test.cpp:158:17:158:18 | *& ... | test.cpp:146:26:146:26 | *p | provenance | |
| test.cpp:217:19:217:24 | definition of buffer | test.cpp:218:16:218:28 | buffer | provenance | |
| test.cpp:218:16:218:28 | buffer | test.cpp:220:5:220:11 | access to array | provenance | Config |
| test.cpp:218:16:218:28 | buffer | test.cpp:221:5:221:11 | access to array | provenance | Config |
| test.cpp:218:23:218:28 | buffer | test.cpp:218:16:218:28 | buffer | provenance | |
| test.cpp:228:10:228:14 | definition of array | test.cpp:229:17:229:29 | array | provenance | |
| test.cpp:229:17:229:29 | array | test.cpp:231:5:231:10 | access to array | provenance | Config |
| test.cpp:229:17:229:29 | array | test.cpp:232:5:232:10 | access to array | provenance | Config |
| test.cpp:229:25:229:29 | array | test.cpp:229:17:229:29 | array | provenance | |
| test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array | provenance | Config |
| test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array | provenance | Config |
| test.cpp:273:19:273:25 | definition of buffer3 | test.cpp:274:14:274:20 | buffer3 | provenance | |
| test.cpp:274:14:274:20 | buffer3 | test.cpp:245:30:245:30 | p | provenance | |
| test.cpp:274:14:274:20 | buffer3 | test.cpp:274:14:274:20 | buffer3 | provenance | |
| test.cpp:277:35:277:35 | p | test.cpp:278:14:278:14 | p | provenance | |
| test.cpp:278:14:278:14 | p | test.cpp:245:30:245:30 | p | provenance | |
| test.cpp:282:19:282:25 | definition of buffer1 | test.cpp:283:19:283:25 | buffer1 | provenance | |
| test.cpp:283:19:283:25 | buffer1 | test.cpp:277:35:277:35 | p | provenance | |
| test.cpp:283:19:283:25 | buffer1 | test.cpp:283:19:283:25 | buffer1 | provenance | |
| test.cpp:285:19:285:25 | definition of buffer2 | test.cpp:286:19:286:25 | buffer2 | provenance | |
| test.cpp:286:19:286:25 | buffer2 | test.cpp:277:35:277:35 | p | provenance | |
| test.cpp:286:19:286:25 | buffer2 | test.cpp:286:19:286:25 | buffer2 | provenance | |
| test.cpp:288:19:288:25 | definition of buffer3 | test.cpp:289:19:289:25 | buffer3 | provenance | |
| test.cpp:289:19:289:25 | buffer3 | test.cpp:277:35:277:35 | p | provenance | |
| test.cpp:289:19:289:25 | buffer3 | test.cpp:289:19:289:25 | buffer3 | provenance | |
| test.cpp:292:25:292:27 | arr | test.cpp:299:16:299:21 | access to array | provenance | Config |
| test.cpp:305:9:305:12 | definition of arr1 | test.cpp:306:20:306:23 | arr1 | provenance | |
| test.cpp:306:20:306:23 | arr1 | test.cpp:292:25:292:27 | arr | provenance | |
| test.cpp:306:20:306:23 | arr1 | test.cpp:306:20:306:23 | arr1 | provenance | |
| test.cpp:308:9:308:12 | definition of arr2 | test.cpp:309:20:309:23 | arr2 | provenance | |
| test.cpp:309:20:309:23 | arr2 | test.cpp:292:25:292:27 | arr | provenance | |
| test.cpp:309:20:309:23 | arr2 | test.cpp:309:20:309:23 | arr2 | provenance | |
| test.cpp:314:10:314:13 | definition of temp | test.cpp:319:19:319:27 | ... + ... | provenance | Config |
| test.cpp:314:10:314:13 | definition of temp | test.cpp:322:19:322:27 | ... + ... | provenance | Config |
| test.cpp:314:10:314:13 | definition of temp | test.cpp:324:23:324:32 | ... + ... | provenance | Config |
| test.cpp:319:13:319:27 | ... = ... | test.cpp:325:24:325:26 | end | provenance | |
| test.cpp:319:19:319:22 | temp | test.cpp:319:19:319:27 | ... + ... | provenance | Config |
| test.cpp:319:19:319:22 | temp | test.cpp:324:23:324:32 | ... + ... | provenance | Config |
@@ -133,40 +115,33 @@ nodes
| test.cpp:85:34:85:36 | buf | semmle.label | buf |
| test.cpp:87:5:87:31 | access to array | semmle.label | access to array |
| test.cpp:88:5:88:27 | access to array | semmle.label | access to array |
| test.cpp:92:9:92:11 | definition of arr | semmle.label | definition of arr |
| test.cpp:96:13:96:15 | arr | semmle.label | arr |
| test.cpp:96:13:96:18 | access to array | semmle.label | access to array |
| test.cpp:102:9:102:11 | definition of arr | semmle.label | definition of arr |
| test.cpp:111:17:111:19 | arr | semmle.label | arr |
| test.cpp:111:17:111:22 | access to array | semmle.label | access to array |
| test.cpp:115:35:115:37 | arr | semmle.label | arr |
| test.cpp:115:35:115:40 | access to array | semmle.label | access to array |
| test.cpp:119:17:119:19 | arr | semmle.label | arr |
| test.cpp:119:17:119:22 | access to array | semmle.label | access to array |
| test.cpp:125:11:125:13 | definition of arr | semmle.label | definition of arr |
| test.cpp:128:9:128:11 | arr | semmle.label | arr |
| test.cpp:128:9:128:14 | access to array | semmle.label | access to array |
| test.cpp:134:25:134:27 | arr | semmle.label | arr |
| test.cpp:136:9:136:16 | ... += ... | semmle.label | ... += ... |
| test.cpp:136:9:136:16 | ... += ... | semmle.label | ... += ... |
| test.cpp:138:13:138:15 | arr | semmle.label | arr |
| test.cpp:142:10:142:13 | definition of asdf | semmle.label | definition of asdf |
| test.cpp:143:18:143:21 | asdf | semmle.label | asdf |
| test.cpp:143:18:143:21 | asdf | semmle.label | asdf |
| test.cpp:146:26:146:26 | *p | semmle.label | *p |
| test.cpp:147:4:147:9 | -- ... | semmle.label | -- ... |
| test.cpp:147:4:147:9 | -- ... | semmle.label | -- ... |
| test.cpp:154:7:154:9 | definition of buf | semmle.label | definition of buf |
| test.cpp:156:12:156:14 | buf | semmle.label | buf |
| test.cpp:156:12:156:18 | ... + ... | semmle.label | ... + ... |
| test.cpp:156:12:156:18 | ... + ... | semmle.label | ... + ... |
| test.cpp:158:17:158:18 | *& ... | semmle.label | *& ... |
| test.cpp:217:19:217:24 | definition of buffer | semmle.label | definition of buffer |
| test.cpp:218:16:218:28 | buffer | semmle.label | buffer |
| test.cpp:218:23:218:28 | buffer | semmle.label | buffer |
| test.cpp:220:5:220:11 | access to array | semmle.label | access to array |
| test.cpp:221:5:221:11 | access to array | semmle.label | access to array |
| test.cpp:228:10:228:14 | definition of array | semmle.label | definition of array |
| test.cpp:229:17:229:29 | array | semmle.label | array |
| test.cpp:229:25:229:29 | array | semmle.label | array |
| test.cpp:231:5:231:10 | access to array | semmle.label | access to array |
@@ -174,29 +149,22 @@ nodes
| test.cpp:245:30:245:30 | p | semmle.label | p |
| test.cpp:245:30:245:30 | p | semmle.label | p |
| test.cpp:261:27:261:30 | access to array | semmle.label | access to array |
| test.cpp:273:19:273:25 | definition of buffer3 | semmle.label | definition of buffer3 |
| test.cpp:274:14:274:20 | buffer3 | semmle.label | buffer3 |
| test.cpp:274:14:274:20 | buffer3 | semmle.label | buffer3 |
| test.cpp:277:35:277:35 | p | semmle.label | p |
| test.cpp:278:14:278:14 | p | semmle.label | p |
| test.cpp:282:19:282:25 | definition of buffer1 | semmle.label | definition of buffer1 |
| test.cpp:283:19:283:25 | buffer1 | semmle.label | buffer1 |
| test.cpp:283:19:283:25 | buffer1 | semmle.label | buffer1 |
| test.cpp:285:19:285:25 | definition of buffer2 | semmle.label | definition of buffer2 |
| test.cpp:286:19:286:25 | buffer2 | semmle.label | buffer2 |
| test.cpp:286:19:286:25 | buffer2 | semmle.label | buffer2 |
| test.cpp:288:19:288:25 | definition of buffer3 | semmle.label | definition of buffer3 |
| test.cpp:289:19:289:25 | buffer3 | semmle.label | buffer3 |
| test.cpp:289:19:289:25 | buffer3 | semmle.label | buffer3 |
| test.cpp:292:25:292:27 | arr | semmle.label | arr |
| test.cpp:299:16:299:21 | access to array | semmle.label | access to array |
| test.cpp:305:9:305:12 | definition of arr1 | semmle.label | definition of arr1 |
| test.cpp:306:20:306:23 | arr1 | semmle.label | arr1 |
| test.cpp:306:20:306:23 | arr1 | semmle.label | arr1 |
| test.cpp:308:9:308:12 | definition of arr2 | semmle.label | definition of arr2 |
| test.cpp:309:20:309:23 | arr2 | semmle.label | arr2 |
| test.cpp:309:20:309:23 | arr2 | semmle.label | arr2 |
| test.cpp:314:10:314:13 | definition of temp | semmle.label | definition of temp |
| test.cpp:319:13:319:27 | ... = ... | semmle.label | ... = ... |
| test.cpp:319:19:319:22 | temp | semmle.label | temp |
| test.cpp:319:19:319:27 | ... + ... | semmle.label | ... + ... |
@@ -221,25 +189,14 @@ subpaths
| test.cpp:72:5:72:15 | PointerAdd: access to array | test.cpp:79:32:79:34 | buf | test.cpp:72:5:72:15 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:72:5:72:19 | Store: ... = ... | write |
| test.cpp:77:27:77:44 | PointerAdd: access to array | test.cpp:77:32:77:34 | buf | test.cpp:66:32:66:32 | p | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:67:5:67:10 | Store: ... = ... | write |
| test.cpp:88:5:88:27 | PointerAdd: access to array | test.cpp:85:34:85:36 | buf | test.cpp:88:5:88:27 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:88:5:88:31 | Store: ... = ... | write |
| test.cpp:128:9:128:14 | PointerAdd: access to array | test.cpp:125:11:125:13 | definition of arr | test.cpp:128:9:128:14 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:125:11:125:13 | arr | arr | test.cpp:128:9:128:18 | Store: ... = ... | write |
| test.cpp:128:9:128:14 | PointerAdd: access to array | test.cpp:128:9:128:11 | arr | test.cpp:128:9:128:14 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:125:11:125:13 | arr | arr | test.cpp:128:9:128:18 | Store: ... = ... | write |
| test.cpp:136:9:136:16 | PointerAdd: ... += ... | test.cpp:142:10:142:13 | definition of asdf | test.cpp:138:13:138:15 | arr | This pointer arithmetic may have an off-by-2 error allowing it to overrun $@ at this $@. | test.cpp:142:10:142:13 | asdf | asdf | test.cpp:138:12:138:15 | Load: * ... | read |
| test.cpp:136:9:136:16 | PointerAdd: ... += ... | test.cpp:143:18:143:21 | asdf | test.cpp:138:13:138:15 | arr | This pointer arithmetic may have an off-by-2 error allowing it to overrun $@ at this $@. | test.cpp:142:10:142:13 | asdf | asdf | test.cpp:138:12:138:15 | Load: * ... | read |
| test.cpp:156:12:156:18 | PointerAdd: ... + ... | test.cpp:154:7:154:9 | definition of buf | test.cpp:147:4:147:9 | -- ... | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:154:7:154:9 | buf | buf | test.cpp:147:3:147:13 | Store: ... = ... | write |
| test.cpp:156:12:156:18 | PointerAdd: ... + ... | test.cpp:154:7:154:9 | definition of buf | test.cpp:147:4:147:9 | -- ... | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:154:7:154:9 | buf | buf | test.cpp:147:3:147:13 | Store: ... = ... | write |
| test.cpp:156:12:156:18 | PointerAdd: ... + ... | test.cpp:156:12:156:14 | buf | test.cpp:147:4:147:9 | -- ... | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:154:7:154:9 | buf | buf | test.cpp:147:3:147:13 | Store: ... = ... | write |
| test.cpp:156:12:156:18 | PointerAdd: ... + ... | test.cpp:156:12:156:14 | buf | test.cpp:147:4:147:9 | -- ... | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:154:7:154:9 | buf | buf | test.cpp:147:3:147:13 | Store: ... = ... | write |
| test.cpp:221:5:221:11 | PointerAdd: access to array | test.cpp:217:19:217:24 | definition of buffer | test.cpp:221:5:221:11 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:217:19:217:24 | buffer | buffer | test.cpp:221:5:221:15 | Store: ... = ... | write |
| test.cpp:221:5:221:11 | PointerAdd: access to array | test.cpp:218:23:218:28 | buffer | test.cpp:221:5:221:11 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:217:19:217:24 | buffer | buffer | test.cpp:221:5:221:15 | Store: ... = ... | write |
| test.cpp:232:5:232:10 | PointerAdd: access to array | test.cpp:228:10:228:14 | definition of array | test.cpp:232:5:232:10 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:228:10:228:14 | array | array | test.cpp:232:5:232:19 | Store: ... = ... | write |
| test.cpp:232:5:232:10 | PointerAdd: access to array | test.cpp:229:25:229:29 | array | test.cpp:232:5:232:10 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:228:10:228:14 | array | array | test.cpp:232:5:232:19 | Store: ... = ... | write |
| test.cpp:261:27:261:30 | PointerAdd: access to array | test.cpp:285:19:285:25 | definition of buffer2 | test.cpp:261:27:261:30 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:285:19:285:25 | buffer2 | buffer2 | test.cpp:261:27:261:30 | Load: access to array | read |
| test.cpp:261:27:261:30 | PointerAdd: access to array | test.cpp:286:19:286:25 | buffer2 | test.cpp:261:27:261:30 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:285:19:285:25 | buffer2 | buffer2 | test.cpp:261:27:261:30 | Load: access to array | read |
| test.cpp:299:16:299:21 | PointerAdd: access to array | test.cpp:308:9:308:12 | definition of arr2 | test.cpp:299:16:299:21 | access to array | This pointer arithmetic may have an off-by-1014 error allowing it to overrun $@ at this $@. | test.cpp:308:9:308:12 | arr2 | arr2 | test.cpp:299:16:299:21 | Load: access to array | read |
| test.cpp:299:16:299:21 | PointerAdd: access to array | test.cpp:309:20:309:23 | arr2 | test.cpp:299:16:299:21 | access to array | This pointer arithmetic may have an off-by-1014 error allowing it to overrun $@ at this $@. | test.cpp:308:9:308:12 | arr2 | arr2 | test.cpp:299:16:299:21 | Load: access to array | read |
| test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:314:10:314:13 | definition of temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:330:13:330:24 | Store: ... = ... | write |
| test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:314:10:314:13 | definition of temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:331:13:331:24 | Store: ... = ... | write |
| test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:314:10:314:13 | definition of temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:333:13:333:24 | Store: ... = ... | write |
| test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:322:19:322:22 | temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:330:13:330:24 | Store: ... = ... | write |
| test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:322:19:322:22 | temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:331:13:331:24 | Store: ... = ... | write |
| test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:322:19:322:22 | temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:333:13:333:24 | Store: ... = ... | write |

View File

@@ -0,0 +1,82 @@
void use(...);
void test1() {
int x = 0; // $ certain="SSA def(&x)" certain="SSA def(x)"
use(x);
x = 1; // $ certain="SSA def(x)"
use(x);
int* p = &x; // $ certain="SSA def(&p)" certain="SSA def(p)" certain="SSA def(*p)"
use(p);
*p = 2; // $ certain="SSA def(*p)"
use(p);
p = nullptr; // $ certain="SSA def(p)" certain="SSA def(*p)"
use(p);
*p = 2; // $ uncertain="SSA def(*p)"
use(p);
}
void test2(bool b) { // $ certain="SSA def(&b)" certain="SSA def(b)"
{
int x; // $ certain="SSA def(&x)"
if(b) {
x = 0; // $ certain="SSA def(x)"
} else {
x = 1; // $ certain="SSA def(x)"
}
use(x); // $ certain="SSA phi(x)"
}
{
int x; // $ certain="SSA def(&x)" certain="SSA def(x)"
if(b) {
x = 0; // $ certain="SSA def(x)"
} else {
}
use(x); // $ certain="SSA phi(x)"
}
{
int x; // $ certain="SSA def(&x)" certain="SSA def(x)"
int* p = &x; // $ certain="SSA def(&p)" certain="SSA def(p)" certain="SSA def(*p)"
if(b) {
*p = 0; // $ certain="SSA def(*p)"
} else {
*(p + 1) = 1; // $ uncertain="SSA def(*p)"
}
use(p); // $ uncertain="SSA phi(*p)"
}
}
void test3(bool b) { // $ certain="SSA def(&b)" certain="SSA def(b)"
for(int i = 0; i < 10;) { // $ certain="SSA def(&i)" certain="SSA def(i)" certain="SSA phi(i)"
if(b) {
++i; // $ certain="SSA def(i)"
}
use(i); // $ certain="SSA phi(i)"
}
}
void test(int x, bool b1, bool b2) { // $ certain="SSA def(&x)" certain="SSA def(x)" certain="SSA def(&b1)" certain="SSA def(b1)" certain="SSA def(&b2)" certain="SSA def(b2)"
int* p = &x; // $ certain="SSA def(&p)" certain="SSA def(p)" certain="SSA def(*p)"
int i = 0; // $ certain="SSA def(&i)" certain="SSA def(i)"
int j = 0; // $ certain="SSA def(&j)" certain="SSA def(j)"
while (i < 10) { // $ certain="SSA phi(i)" certain="SSA phi(*p)"
if (b1) {
*p = 0; // $ certain="SSA def(*p)"
}
++i; // $ certain="SSA def(i)" certain="SSA phi(*p)"
}
while (j < 10) { // $ uncertain="SSA phi(*p)" certain="SSA phi(j)"
if (b2) {
*(p + j) = 0; // $ uncertain="SSA def(*p)"
}
++j; // $ certain="SSA def(j)" uncertain="SSA phi(*p)"
}
}

View File

@@ -0,0 +1,22 @@
import cpp
import utils.test.InlineExpectationsTest
import semmle.code.cpp.dataflow.new.DataFlow::DataFlow
bindingset[s]
string quote(string s) { if s.matches("% %") then result = "\"" + s + "\"" else result = s }
module AsDefinitionTest implements TestSig {
string getARelevantTag() { result = ["certain", "uncertain"] }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Ssa::Definition d |
location = d.getLocation() and
element = d.toString() and
value = quote(d.toString())
|
if d.isCertain() then tag = "certain" else tag = "uncertain"
)
}
}
import MakeTest<AsDefinitionTest>

View File

@@ -143,6 +143,7 @@ postWithInFlow
| test.cpp:1153:5:1153:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1165:5:1165:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1195:5:1195:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1337:5:1337:13 | access to array [post update] | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge
uniqueParameterNodeAtPosition
uniqueParameterNodePosition

View File

@@ -65,52 +65,52 @@
| test.cpp:8:8:8:9 | t1 | test.cpp:9:8:9:9 | t1 |
| test.cpp:9:8:9:9 | t1 | test.cpp:11:7:11:8 | t1 |
| test.cpp:9:8:9:9 | t1 | test.cpp:11:7:11:8 | t1 |
| test.cpp:10:8:10:9 | t2 | test.cpp:11:7:11:8 | [input] SSA phi read(t2) |
| test.cpp:10:8:10:9 | t2 | test.cpp:11:7:11:8 | [input] SSA phi(*t2) |
| test.cpp:10:8:10:9 | t2 | test.cpp:11:7:11:8 | [input] SSA phi read(&t2) |
| test.cpp:10:8:10:9 | t2 | test.cpp:11:7:11:8 | [input] SSA phi(t2) |
| test.cpp:10:8:10:9 | t2 | test.cpp:13:10:13:11 | t2 |
| test.cpp:11:7:11:8 | [input] SSA phi read(t2) | test.cpp:15:8:15:9 | t2 |
| test.cpp:11:7:11:8 | [input] SSA phi(*t2) | test.cpp:15:8:15:9 | t2 |
| test.cpp:11:7:11:8 | [input] SSA phi read(&t2) | test.cpp:15:8:15:9 | t2 |
| test.cpp:11:7:11:8 | [input] SSA phi(t2) | test.cpp:15:8:15:9 | t2 |
| test.cpp:11:7:11:8 | t1 | test.cpp:21:8:21:9 | t1 |
| test.cpp:12:5:12:10 | ... = ... | test.cpp:13:10:13:11 | t2 |
| test.cpp:12:10:12:10 | 0 | test.cpp:12:5:12:10 | ... = ... |
| test.cpp:13:10:13:11 | t2 | test.cpp:15:8:15:9 | t2 |
| test.cpp:13:10:13:11 | t2 | test.cpp:15:8:15:9 | t2 |
| test.cpp:15:8:15:9 | t2 | test.cpp:23:15:23:16 | [input] SSA phi read(*t2) |
| test.cpp:15:8:15:9 | t2 | test.cpp:23:15:23:16 | [input] SSA phi read(&t2) |
| test.cpp:15:8:15:9 | t2 | test.cpp:23:15:23:16 | [input] SSA phi read(t2) |
| test.cpp:17:3:17:8 | ... = ... | test.cpp:21:8:21:9 | t1 |
| test.cpp:17:8:17:8 | 0 | test.cpp:17:3:17:8 | ... = ... |
| test.cpp:21:8:21:9 | t1 | test.cpp:23:19:23:19 | SSA phi read(t1) |
| test.cpp:21:8:21:9 | t1 | test.cpp:23:19:23:19 | SSA phi(*t1) |
| test.cpp:21:8:21:9 | t1 | test.cpp:23:19:23:19 | SSA phi read(&t1) |
| test.cpp:21:8:21:9 | t1 | test.cpp:23:19:23:19 | SSA phi(t1) |
| test.cpp:23:15:23:16 | 0 | test.cpp:23:15:23:16 | 0 |
| test.cpp:23:15:23:16 | 0 | test.cpp:23:19:23:19 | SSA phi(*i) |
| test.cpp:23:15:23:16 | [input] SSA phi read(*t2) | test.cpp:23:19:23:19 | SSA phi read(*t2) |
| test.cpp:23:15:23:16 | 0 | test.cpp:23:19:23:19 | SSA phi(i) |
| test.cpp:23:15:23:16 | [input] SSA phi read(&t2) | test.cpp:23:19:23:19 | SSA phi read(&t2) |
| test.cpp:23:15:23:16 | [input] SSA phi read(t2) | test.cpp:23:19:23:19 | SSA phi read(t2) |
| test.cpp:23:19:23:19 | SSA phi read(*t2) | test.cpp:24:10:24:11 | t2 |
| test.cpp:23:19:23:19 | SSA phi read(i) | test.cpp:23:19:23:19 | i |
| test.cpp:23:19:23:19 | SSA phi read(t1) | test.cpp:23:23:23:24 | t1 |
| test.cpp:23:19:23:19 | SSA phi read(&i) | test.cpp:23:19:23:19 | i |
| test.cpp:23:19:23:19 | SSA phi read(&t1) | test.cpp:23:23:23:24 | t1 |
| test.cpp:23:19:23:19 | SSA phi read(&t2) | test.cpp:24:10:24:11 | t2 |
| test.cpp:23:19:23:19 | SSA phi read(t2) | test.cpp:24:10:24:11 | t2 |
| test.cpp:23:19:23:19 | SSA phi(*i) | test.cpp:23:19:23:19 | i |
| test.cpp:23:19:23:19 | SSA phi(*t1) | test.cpp:23:23:23:24 | t1 |
| test.cpp:23:19:23:19 | SSA phi(i) | test.cpp:23:19:23:19 | i |
| test.cpp:23:19:23:19 | SSA phi(t1) | test.cpp:23:23:23:24 | t1 |
| test.cpp:23:19:23:19 | i | test.cpp:23:27:23:27 | i |
| test.cpp:23:19:23:19 | i | test.cpp:23:27:23:27 | i |
| test.cpp:23:23:23:24 | t1 | test.cpp:23:27:23:29 | [input] SSA phi read(t1) |
| test.cpp:23:23:23:24 | t1 | test.cpp:23:27:23:29 | [input] SSA phi read(&t1) |
| test.cpp:23:23:23:24 | t1 | test.cpp:26:8:26:9 | t1 |
| test.cpp:23:23:23:24 | t1 | test.cpp:26:8:26:9 | t1 |
| test.cpp:23:27:23:27 | *i | test.cpp:23:27:23:27 | *i |
| test.cpp:23:27:23:27 | *i | test.cpp:23:27:23:27 | i |
| test.cpp:23:27:23:27 | i | test.cpp:23:27:23:27 | i |
| test.cpp:23:27:23:27 | i | test.cpp:23:27:23:27 | i |
| test.cpp:23:27:23:27 | i | test.cpp:23:27:23:29 | [input] SSA phi read(i) |
| test.cpp:23:27:23:27 | i | test.cpp:23:27:23:29 | [input] SSA phi read(&i) |
| test.cpp:23:27:23:29 | ... ++ | test.cpp:23:27:23:29 | ... ++ |
| test.cpp:23:27:23:29 | ... ++ | test.cpp:23:27:23:29 | [input] SSA phi(*i) |
| test.cpp:23:27:23:29 | [input] SSA phi read(*t2) | test.cpp:23:19:23:19 | SSA phi read(*t2) |
| test.cpp:23:27:23:29 | [input] SSA phi read(i) | test.cpp:23:19:23:19 | SSA phi read(i) |
| test.cpp:23:27:23:29 | [input] SSA phi read(t1) | test.cpp:23:19:23:19 | SSA phi read(t1) |
| test.cpp:23:27:23:29 | ... ++ | test.cpp:23:27:23:29 | [input] SSA phi(i) |
| test.cpp:23:27:23:29 | [input] SSA phi read(&i) | test.cpp:23:19:23:19 | SSA phi read(&i) |
| test.cpp:23:27:23:29 | [input] SSA phi read(&t1) | test.cpp:23:19:23:19 | SSA phi read(&t1) |
| test.cpp:23:27:23:29 | [input] SSA phi read(&t2) | test.cpp:23:19:23:19 | SSA phi read(&t2) |
| test.cpp:23:27:23:29 | [input] SSA phi read(t2) | test.cpp:23:19:23:19 | SSA phi read(t2) |
| test.cpp:23:27:23:29 | [input] SSA phi(*i) | test.cpp:23:19:23:19 | SSA phi(*i) |
| test.cpp:23:27:23:29 | [input] SSA phi(*t1) | test.cpp:23:19:23:19 | SSA phi(*t1) |
| test.cpp:24:5:24:11 | ... = ... | test.cpp:23:27:23:29 | [input] SSA phi(*t1) |
| test.cpp:24:10:24:11 | t2 | test.cpp:23:27:23:29 | [input] SSA phi read(*t2) |
| test.cpp:23:27:23:29 | [input] SSA phi(i) | test.cpp:23:19:23:19 | SSA phi(i) |
| test.cpp:23:27:23:29 | [input] SSA phi(t1) | test.cpp:23:19:23:19 | SSA phi(t1) |
| test.cpp:24:5:24:11 | ... = ... | test.cpp:23:27:23:29 | [input] SSA phi(t1) |
| test.cpp:24:10:24:11 | t2 | test.cpp:23:27:23:29 | [input] SSA phi read(&t2) |
| test.cpp:24:10:24:11 | t2 | test.cpp:23:27:23:29 | [input] SSA phi read(t2) |
| test.cpp:24:10:24:11 | t2 | test.cpp:24:5:24:11 | ... = ... |
| test.cpp:382:48:382:54 | source1 | test.cpp:384:16:384:23 | *& ... |

View File

@@ -171,6 +171,7 @@ astFlow
| test.cpp:1312:7:1312:12 | call to source | test.cpp:1313:8:1313:24 | ... ? ... : ... |
| test.cpp:1312:7:1312:12 | call to source | test.cpp:1314:8:1314:8 | x |
| test.cpp:1329:11:1329:16 | call to source | test.cpp:1330:10:1330:10 | i |
| test.cpp:1335:10:1335:15 | buffer | test.cpp:1336:10:1336:18 | access to array |
| true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x |
| true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x |
| true_upon_entry.cpp:33:11:33:16 | call to source | true_upon_entry.cpp:39:8:39:8 | x |

View File

@@ -1329,3 +1329,11 @@ void nsdmi_test() {
nsdmi y(source());
sink(y.i); // $ ir ast
}
void certain_def_uninitialized_instruction_test() {
for(int i = 0; i < 10; i++) {
char buffer[10];
sink(buffer[0]); // $ SPURIOUS: ast
buffer[0] = source();
}
}

View File

@@ -59,3 +59,5 @@
| test.cpp:1137:7:1137:10 | data | test.cpp:1138:5:1138:8 | data |
| test.cpp:1137:7:1137:10 | data | test.cpp:1139:4:1139:7 | data |
| test.cpp:1137:7:1137:10 | data | test.cpp:1140:10:1140:13 | data |
| test.cpp:1335:10:1335:15 | buffer | test.cpp:1336:10:1336:15 | buffer |
| test.cpp:1335:10:1335:15 | buffer | test.cpp:1337:5:1337:10 | buffer |

View File

@@ -131,3 +131,112 @@ void test_strsafe_gets() {
StringCchGetsExA(dest, sizeof(dest), &end, &remaining, 0); // $ local_source
}
}
int scanf_s(const char *format, ...);
int fscanf_s(FILE *stream, const char *format, ...);
void test_scanf_s(FILE *stream) {
{
int n1, n2;
scanf_s(
"%d %d",
&n1, // $ local_source
&n2); // $ local_source
}
{
int n;
fscanf_s(stream, "%d", &n); // $ remote_source
}
{
int n1, n2;
char buf[256];
scanf_s("%d %s %d",
&n1, // $ local_source
buf, // $ local_source
256,
&n2); // $ local_source
}
{
int n1, n2;
char buf[256];
fscanf_s(stream, "%d %s %d",
&n1, // $ remote_source
buf, // $ remote_source
256,
&n2); // $ remote_source
}
}
typedef void *locale_t;
int wscanf_s(const wchar_t *format, ...);
int _scanf_s_l(const char *format, locale_t locale, ...);
int _wscanf_s_l(const wchar_t *format, locale_t locale, ...);
int fwscanf_s(FILE *stream, const wchar_t *format, ...);
int _fscanf_s_l(FILE *stream, const char *format, locale_t locale, ...);
int _fwscanf_s_l(FILE *stream, const wchar_t *format, locale_t locale, ...);
void test_additional_scanf_s_variants(FILE *stream, locale_t locale) {
{
int n1, n2;
wchar_t buf[256];
wscanf_s(L"%d %s %d",
&n1, // $ local_source
buf, // $ local_source
256,
&n2); // $ local_source
}
{
int n1, n2;
char buf[256];
_scanf_s_l("%d %s %d", locale,
&n1, // $ local_source
buf, // $ local_source
256,
&n2); // $ local_source
}
{
int n1, n2;
wchar_t buf[256];
_wscanf_s_l(L"%d %s %d", locale,
&n1, // $ local_source
buf, // $ local_source
256,
&n2); // $ local_source
}
{
int n1, n2;
wchar_t buf[256];
fwscanf_s(stream, L"%d %s %d",
&n1, // $ remote_source
buf, // $ remote_source
256,
&n2); // $ remote_source
}
{
int n1, n2;
char buf[256];
_fscanf_s_l(stream, "%d %s %d", locale,
&n1, // $ remote_source
buf, // $ remote_source
256,
&n2); // $ remote_source
}
{
int n1, n2;
wchar_t buf[256];
_fwscanf_s_l(stream, L"%d %s %d", locale,
&n1, // $ remote_source
buf, // $ remote_source
256,
&n2); // $ remote_source
}
}

View File

@@ -4928,6 +4928,8 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| stl.h:95:69:95:69 | x | stl.h:96:42:96:42 | x | |
| stl.h:96:42:96:42 | ref arg x | stl.h:95:69:95:69 | x | |
| stl.h:96:42:96:42 | ref arg x | stl.h:95:69:95:69 | x | |
| stl.h:292:30:292:40 | 0 | file://:0:0:0:0 | noexcept(...) | TAINT |
| stl.h:292:30:292:40 | 0 | file://:0:0:0:0 | noexcept(...) | TAINT |
| stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT |
| stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT |
| stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT |

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,8 @@
| test.c:18:2:18:6 | call to scanf | 0 | s | 0 | 0 |
| test.c:19:2:19:7 | call to fscanf | 0 | s | 10 | 10 |
| test.c:19:2:19:7 | call to fscanf | 1 | i | 0 | 0 |
| test.c:20:2:20:7 | call to sscanf | 0 | s | 0 | 0 |
| test.c:21:2:21:8 | call to swscanf | 0 | s | 10 | 10 |
| test.c:19:2:19:6 | call to scanf | 0 | s | 0 | 0 |
| test.c:20:2:20:7 | call to fscanf | 0 | s | 10 | 10 |
| test.c:20:2:20:7 | call to fscanf | 1 | i | 0 | 0 |
| test.c:21:2:21:7 | call to sscanf | 0 | s | 0 | 0 |
| test.c:22:2:22:8 | call to swscanf | 0 | s | 10 | 10 |
| test.c:23:2:23:8 | call to scanf_s | 0 | d | 0 | 0 |
| test.c:23:2:23:8 | call to scanf_s | 1 | s | 0 | 0 |
| test.c:23:2:23:8 | call to scanf_s | 2 | d | 0 | 0 |

View File

@@ -1,5 +1,6 @@
| ms.cpp:17:3:17:8 | call to sscanf | 0 | 1 | ms.cpp:17:24:17:30 | %I64i | non-wide |
| test.c:18:2:18:6 | call to scanf | 0 | 0 | test.c:18:8:18:11 | %s | non-wide |
| test.c:19:2:19:7 | call to fscanf | 0 | 1 | test.c:19:15:19:23 | %10s %i | non-wide |
| test.c:20:2:20:7 | call to sscanf | 0 | 1 | test.c:20:19:20:28 | %*i%s%*s | non-wide |
| test.c:21:2:21:8 | call to swscanf | 0 | 1 | test.c:21:21:21:26 | %10s | wide |
| test.c:19:2:19:6 | call to scanf | 0 | 0 | test.c:19:8:19:11 | %s | non-wide |
| test.c:20:2:20:7 | call to fscanf | 0 | 1 | test.c:20:15:20:23 | %10s %i | non-wide |
| test.c:21:2:21:7 | call to sscanf | 0 | 1 | test.c:21:19:21:28 | %*i%s%*s | non-wide |
| test.c:22:2:22:8 | call to swscanf | 0 | 1 | test.c:22:21:22:26 | %10s | wide |
| test.c:23:2:23:8 | call to scanf_s | 0 | 0 | test.c:23:10:23:19 | %d %s %d | non-wide |

View File

@@ -0,0 +1,9 @@
| ms.cpp:17:3:17:8 | call to sscanf | ms.cpp:17:33:17:36 | & ... | 0 |
| test.c:19:2:19:6 | call to scanf | test.c:19:14:19:19 | buffer | 0 |
| test.c:20:2:20:7 | call to fscanf | test.c:20:26:20:31 | buffer | 0 |
| test.c:20:2:20:7 | call to fscanf | test.c:20:34:20:34 | i | 1 |
| test.c:21:2:21:7 | call to sscanf | test.c:21:31:21:36 | buffer | 0 |
| test.c:22:2:22:8 | call to swscanf | test.c:22:29:22:35 | wbuffer | 0 |
| test.c:23:2:23:8 | call to scanf_s | test.c:23:22:23:23 | & ... | 0 |
| test.c:23:2:23:8 | call to scanf_s | test.c:23:26:23:31 | buffer | 1 |
| test.c:23:2:23:8 | call to scanf_s | test.c:23:38:23:40 | & ... | 2 |

View File

@@ -0,0 +1,5 @@
import semmle.code.cpp.commons.Scanf
from ScanfFunctionCall sfc, Expr e, int n
where e = sfc.getOutputArgument(n)
select sfc, e, n

View File

@@ -7,18 +7,20 @@ int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *s, const char *format, ...);
int swscanf(const wchar_t* ws, const wchar_t* format, ...);
int scanf_s(const char *format, ...);
int main(int argc, char *argv[])
{
char buffer[256];
wchar_t wbuffer[256];
FILE *file;
int i;
int i, i2;
scanf("%s", buffer);
fscanf(file, "%10s %i", buffer, i);
sscanf("Hello.", "%*i%s%*s", buffer);
swscanf(L"Hello.", "%10s", wbuffer);
scanf_s("%d %s %d", &i, buffer, 10, &i2);
return 0;
}

View File

@@ -1,9 +1,9 @@
| file://:0:0:0:0 | X | NestedTypedefType | file://:0:0:0:0 | int * |
| file://:0:0:0:0 | X | UsingAliasTypedefType | file://:0:0:0:0 | int * |
| file://:0:0:0:0 | X | TypeAliasType | file://:0:0:0:0 | int * |
| using-alias.cpp:2:13:2:17 | type1 | CTypedefType | file://:0:0:0:0 | int |
| using-alias.cpp:3:7:3:12 | using1 | UsingAliasTypedefType | file://:0:0:0:0 | float |
| using-alias.cpp:3:7:3:12 | using1 | TypeAliasType | file://:0:0:0:0 | float |
| using-alias.cpp:5:16:5:20 | type2 | CTypedefType | file://:0:0:0:0 | float |
| using-alias.cpp:6:7:6:12 | using2 | UsingAliasTypedefType | file://:0:0:0:0 | int |
| using-alias.cpp:6:7:6:12 | using2 | TypeAliasType | file://:0:0:0:0 | int |
| using-alias.cpp:8:39:8:39 | X | NestedTypedefType | file://:0:0:0:0 | T * |
| using-alias.cpp:8:39:8:39 | X | UsingAliasTypedefType | file://:0:0:0:0 | T * |
| using-alias.cpp:10:7:10:7 | Y | UsingAliasTypedefType | file://:0:0:0:0 | int * |
| using-alias.cpp:8:39:8:39 | X | TypeAliasType | file://:0:0:0:0 | T * |
| using-alias.cpp:10:7:10:7 | Y | TypeAliasType | file://:0:0:0:0 | int * |

View File

@@ -577,3 +577,10 @@ void tests3()
str = get_home_address();
send(val(), str, strlen(str), val()); // BAD
}
int fscanf(FILE* stream, const char* format, ... );
void test_scanf() {
char password[256];
fscanf(stdin, "%255s", password); // GOOD: this is not a remote source
}

View File

@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"paket": {
"version": "10.0.0-alpha011",
"version": "10.3.1",
"commands": [
"paket"
]

View File

@@ -241,8 +241,9 @@
<OmitContent Condition="%(PaketReferencesFileLinesInfo.Splits) &gt;= 7">$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[6])</OmitContent>
<ImportTargets Condition="%(PaketReferencesFileLinesInfo.Splits) &gt;= 8">$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[7])</ImportTargets>
<Aliases Condition="%(PaketReferencesFileLinesInfo.Splits) &gt;= 9">$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[8])</Aliases>
<ReferenceCondition Condition="%(PaketReferencesFileLinesInfo.Splits) &gt;= 10">$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[9])</ReferenceCondition>
</PaketReferencesFileLinesInfo>
<PackageReference Condition=" '$(ManagePackageVersionsCentrally)' != 'true' Or '%(PaketReferencesFileLinesInfo.Reference)' == 'Direct' " Include="%(PaketReferencesFileLinesInfo.PackageName)">
<PackageReference Condition=" ('$(ManagePackageVersionsCentrally)' != 'true' Or '%(PaketReferencesFileLinesInfo.Reference)' == 'Direct') AND ('%(PaketReferencesFileLinesInfo.ReferenceCondition)' == 'true' Or $(%(PaketReferencesFileLinesInfo.ReferenceCondition)) == 'true')" Include="%(PaketReferencesFileLinesInfo.PackageName)">
<Version Condition=" '$(ManagePackageVersionsCentrally)' != 'true' ">%(PaketReferencesFileLinesInfo.PackageVersion)</Version>
<PrivateAssets Condition=" ('%(PaketReferencesFileLinesInfo.AllPrivateAssets)' == 'true') Or ('$(PackAsTool)' == 'true') ">All</PrivateAssets>
<ExcludeAssets Condition=" %(PaketReferencesFileLinesInfo.CopyLocal) == 'false' or %(PaketReferencesFileLinesInfo.AllPrivateAssets) == 'exclude'">runtime</ExcludeAssets>
@@ -251,10 +252,8 @@
<Aliases Condition=" %(PaketReferencesFileLinesInfo.Aliases) != ''">%(PaketReferencesFileLinesInfo.Aliases)</Aliases>
<Publish Condition=" '$(PackAsTool)' == 'true' ">true</Publish>
<AllowExplicitVersion>true</AllowExplicitVersion>
</PackageReference>
<PackageVersion Include="%(PaketReferencesFileLinesInfo.PackageName)">
<PackageVersion Condition="('$(ManagePackageVersionsCentrally)' != 'true' Or '%(PaketReferencesFileLinesInfo.Reference)' == 'Direct') AND ('%(PaketReferencesFileLinesInfo.ReferenceCondition)' == 'true' Or $(%(PaketReferencesFileLinesInfo.ReferenceCondition)) == 'true')" Include="%(PaketReferencesFileLinesInfo.PackageName)">
<Version>%(PaketReferencesFileLinesInfo.PackageVersion)</Version>
</PackageVersion>
</ItemGroup>
@@ -319,7 +318,17 @@
</ItemGroup>
<Error Text="Error Because of PAKET_ERROR_ON_MSBUILD_EXEC (not calling fix-nuspecs)" Condition=" '$(PAKET_ERROR_ON_MSBUILD_EXEC)' == 'true' " />
<Exec Condition="@(_NuspecFiles) != ''" Command='$(PaketCommand) fix-nuspecs files "@(_NuspecFiles)" project-file "$(PaketProjectFile)" ' />
<Exec Condition="@(_NuspecFiles) != ''" Command='$(PaketCommand) show-conditions -s' ConsoleToMSBuild="true" StandardOutputImportance="low">
<Output TaskParameter="ConsoleOutput" ItemName="_ConditionProperties"/>
</Exec>
<ItemGroup>
<_DefinedConditionProperties Include="@(_ConditionProperties)" Condition="$(%(Identity)) == 'true'"/>
</ItemGroup>
<PropertyGroup>
<_ConditionsParameter></_ConditionsParameter>
<_ConditionsParameter Condition="@(_DefinedConditionProperties) != ''">--conditions @(_DefinedConditionProperties)</_ConditionsParameter>
</PropertyGroup>
<Exec Condition="@(_NuspecFiles) != ''" Command='$(PaketCommand) fix-nuspecs files "@(_NuspecFiles)" project-file "$(PaketProjectFile)" $(_ConditionsParameter)' />
<Error Condition="@(_NuspecFiles) == ''" Text='Could not find nuspec files in "$(AdjustedNuspecOutputPath)" (Version: "$(PackageVersion)"), therefore we cannot call "paket fix-nuspecs" and have to error out!' />
<ConvertToAbsolutePath Condition="@(_NuspecFiles) != ''" Paths="@(_NuspecFiles)">

View File

@@ -52,6 +52,13 @@ namespace Semmle.Extraction.CSharp.Util
{ "op_False", "false" }
});
/// <summary>
/// The operatorname for user-defined instance increment- and decrement operators are "op_IncrementAssignment" and
/// "op_DecrementAssignment" respectively.
/// Thus we need to handle this explicitly to avoid postfixing them with an "=".
/// </summary>
private static bool IsIncrementOrDecrement(string operatorName) => operatorName == "++" || operatorName == "--";
/// <summary>
/// Convert an operator method name in to a symbolic name.
/// A return value indicates whether the conversion succeeded.
@@ -72,7 +79,7 @@ namespace Semmle.Extraction.CSharp.Util
if (match.Success && methodToOperator.TryGetValue($"op_{match.Groups[2]}", out var rawOperatorName))
{
var prefix = match.Groups[1].Success ? "checked " : "";
var postfix = match.Groups[3].Success ? "=" : "";
var postfix = match.Groups[3].Success && !IsIncrementOrDecrement(rawOperatorName) ? "=" : "";
operatorName = $"{prefix}{rawOperatorName}{postfix}";
return true;
}

View File

@@ -32,9 +32,13 @@ namespace Semmle.Extraction.CSharp.Entities
{
var assembly = Assembly.CreateOutputAssembly(Context);
trapFile.compilations(this, FileUtils.ConvertToUnix(cwd));
var path = Context.ExtractionContext.PathTransformer.Transform(cwd);
trapFile.compilations(this, path.Value);
trapFile.compilation_assembly(this, assembly);
// Ensure that a `Folder` entity exists
Folder.Create(Context, path);
// Arguments
var expandedIndex = 0;
for (var i = 0; i < args.Length; i++)

View File

@@ -234,9 +234,9 @@ namespace Semmle.Extraction.CSharp.Entities
/// </summary>
/// <param name="node">The expression syntax node.</param>
/// <returns>Returns the target method symbol, or null if it cannot be resolved.</returns>
protected IMethodSymbol? GetTargetSymbol(ExpressionSyntax node)
protected static IMethodSymbol? GetTargetSymbol(Context cx, ExpressionSyntax node)
{
var si = Context.GetSymbolInfo(node);
var si = cx.GetSymbolInfo(node);
if (si.Symbol is ISymbol symbol)
{
var method = symbol as IMethodSymbol;
@@ -255,7 +255,7 @@ namespace Semmle.Extraction.CSharp.Entities
.Where(method => method.Parameters.Length >= syntax.ArgumentList.Arguments.Count)
.Where(method => method.Parameters.Count(p => !p.HasExplicitDefaultValue) <= syntax.ArgumentList.Arguments.Count);
return Context.ExtractionContext.IsStandalone ?
return cx.ExtractionContext.IsStandalone ?
candidates.FirstOrDefault() :
candidates.SingleOrDefault();
}
@@ -281,7 +281,7 @@ namespace Semmle.Extraction.CSharp.Entities
/// <param name="node">The expression.</param>
public void AddOperatorCall(TextWriter trapFile, ExpressionSyntax node)
{
var @operator = GetTargetSymbol(node);
var @operator = GetTargetSymbol(Context, node);
if (@operator is IMethodSymbol method)
{
var callType = GetCallType(Context, node);
@@ -312,9 +312,9 @@ namespace Semmle.Extraction.CSharp.Entities
/// <returns>The call type.</returns>
public static CallType GetCallType(Context cx, ExpressionSyntax node)
{
var @operator = cx.GetSymbolInfo(node);
var @operator = GetTargetSymbol(cx, node);
if (@operator.Symbol is IMethodSymbol method)
if (@operator is IMethodSymbol method)
{
if (method.ContainingSymbol is ITypeSymbol containingSymbol && containingSymbol.TypeKind == Microsoft.CodeAnalysis.TypeKind.Dynamic)
{

View File

@@ -58,10 +58,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return Invocation.Create(info);
case SyntaxKind.PostIncrementExpression:
return PostfixUnary.Create(info.SetKind(ExprKind.POST_INCR), ((PostfixUnaryExpressionSyntax)info.Node).Operand);
return PostfixUnary.Create(info.SetKind(ExprKind.POST_INCR));
case SyntaxKind.PostDecrementExpression:
return PostfixUnary.Create(info.SetKind(ExprKind.POST_DECR), ((PostfixUnaryExpressionSyntax)info.Node).Operand);
return PostfixUnary.Create(info.SetKind(ExprKind.POST_DECR));
case SyntaxKind.AwaitExpression:
return Await.Create(info);
@@ -109,10 +109,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return MemberAccess.Create(info, (MemberAccessExpressionSyntax)info.Node);
case SyntaxKind.UnaryMinusExpression:
return Unary.Create(info.SetKind(ExprKind.MINUS));
return PrefixUnary.Create(info.SetKind(ExprKind.MINUS));
case SyntaxKind.UnaryPlusExpression:
return Unary.Create(info.SetKind(ExprKind.PLUS));
return PrefixUnary.Create(info.SetKind(ExprKind.PLUS));
case SyntaxKind.SimpleLambdaExpression:
return Lambda.Create(info, (SimpleLambdaExpressionSyntax)info.Node);
@@ -146,16 +146,16 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return Name.Create(info);
case SyntaxKind.LogicalNotExpression:
return Unary.Create(info.SetKind(ExprKind.LOG_NOT));
return PrefixUnary.Create(info.SetKind(ExprKind.LOG_NOT));
case SyntaxKind.BitwiseNotExpression:
return Unary.Create(info.SetKind(ExprKind.BIT_NOT));
return PrefixUnary.Create(info.SetKind(ExprKind.BIT_NOT));
case SyntaxKind.PreIncrementExpression:
return Unary.Create(info.SetKind(ExprKind.PRE_INCR));
return PrefixUnary.Create(info.SetKind(ExprKind.PRE_INCR));
case SyntaxKind.PreDecrementExpression:
return Unary.Create(info.SetKind(ExprKind.PRE_DECR));
return PrefixUnary.Create(info.SetKind(ExprKind.PRE_DECR));
case SyntaxKind.ThisExpression:
return This.CreateExplicit(info);
@@ -164,10 +164,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return PropertyFieldAccess.Create(info);
case SyntaxKind.AddressOfExpression:
return Unary.Create(info.SetKind(ExprKind.ADDRESS_OF));
return PrefixUnary.Create(info.SetKind(ExprKind.ADDRESS_OF));
case SyntaxKind.PointerIndirectionExpression:
return Unary.Create(info.SetKind(ExprKind.POINTER_INDIRECTION));
return PrefixUnary.Create(info.SetKind(ExprKind.POINTER_INDIRECTION));
case SyntaxKind.DefaultExpression:
return Default.Create(info);
@@ -248,13 +248,13 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return RangeExpression.Create(info);
case SyntaxKind.IndexExpression:
return Unary.Create(info.SetKind(ExprKind.INDEX));
return PrefixUnary.Create(info.SetKind(ExprKind.INDEX));
case SyntaxKind.SwitchExpression:
return Switch.Create(info);
case SyntaxKind.SuppressNullableWarningExpression:
return PostfixUnary.Create(info.SetKind(ExprKind.SUPPRESS_NULLABLE_WARNING), ((PostfixUnaryExpressionSyntax)info.Node).Operand);
return PostfixUnary.Create(info.SetKind(ExprKind.SUPPRESS_NULLABLE_WARNING));
case SyntaxKind.WithExpression:
return WithExpression.Create(info);

View File

@@ -44,7 +44,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
var child = -1;
string? memberName = null;
var target = GetTargetSymbol(Syntax);
var target = GetTargetSymbol(Context, Syntax);
switch (Syntax.Expression)
{
case MemberAccessExpressionSyntax memberAccess when IsValidMemberAccessKind():

Some files were not shown because too many files have changed in this diff Show More