Skip to content

Commit

Permalink
Merge branch 'main' into redsun82/rust-canonical-enum
Browse files Browse the repository at this point in the history
  • Loading branch information
Paolo Tranquilli committed Nov 25, 2024
2 parents adafe3e + 74aa47a commit c3b4447
Show file tree
Hide file tree
Showing 17 changed files with 119 additions and 59 deletions.
1 change: 1 addition & 0 deletions cpp/ql/lib/semmle/code/cpp/models/Models.qll
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,4 @@ private import implementations.PostgreSql
private import implementations.System
private import implementations.StructuredExceptionHandling
private import implementations.ZMQ
private import implementations.Win32CommandExecution
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
private import semmle.code.cpp.models.interfaces.CommandExecution

/** The `ShellExecute` family of functions from Win32. */
class ShellExecute extends Function {
ShellExecute() { this.hasGlobalName("ShellExecute" + ["", "A", "W"]) }
}

private class ShellExecuteModel extends ShellExecute, CommandExecutionFunction {
override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(2) }
}

/** The `WinExec` function from Win32. */
class WinExec extends Function {
WinExec() { this.hasGlobalName("WinExec") }
}

private class WinExecModel extends WinExec, CommandExecutionFunction {
override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(0) }
}

/** The `CreateProcess` family of functions from Win32. */
class CreateProcess extends Function {
CreateProcess() { this.hasGlobalName("CreateProcess" + ["", "A", "W"]) }
}

private class CreateProcessModel extends CreateProcess, CommandExecutionFunction {
override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(0) }
}

/** The `CreateProcessAsUser` family of functions from Win32. */
class CreateProcessAsUser extends Function {
CreateProcessAsUser() { this.hasGlobalName("CreateProcessAsUser" + ["", "A", "W"]) }
}

private class CreateProcessAsUserModel extends CreateProcessAsUser, CommandExecutionFunction {
override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(1) }
}

/** The `CreateProcessWithLogonW` function from Win32. */
class CreateProcessWithLogonW extends Function {
CreateProcessWithLogonW() { this.hasGlobalName("CreateProcessWithLogonW") }
}

private class CreateProcessWithLogonModel extends CreateProcessWithLogonW, CommandExecutionFunction {
override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(4) }
}

/** The `CreateProcessWithTokenW` function from Win32. */
class CreateProcessWithTokenW extends Function {
CreateProcessWithTokenW() { this.hasGlobalName("CreateProcessWithTokenW") }
}

private class CreateProcessWithTokenWModel extends CreateProcessWithTokenW, CommandExecutionFunction
{
override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(2) }
}
13 changes: 8 additions & 5 deletions misc/codegen/generators/qlgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,32 +118,33 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic
type_is_hideable="ql_hideable" in lookup[prop.type].pragmas if prop.type in lookup else False,
internal="ql_internal" in prop.pragmas,
)
ql_name = prop.pragmas.get("ql_name", prop.name)
if prop.is_single:
args.update(
singular=inflection.camelize(prop.name),
singular=inflection.camelize(ql_name),
tablename=inflection.tableize(cls.name),
tableparams=["this"] + ["result" if p is prop else "_" for p in cls.properties if p.is_single],
doc=_get_doc(cls, prop),
)
elif prop.is_repeated:
args.update(
singular=inflection.singularize(inflection.camelize(prop.name)),
plural=inflection.pluralize(inflection.camelize(prop.name)),
singular=inflection.singularize(inflection.camelize(ql_name)),
plural=inflection.pluralize(inflection.camelize(ql_name)),
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
tableparams=["this", "index", "result"] if not prop.is_unordered else ["this", "result"],
doc=_get_doc(cls, prop, plural=False),
doc_plural=_get_doc(cls, prop, plural=True),
)
elif prop.is_optional:
args.update(
singular=inflection.camelize(prop.name),
singular=inflection.camelize(ql_name),
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
tableparams=["this", "result"],
doc=_get_doc(cls, prop),
)
elif prop.is_predicate:
args.update(
singular=inflection.camelize(prop.name, uppercase_first_letter=False),
singular=inflection.camelize(ql_name, uppercase_first_letter=False),
tablename=inflection.underscore(f"{cls.name}_{prop.name}"),
tableparams=["this"],
doc=_get_doc(cls, prop),
Expand All @@ -154,6 +155,8 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic


def get_ql_class(cls: schema.Class, lookup: typing.Dict[str, schema.Class]) -> ql.Class:
if "ql_name" in cls.pragmas:
raise Error("ql_name is not supported yet for classes, only for properties")
prev_child = ""
properties = []
for p in cls.properties:
Expand Down
27 changes: 11 additions & 16 deletions misc/codegen/lib/schemadefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ def include(source: str):
@_dataclass
class _Namespace:
""" simple namespacing mechanism """
name: str
_name: str

def add(self, pragma: "_PragmaBase", key: str | None = None):
self.__dict__[pragma.pragma] = pragma
pragma.pragma = key or f"{self.name}_{pragma.pragma}"
pragma.pragma = key or f"{self._name}_{pragma.pragma}"


@_dataclass
Expand All @@ -87,7 +87,7 @@ def modify(self, prop: _schema.Property):
prop.synth = self.synth

def negate(self) -> _schema.PropertyModifier:
return _SynthModifier(self.name, False)
return _SynthModifier(self._name, False)


qltest = _Namespace("qltest")
Expand Down Expand Up @@ -239,6 +239,7 @@ def __getitem__(self, item):
ql.add(_ParametrizedClassPragma("default_doc_name", factory=lambda doc: doc))
ql.add(_ClassPragma("hideable", inherited=True))
ql.add(_Pragma("internal"))
ql.add(_ParametrizedPragma("name", factory=lambda name: name))

cpp.add(_Pragma("skip"))

Expand All @@ -256,38 +257,32 @@ def __getitem__(self, item):
_schema.SynthInfo(on_arguments={k: _schema.get_type_name(t) for k, t in kwargs.items()})), key="synth")


@_dataclass(frozen=True)
class _PropertyModifierList(_schema.PropertyModifier):
def __init__(self):
self._mods = []
_mods: tuple[_schema.PropertyModifier, ...]

def __or__(self, other: _schema.PropertyModifier):
self._mods.append(other)
return self
return _PropertyModifierList(self._mods + (other,))

def modify(self, prop: Property):
for m in self._mods:
m.modify(prop)


class _PropertyAnnotation:
def __or__(self, other: _schema.PropertyModifier):
return _PropertyModifierList() | other


_ = _PropertyAnnotation()
_ = _PropertyModifierList(())

drop = object()


def annotate(annotated_cls: type, add_bases: _Iterable[type] | None = None, replace_bases: _Dict[type, type] | None = None, cfg: bool = False) -> _Callable[[type], _PropertyAnnotation]:
def annotate(annotated_cls: type, add_bases: _Iterable[type] | None = None, replace_bases: _Dict[type, type] | None = None, cfg: bool = False) -> _Callable[[type], _PropertyModifierList]:
"""
Add or modify schema annotations after a class has been defined previously.
The name of the class used for annotation must be `_`.
`replace_bases` can be used to replace bases on the annotated class.
"""
def decorator(cls: type) -> _PropertyAnnotation:
def decorator(cls: type) -> _PropertyModifierList:
if cls.__name__ != "_":
raise _schema.Error("Annotation classes must be named _")
if cls.__doc__ is not None:
Expand All @@ -307,7 +302,7 @@ def decorator(cls: type) -> _PropertyAnnotation:
del annotated_cls.__annotations__[p]
elif p in annotated_cls.__annotations__:
annotated_cls.__annotations__[p] |= a
elif isinstance(a, (_PropertyAnnotation, _PropertyModifierList)):
elif isinstance(a, (_PropertyModifierList, _PropertyModifierList)):
raise _schema.Error(f"annotated property {p} not present in annotated class "
f"{annotated_cls.__name__}")
else:
Expand Down
12 changes: 6 additions & 6 deletions rust/ql/.generated.list

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rust/ql/.gitattributes

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -514,14 +514,14 @@ module ExprTrees {

class MatchExprTree extends PostOrderTree instanceof MatchExpr {
override predicate propagatesAbnormal(AstNode child) {
child = [super.getExpr(), super.getAnArm().getExpr()]
child = [super.getScrutinee(), super.getAnArm().getExpr()]
}

override predicate first(AstNode node) { first(super.getExpr(), node) }
override predicate first(AstNode node) { first(super.getScrutinee(), node) }

override predicate succ(AstNode pred, AstNode succ, Completion c) {
// Edge from the scrutinee to the first arm or to the match expression if no arms.
last(super.getExpr(), pred, c) and
last(super.getScrutinee(), pred, c) and
(
first(super.getArm(0).getPat(), succ)
or
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module Impl {
*/
class MatchExpr extends Generated::MatchExpr {
override string toString() {
result = "match " + this.getExpr().toAbbreviatedString() + " { ... }"
result = "match " + this.getScrutinee().toAbbreviatedString() + " { ... }"
}

/**
Expand Down
Loading

0 comments on commit c3b4447

Please sign in to comment.