mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge branch 'master' into overflowcalc
This commit is contained in:
@@ -10,12 +10,25 @@ import cpp
|
||||
/**
|
||||
* An alert suppression comment.
|
||||
*/
|
||||
class SuppressionComment extends CppStyleComment {
|
||||
class SuppressionComment extends Comment {
|
||||
string annotation;
|
||||
string text;
|
||||
|
||||
SuppressionComment() {
|
||||
text = getContents().suffix(2) and
|
||||
(
|
||||
this instanceof CppStyleComment and
|
||||
// strip the beginning slashes
|
||||
text = getContents().suffix(2)
|
||||
or
|
||||
this instanceof CStyleComment and
|
||||
// strip both the beginning /* and the end */ the comment
|
||||
exists(string text0 |
|
||||
text0 = getContents().suffix(2) and
|
||||
text = text0.prefix(text0.length() - 2)
|
||||
) and
|
||||
// The /* */ comment must be a single-line comment
|
||||
not text.matches("%\n%")
|
||||
) and
|
||||
(
|
||||
// match `lgtm[...]` anywhere in the comment
|
||||
annotation = text.regexpFind("(?i)\\blgtm\\s*\\[[^\\]]*\\]", _, _)
|
||||
|
||||
@@ -157,4 +157,6 @@ library class SpecialNameQualifyingElement extends NameQualifyingElement,
|
||||
@specialnamequalifyingelement {
|
||||
/** Gets the name of this special qualifying element. */
|
||||
override string getName() { specialnamequalifyingelements(underlyingElement(this), result) }
|
||||
|
||||
override string toString() { result = getName() }
|
||||
}
|
||||
|
||||
@@ -214,7 +214,9 @@ class PreprocessorUndef extends PreprocessorDirective, @ppd_undef {
|
||||
* A C/C++ preprocessor `#pragma` directive.
|
||||
*/
|
||||
class PreprocessorPragma extends PreprocessorDirective, @ppd_pragma {
|
||||
override string toString() { result = "#pragma " + this.getHead() }
|
||||
override string toString() {
|
||||
if exists(this.getHead()) then result = "#pragma " + this.getHead() else result = "#pragma"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Provides classes and predicates for working with XML files and their content.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Location
|
||||
import semmle.files.FileSystem
|
||||
|
||||
/** An XML element that has a location. */
|
||||
abstract class XMLLocatable extends @xmllocatable {
|
||||
@@ -10,19 +10,22 @@ abstract class XMLLocatable extends @xmllocatable {
|
||||
Location getLocation() { xmllocations(this, result) }
|
||||
|
||||
/**
|
||||
* Holds if this element has the specified location information,
|
||||
* including file path, start line, start column, end line and end column.
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
exists(File f, Location l | l = this.getLocation() |
|
||||
locations_default(l, unresolveElement(f), startline, startcolumn, endline, endcolumn) and
|
||||
locations_default(l, f, startline, startcolumn, endline, endcolumn) and
|
||||
filepath = f.getAbsolutePath()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this element. */
|
||||
/** Gets a textual representation of this element. */
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
@@ -31,6 +34,12 @@ abstract class XMLLocatable extends @xmllocatable {
|
||||
* both of which can contain other elements.
|
||||
*/
|
||||
class XMLParent extends @xmlparent {
|
||||
XMLParent() {
|
||||
// explicitly restrict `this` to be either an `XMLElement` or an `XMLFile`;
|
||||
// the type `@xmlparent` currently also includes non-XML files
|
||||
this instanceof @xmlelement or xmlEncoding(this, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a printable representation of this XML parent.
|
||||
* (Intended to be overridden in subclasses.)
|
||||
@@ -106,15 +115,21 @@ class XMLFile extends XMLParent, File {
|
||||
override string toString() { result = XMLParent.super.toString() }
|
||||
|
||||
/** Gets the name of this XML file. */
|
||||
override string getName() { files(this, result, _, _, _) }
|
||||
override string getName() { result = File.super.getAbsolutePath() }
|
||||
|
||||
/** Gets the path of this XML file. */
|
||||
string getPath() { files(this, _, result, _, _) }
|
||||
/**
|
||||
* DEPRECATED: Use `getAbsolutePath()` instead.
|
||||
*
|
||||
* Gets the path of this XML file.
|
||||
*/
|
||||
deprecated string getPath() { result = getAbsolutePath() }
|
||||
|
||||
/** Gets the path of the folder that contains this XML file. */
|
||||
string getFolder() {
|
||||
result = this.getPath().substring(0, this.getPath().length() - this.getName().length())
|
||||
}
|
||||
/**
|
||||
* DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
|
||||
*
|
||||
* Gets the path of the folder that contains this XML file.
|
||||
*/
|
||||
deprecated string getFolder() { result = getParentContainer().getAbsolutePath() }
|
||||
|
||||
/** Gets the encoding of this XML file. */
|
||||
string getEncoding() { xmlEncoding(this, result) }
|
||||
@@ -129,7 +144,17 @@ class XMLFile extends XMLParent, File {
|
||||
XMLDTD getADTD() { xmlDTDs(result, _, _, _, this) }
|
||||
}
|
||||
|
||||
/** A "Document Type Definition" of an XML file. */
|
||||
/**
|
||||
* An XML document type definition (DTD).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!ELEMENT person (firstName, lastName?)>
|
||||
* <!ELEMENT firstName (#PCDATA)>
|
||||
* <!ELEMENT lastName (#PCDATA)>
|
||||
* ```
|
||||
*/
|
||||
class XMLDTD extends @xmldtd {
|
||||
/** Gets the name of the root element of this DTD. */
|
||||
string getRoot() { xmlDTDs(this, result, _, _, _) }
|
||||
@@ -156,7 +181,17 @@ class XMLDTD extends @xmldtd {
|
||||
}
|
||||
}
|
||||
|
||||
/** An XML tag in an XML file. */
|
||||
/**
|
||||
* An XML element in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* package="com.example.exampleapp" android:versionCode="1">
|
||||
* </manifest>
|
||||
* ```
|
||||
*/
|
||||
class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||
/** Holds if this XML element has the given `name`. */
|
||||
predicate hasName(string name) { name = getName() }
|
||||
@@ -201,7 +236,16 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||
override string toString() { result = XMLParent.super.toString() }
|
||||
}
|
||||
|
||||
/** An attribute that occurs inside an XML element. */
|
||||
/**
|
||||
* An attribute that occurs inside an XML element.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* ```
|
||||
* package="com.example.exampleapp"
|
||||
* android:versionCode="1"
|
||||
* ```
|
||||
*/
|
||||
class XMLAttribute extends @xmlattribute, XMLLocatable {
|
||||
/** Gets the name of this attribute. */
|
||||
string getName() { xmlAttrs(this, _, result, _, _, _) }
|
||||
@@ -222,7 +266,15 @@ class XMLAttribute extends @xmlattribute, XMLLocatable {
|
||||
override string toString() { result = this.getName() + "=" + this.getValue() }
|
||||
}
|
||||
|
||||
/** A namespace used in an XML file */
|
||||
/**
|
||||
* A namespace used in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* ```
|
||||
*/
|
||||
class XMLNamespace extends @xmlnamespace {
|
||||
/** Gets the prefix of this namespace. */
|
||||
string getPrefix() { xmlNs(this, result, _, _) }
|
||||
@@ -241,7 +293,15 @@ class XMLNamespace extends @xmlnamespace {
|
||||
}
|
||||
}
|
||||
|
||||
/** A comment of the form `<!-- ... -->` is an XML comment. */
|
||||
/**
|
||||
* A comment in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!-- This is a comment. -->
|
||||
* ```
|
||||
*/
|
||||
class XMLComment extends @xmlcomment, XMLLocatable {
|
||||
/** Gets the text content of this XML comment. */
|
||||
string getText() { xmlComments(this, result, _, _) }
|
||||
@@ -256,6 +316,12 @@ class XMLComment extends @xmlcomment, XMLLocatable {
|
||||
/**
|
||||
* A sequence of characters that occurs between opening and
|
||||
* closing tags of an XML element, excluding other elements.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <content>This is a sequence of characters.</content>
|
||||
* ```
|
||||
*/
|
||||
class XMLCharacters extends @xmlcharacters, XMLLocatable {
|
||||
/** Gets the content of this character sequence. */
|
||||
|
||||
@@ -19,10 +19,32 @@ private predicate predictableInstruction(Instruction instr) {
|
||||
predictableInstruction(instr.(UnaryInstruction).getUnary())
|
||||
}
|
||||
|
||||
private predicate userInputInstruction(Instruction instr) {
|
||||
exists(CallInstruction ci, WriteSideEffectInstruction wsei |
|
||||
userInputArgument(ci.getConvertedResultExpression(), wsei.getIndex()) and
|
||||
instr = wsei and
|
||||
wsei.getPrimaryInstruction() = ci
|
||||
)
|
||||
or
|
||||
userInputReturned(instr.getConvertedResultExpression())
|
||||
or
|
||||
instr.getConvertedResultExpression() instanceof EnvironmentRead
|
||||
or
|
||||
instr
|
||||
.(LoadInstruction)
|
||||
.getSourceAddress()
|
||||
.(VariableAddressInstruction)
|
||||
.getASTVariable()
|
||||
.hasName("argv") and
|
||||
instr.getEnclosingFunction().hasGlobalName("main")
|
||||
}
|
||||
|
||||
private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
|
||||
DefaultTaintTrackingCfg() { this = "DefaultTaintTrackingCfg" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { isUserInput(source.asExpr(), _) }
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
userInputInstruction(source.asInstruction())
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { any() }
|
||||
|
||||
@@ -135,6 +157,8 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
|
||||
// This is part of the translation of `a[i]`, where we want taint to flow
|
||||
// from `a`.
|
||||
i2.(PointerAddInstruction).getLeft() = i1
|
||||
// TODO: robust Chi handling
|
||||
//
|
||||
// TODO: Flow from argument to return of known functions: Port missing parts
|
||||
// of `returnArgument` to the `interfaces.Taint` and `interfaces.DataFlow`
|
||||
// libraries.
|
||||
@@ -176,11 +200,30 @@ private Element adjustedSink(DataFlow::Node sink) {
|
||||
// For compatibility, send flow into a `NotExpr` even if it's part of a
|
||||
// short-circuiting condition and thus might get skipped.
|
||||
result.(NotExpr).getOperand() = sink.asExpr()
|
||||
or
|
||||
// For compatibility, send flow from argument read side effects to their
|
||||
// corresponding argument expression
|
||||
exists(IndirectReadSideEffectInstruction read |
|
||||
read.getAnOperand().(SideEffectOperand).getAnyDef() = sink.asInstruction() and
|
||||
read.getArgumentDef().getUnconvertedResultExpression() = result
|
||||
)
|
||||
or
|
||||
exists(BufferReadSideEffectInstruction read |
|
||||
read.getAnOperand().(SideEffectOperand).getAnyDef() = sink.asInstruction() and
|
||||
read.getArgumentDef().getUnconvertedResultExpression() = result
|
||||
)
|
||||
or
|
||||
exists(SizedBufferReadSideEffectInstruction read |
|
||||
read.getAnOperand().(SideEffectOperand).getAnyDef() = sink.asInstruction() and
|
||||
read.getArgumentDef().getUnconvertedResultExpression() = result
|
||||
)
|
||||
}
|
||||
|
||||
predicate tainted(Expr source, Element tainted) {
|
||||
exists(DefaultTaintTrackingCfg cfg, DataFlow::Node sink |
|
||||
cfg.hasFlow(DataFlow::exprNode(source), sink)
|
||||
or
|
||||
cfg.hasFlow(DataFlow::definitionByReferenceNode(source), sink)
|
||||
|
|
||||
tainted = adjustedSink(sink)
|
||||
)
|
||||
|
||||
@@ -173,11 +173,48 @@ abstract class PostUpdateNode extends Node {
|
||||
abstract Node getPreUpdateNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* A node that represents the value of a variable after a function call that
|
||||
* may have changed the variable because it's passed by reference.
|
||||
*
|
||||
* A typical example would be a call `f(&x)`. Firstly, there will be flow into
|
||||
* `x` from previous definitions of `x`. Secondly, there will be a
|
||||
* `DefinitionByReferenceNode` to represent the value of `x` after the call has
|
||||
* returned. This node will have its `getArgument()` equal to `&x` and its
|
||||
* `getVariableAccess()` equal to `x`.
|
||||
*/
|
||||
class DefinitionByReferenceNode extends Node {
|
||||
override WriteSideEffectInstruction instr;
|
||||
|
||||
/** Gets the argument corresponding to this node. */
|
||||
Expr getArgument() {
|
||||
result = instr
|
||||
.getPrimaryInstruction()
|
||||
.(CallInstruction)
|
||||
.getPositionalArgument(instr.getIndex())
|
||||
.getUnconvertedResultExpression()
|
||||
or
|
||||
result = instr
|
||||
.getPrimaryInstruction()
|
||||
.(CallInstruction)
|
||||
.getThisArgument()
|
||||
.getUnconvertedResultExpression() and
|
||||
instr.getIndex() = -1
|
||||
}
|
||||
|
||||
/** Gets the parameter through which this value is assigned. */
|
||||
Parameter getParameter() {
|
||||
exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(instr.getIndex()))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node corresponding to `instr`.
|
||||
*/
|
||||
Node instructionNode(Instruction instr) { result.asInstruction() = instr }
|
||||
|
||||
DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e }
|
||||
|
||||
/**
|
||||
* Gets a `Node` corresponding to `e` or any of its conversions. There is no
|
||||
* result if `e` is a `Conversion`.
|
||||
|
||||
@@ -1236,6 +1236,8 @@ class IndirectReadSideEffectInstruction extends SideEffectInstruction {
|
||||
IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect }
|
||||
|
||||
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
|
||||
|
||||
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1245,6 +1247,8 @@ class BufferReadSideEffectInstruction extends SideEffectInstruction {
|
||||
BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect }
|
||||
|
||||
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
|
||||
|
||||
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1258,12 +1262,14 @@ class SizedBufferReadSideEffectInstruction extends SideEffectInstruction {
|
||||
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
|
||||
|
||||
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
|
||||
|
||||
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing a side effect of a function call.
|
||||
*/
|
||||
class WriteSideEffectInstruction extends SideEffectInstruction {
|
||||
class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction {
|
||||
WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode }
|
||||
|
||||
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
|
||||
|
||||
@@ -1236,6 +1236,8 @@ class IndirectReadSideEffectInstruction extends SideEffectInstruction {
|
||||
IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect }
|
||||
|
||||
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
|
||||
|
||||
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1245,6 +1247,8 @@ class BufferReadSideEffectInstruction extends SideEffectInstruction {
|
||||
BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect }
|
||||
|
||||
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
|
||||
|
||||
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1258,12 +1262,14 @@ class SizedBufferReadSideEffectInstruction extends SideEffectInstruction {
|
||||
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
|
||||
|
||||
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
|
||||
|
||||
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing a side effect of a function call.
|
||||
*/
|
||||
class WriteSideEffectInstruction extends SideEffectInstruction {
|
||||
class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction {
|
||||
WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode }
|
||||
|
||||
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
|
||||
|
||||
@@ -143,26 +143,23 @@ private module Cached {
|
||||
.getInstructionSuccessor(getInstructionTag(instruction), kind)
|
||||
}
|
||||
|
||||
// This predicate has pragma[noopt] because otherwise the `getAChild*` calls
|
||||
// get joined too early. The join order for the loop cases goes like this:
|
||||
// - Find all loops of that type (tens of thousands).
|
||||
// - Find all edges into the start of the loop (x 2).
|
||||
// - Restrict to edges that originate within the loop (/ 2).
|
||||
pragma[noopt]
|
||||
cached
|
||||
Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
/**
|
||||
* Holds if the CFG edge (`sourceElement`, `sourceTag`) ---`kind`-->
|
||||
* `targetInstruction` is a back edge under the condition that
|
||||
* `requiredAncestor` is an ancestor of `sourceElement`.
|
||||
*/
|
||||
private predicate backEdgeCandidate(
|
||||
TranslatedElement sourceElement, InstructionTag sourceTag, TranslatedElement requiredAncestor,
|
||||
Instruction targetInstruction, EdgeKind kind
|
||||
) {
|
||||
// While loop:
|
||||
// Any edge from within the body of the loop to the condition of the loop
|
||||
// is a back edge. This includes edges from `continue` and the fall-through
|
||||
// edge(s) after the last instruction(s) in the body.
|
||||
exists(TranslatedWhileStmt s |
|
||||
s instanceof TranslatedWhileStmt and
|
||||
result = s.getFirstConditionInstruction() and
|
||||
exists(TranslatedElement inBody, InstructionTag tag |
|
||||
result = inBody.getInstructionSuccessor(tag, kind) and
|
||||
exists(TranslatedElement body | body = s.getBody() | inBody = body.getAChild*()) and
|
||||
instruction = inBody.getInstruction(tag)
|
||||
)
|
||||
targetInstruction = s.getFirstConditionInstruction() and
|
||||
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
|
||||
requiredAncestor = s.getBody()
|
||||
)
|
||||
or
|
||||
// Do-while loop:
|
||||
@@ -171,15 +168,9 @@ private module Cached {
|
||||
// { ... } while (0)` statement. Note that all `continue` statements in a
|
||||
// do-while loop produce forward edges.
|
||||
exists(TranslatedDoStmt s |
|
||||
s instanceof TranslatedDoStmt and
|
||||
exists(TranslatedStmt body | body = s.getBody() | result = body.getFirstInstruction()) and
|
||||
exists(TranslatedElement inCondition, InstructionTag tag |
|
||||
result = inCondition.getInstructionSuccessor(tag, kind) and
|
||||
exists(TranslatedElement condition | condition = s.getCondition() |
|
||||
inCondition = condition.getAChild*()
|
||||
) and
|
||||
instruction = inCondition.getInstruction(tag)
|
||||
)
|
||||
targetInstruction = s.getBody().getFirstInstruction() and
|
||||
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
|
||||
requiredAncestor = s.getCondition()
|
||||
)
|
||||
or
|
||||
// For loop:
|
||||
@@ -189,33 +180,42 @@ private module Cached {
|
||||
// last instruction(s) in the body. A for loop may not have a condition, in
|
||||
// which case `getFirstConditionInstruction` returns the body instead.
|
||||
exists(TranslatedForStmt s |
|
||||
s instanceof TranslatedForStmt and
|
||||
result = s.getFirstConditionInstruction() and
|
||||
exists(TranslatedElement inLoop, InstructionTag tag |
|
||||
result = inLoop.getInstructionSuccessor(tag, kind) and
|
||||
exists(TranslatedElement bodyOrUpdate |
|
||||
bodyOrUpdate = s.getBody()
|
||||
or
|
||||
bodyOrUpdate = s.getUpdate()
|
||||
|
|
||||
inLoop = bodyOrUpdate.getAChild*()
|
||||
) and
|
||||
instruction = inLoop.getInstruction(tag)
|
||||
targetInstruction = s.getFirstConditionInstruction() and
|
||||
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
|
||||
(
|
||||
requiredAncestor = s.getUpdate()
|
||||
or
|
||||
not exists(s.getUpdate()) and
|
||||
requiredAncestor = s.getBody()
|
||||
)
|
||||
)
|
||||
or
|
||||
// Range-based for loop:
|
||||
// Any edge from within the update of the loop to the condition of
|
||||
// the loop is a back edge.
|
||||
exists(TranslatedRangeBasedForStmt s, TranslatedCondition condition |
|
||||
s instanceof TranslatedRangeBasedForStmt and
|
||||
condition = s.getCondition() and
|
||||
result = condition.getFirstInstruction() and
|
||||
exists(TranslatedElement inUpdate, InstructionTag tag |
|
||||
result = inUpdate.getInstructionSuccessor(tag, kind) and
|
||||
exists(TranslatedElement update | update = s.getUpdate() | inUpdate = update.getAChild*()) and
|
||||
instruction = inUpdate.getInstruction(tag)
|
||||
)
|
||||
exists(TranslatedRangeBasedForStmt s |
|
||||
targetInstruction = s.getCondition().getFirstInstruction() and
|
||||
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
|
||||
requiredAncestor = s.getUpdate()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate jumpSourceHasAncestor(TranslatedElement jumpSource, TranslatedElement ancestor) {
|
||||
backEdgeCandidate(jumpSource, _, _, _, _) and
|
||||
ancestor = jumpSource
|
||||
or
|
||||
// For performance, we don't want a fastTC here
|
||||
jumpSourceHasAncestor(jumpSource, ancestor.getAChild())
|
||||
}
|
||||
|
||||
cached
|
||||
Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
exists(
|
||||
TranslatedElement sourceElement, InstructionTag sourceTag, TranslatedElement requiredAncestor
|
||||
|
|
||||
backEdgeCandidate(sourceElement, sourceTag, requiredAncestor, result, kind) and
|
||||
jumpSourceHasAncestor(sourceElement, requiredAncestor) and
|
||||
instruction = sourceElement.getInstruction(sourceTag)
|
||||
)
|
||||
or
|
||||
// Goto statement:
|
||||
@@ -225,7 +225,6 @@ private module Cached {
|
||||
// same location for source and target, so we conservatively assume that
|
||||
// such a `goto` creates a back edge.
|
||||
exists(TranslatedElement s, GotoStmt goto |
|
||||
goto instanceof GotoStmt and
|
||||
not isStrictlyForwardGoto(goto) and
|
||||
goto = s.getAST() and
|
||||
exists(InstructionTag tag |
|
||||
|
||||
@@ -1236,6 +1236,8 @@ class IndirectReadSideEffectInstruction extends SideEffectInstruction {
|
||||
IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect }
|
||||
|
||||
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
|
||||
|
||||
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1245,6 +1247,8 @@ class BufferReadSideEffectInstruction extends SideEffectInstruction {
|
||||
BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect }
|
||||
|
||||
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
|
||||
|
||||
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1258,12 +1262,14 @@ class SizedBufferReadSideEffectInstruction extends SideEffectInstruction {
|
||||
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
|
||||
|
||||
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
|
||||
|
||||
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing a side effect of a function call.
|
||||
*/
|
||||
class WriteSideEffectInstruction extends SideEffectInstruction {
|
||||
class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction {
|
||||
WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode }
|
||||
|
||||
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
private import implementations.Allocation
|
||||
private import implementations.Deallocation
|
||||
private import implementations.Fread
|
||||
private import implementations.IdentityFunction
|
||||
private import implementations.Inet
|
||||
private import implementations.Memcpy
|
||||
|
||||
14
cpp/ql/src/semmle/code/cpp/models/implementations/Fread.qll
Normal file
14
cpp/ql/src/semmle/code/cpp/models/implementations/Fread.qll
Normal file
@@ -0,0 +1,14 @@
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
|
||||
class Fread extends AliasFunction {
|
||||
Fread() { this.hasGlobalName("fread") }
|
||||
|
||||
override predicate parameterNeverEscapes(int n) {
|
||||
n = 0 or
|
||||
n = 3
|
||||
}
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int n) { none() }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int n) { none() }
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import semmle.code.cpp.models.interfaces.FormattingFunction
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
|
||||
/**
|
||||
* The standard functions `printf`, `wprintf` and their glib variants.
|
||||
*/
|
||||
class Printf extends FormattingFunction {
|
||||
class Printf extends FormattingFunction, AliasFunction {
|
||||
Printf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
@@ -22,6 +23,12 @@ class Printf extends FormattingFunction {
|
||||
hasGlobalOrStdName("wprintf") or
|
||||
hasGlobalName("wprintf_s")
|
||||
}
|
||||
|
||||
override predicate parameterNeverEscapes(int n) { n = 0 }
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int n) { none() }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int n) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
| CPP-205.cpp:8:3:8:15 | return ... | |
|
||||
| CPP-205.cpp:8:10:8:11 | call to fn | |
|
||||
| CPP-205.cpp:8:13:8:13 | 0 | |
|
||||
| file://:0:0:0:0 | __super | |
|
||||
| file://:0:0:0:0 | __va_list_tag | |
|
||||
| file://:0:0:0:0 | operator= | function __va_list_tag::operator=(__va_list_tag &&) -> __va_list_tag & |
|
||||
| file://:0:0:0:0 | operator= | function __va_list_tag::operator=(const __va_list_tag &) -> __va_list_tag & |
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
| clang_ms.cpp:11:5:11:13 | asm statement |
|
||||
| clang_ms.cpp:12:1:12:1 | return ... |
|
||||
| clang_ms.cpp:16:1:16:19 | // Test for CPP-184 |
|
||||
| clang_ms.cpp:17:1:17:32 | #pragma |
|
||||
| clang_ms.cpp:18:1:18:31 | #pragma |
|
||||
| file://:0:0:0:0 | |
|
||||
| file://:0:0:0:0 | (global namespace) |
|
||||
| file://:0:0:0:0 | _Complex __float128 |
|
||||
@@ -48,6 +50,7 @@
|
||||
| file://:0:0:0:0 | __ptr32 |
|
||||
| file://:0:0:0:0 | __ptr64 |
|
||||
| file://:0:0:0:0 | __sptr |
|
||||
| file://:0:0:0:0 | __super |
|
||||
| file://:0:0:0:0 | __uptr |
|
||||
| file://:0:0:0:0 | __va_list_tag |
|
||||
| file://:0:0:0:0 | __va_list_tag & |
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
| file://:0:0:0:0 | __ptr32 |
|
||||
| file://:0:0:0:0 | __ptr64 |
|
||||
| file://:0:0:0:0 | __sptr |
|
||||
| file://:0:0:0:0 | __super |
|
||||
| file://:0:0:0:0 | __uptr |
|
||||
| file://:0:0:0:0 | __va_list_tag |
|
||||
| file://:0:0:0:0 | __va_list_tag & |
|
||||
|
||||
34
cpp/ql/test/library-tests/dataflow/fields/E.cpp
Normal file
34
cpp/ql/test/library-tests/dataflow/fields/E.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
class buf
|
||||
{
|
||||
public:
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
class packet
|
||||
{
|
||||
public:
|
||||
buf data;
|
||||
};
|
||||
|
||||
typedef long ssize_t;
|
||||
|
||||
ssize_t argument_source(void *buf);
|
||||
|
||||
void sink(char *b);
|
||||
|
||||
void handlePacket(packet *p)
|
||||
{
|
||||
sink(p->data.buffer);
|
||||
}
|
||||
|
||||
void f(buf* b)
|
||||
{
|
||||
char *raw;
|
||||
packet p;
|
||||
argument_source(raw);
|
||||
argument_source(b->buffer);
|
||||
argument_source(p.data.buffer);
|
||||
sink(raw);
|
||||
sink(b->buffer);
|
||||
handlePacket(&p);
|
||||
}
|
||||
@@ -122,6 +122,17 @@ edges
|
||||
| D.cpp:64:10:64:17 | boxfield [box, elem] | D.cpp:64:20:64:22 | box [elem] |
|
||||
| D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | D.cpp:64:10:64:17 | boxfield [box, elem] |
|
||||
| D.cpp:64:20:64:22 | box [elem] | D.cpp:64:25:64:28 | elem |
|
||||
| E.cpp:19:27:19:27 | p [data, buffer] | E.cpp:21:10:21:10 | p [data, buffer] |
|
||||
| E.cpp:21:10:21:10 | p [data, buffer] | E.cpp:21:13:21:16 | data [buffer] |
|
||||
| E.cpp:21:13:21:16 | data [buffer] | E.cpp:21:18:21:23 | buffer |
|
||||
| E.cpp:28:21:28:23 | ref arg raw | E.cpp:31:10:31:12 | raw |
|
||||
| E.cpp:29:21:29:21 | b [post update] [buffer] | E.cpp:32:10:32:10 | b [buffer] |
|
||||
| E.cpp:29:24:29:29 | ref arg buffer | E.cpp:29:21:29:21 | b [post update] [buffer] |
|
||||
| E.cpp:30:21:30:21 | p [post update] [data, buffer] | E.cpp:33:18:33:19 | & ... [data, buffer] |
|
||||
| E.cpp:30:23:30:26 | data [post update] [buffer] | E.cpp:30:21:30:21 | p [post update] [data, buffer] |
|
||||
| E.cpp:30:28:30:33 | ref arg buffer | E.cpp:30:23:30:26 | data [post update] [buffer] |
|
||||
| E.cpp:32:10:32:10 | b [buffer] | E.cpp:32:13:32:18 | buffer |
|
||||
| E.cpp:33:18:33:19 | & ... [data, buffer] | E.cpp:19:27:19:27 | p [data, buffer] |
|
||||
| aliasing.cpp:9:3:9:3 | s [post update] [m1] | aliasing.cpp:25:17:25:19 | ref arg & ... [m1] |
|
||||
| aliasing.cpp:9:3:9:22 | ... = ... | aliasing.cpp:9:3:9:3 | s [post update] [m1] |
|
||||
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | ... = ... |
|
||||
@@ -378,6 +389,20 @@ nodes
|
||||
| D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] |
|
||||
| D.cpp:64:20:64:22 | box [elem] | semmle.label | box [elem] |
|
||||
| D.cpp:64:25:64:28 | elem | semmle.label | elem |
|
||||
| E.cpp:19:27:19:27 | p [data, buffer] | semmle.label | p [data, buffer] |
|
||||
| E.cpp:21:10:21:10 | p [data, buffer] | semmle.label | p [data, buffer] |
|
||||
| E.cpp:21:13:21:16 | data [buffer] | semmle.label | data [buffer] |
|
||||
| E.cpp:21:18:21:23 | buffer | semmle.label | buffer |
|
||||
| E.cpp:28:21:28:23 | ref arg raw | semmle.label | ref arg raw |
|
||||
| E.cpp:29:21:29:21 | b [post update] [buffer] | semmle.label | b [post update] [buffer] |
|
||||
| E.cpp:29:24:29:29 | ref arg buffer | semmle.label | ref arg buffer |
|
||||
| E.cpp:30:21:30:21 | p [post update] [data, buffer] | semmle.label | p [post update] [data, buffer] |
|
||||
| E.cpp:30:23:30:26 | data [post update] [buffer] | semmle.label | data [post update] [buffer] |
|
||||
| E.cpp:30:28:30:33 | ref arg buffer | semmle.label | ref arg buffer |
|
||||
| E.cpp:31:10:31:12 | raw | semmle.label | raw |
|
||||
| E.cpp:32:10:32:10 | b [buffer] | semmle.label | b [buffer] |
|
||||
| E.cpp:32:13:32:18 | buffer | semmle.label | buffer |
|
||||
| E.cpp:33:18:33:19 | & ... [data, buffer] | semmle.label | & ... [data, buffer] |
|
||||
| aliasing.cpp:9:3:9:3 | s [post update] [m1] | semmle.label | s [post update] [m1] |
|
||||
| aliasing.cpp:9:3:9:22 | ... = ... | semmle.label | ... = ... |
|
||||
| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input |
|
||||
@@ -532,6 +557,9 @@ nodes
|
||||
| D.cpp:22:25:22:31 | call to getElem | D.cpp:42:15:42:24 | new | D.cpp:22:25:22:31 | call to getElem | call to getElem flows from $@ | D.cpp:42:15:42:24 | new | new |
|
||||
| D.cpp:22:25:22:31 | call to getElem | D.cpp:49:15:49:24 | new | D.cpp:22:25:22:31 | call to getElem | call to getElem flows from $@ | D.cpp:49:15:49:24 | new | new |
|
||||
| D.cpp:64:25:64:28 | elem | D.cpp:56:15:56:24 | new | D.cpp:64:25:64:28 | elem | elem flows from $@ | D.cpp:56:15:56:24 | new | new |
|
||||
| E.cpp:21:18:21:23 | buffer | E.cpp:30:28:30:33 | ref arg buffer | E.cpp:21:18:21:23 | buffer | buffer flows from $@ | E.cpp:30:28:30:33 | ref arg buffer | ref arg buffer |
|
||||
| E.cpp:31:10:31:12 | raw | E.cpp:28:21:28:23 | ref arg raw | E.cpp:31:10:31:12 | raw | raw flows from $@ | E.cpp:28:21:28:23 | ref arg raw | ref arg raw |
|
||||
| E.cpp:32:13:32:18 | buffer | E.cpp:29:24:29:29 | ref arg buffer | E.cpp:32:13:32:18 | buffer | buffer flows from $@ | E.cpp:29:24:29:29 | ref arg buffer | ref arg buffer |
|
||||
| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input | call to user_input |
|
||||
| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input | call to user_input |
|
||||
| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input | call to user_input |
|
||||
|
||||
@@ -14,6 +14,11 @@ class Conf extends Configuration {
|
||||
src.asExpr() instanceof NewExpr
|
||||
or
|
||||
src.asExpr().(Call).getTarget().hasName("user_input")
|
||||
or
|
||||
exists(FunctionCall fc |
|
||||
fc.getAnArgument() = src.asDefiningArgument() and
|
||||
fc.getTarget().hasName("argument_source")
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(Node sink) {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
| c.c | library-tests/files/c.c |
|
||||
| files1.cpp | library-tests/files/files1.cpp |
|
||||
| files1.h | library-tests/files/files1.h |
|
||||
| files2.cpp | library-tests/files/files2.cpp |
|
||||
@@ -1,5 +0,0 @@
|
||||
import cpp
|
||||
|
||||
from File f
|
||||
where f.toString() != ""
|
||||
select f.toString(), f.getRelativePath()
|
||||
4
cpp/ql/test/library-tests/files/Files.expected
Normal file
4
cpp/ql/test/library-tests/files/Files.expected
Normal file
@@ -0,0 +1,4 @@
|
||||
| c.c | library-tests/files/c.c | CFile, MetricFile | C | | |
|
||||
| files1.cpp | library-tests/files/files1.cpp | CppFile, MetricFile | C++ | swap | t |
|
||||
| files1.h | library-tests/files/files1.h | HeaderFile, MetricFile | | swap | |
|
||||
| files2.cpp | library-tests/files/files2.cpp | CppFile, MetricFile | C++ | g | x, y |
|
||||
18
cpp/ql/test/library-tests/files/Files.ql
Normal file
18
cpp/ql/test/library-tests/files/Files.ql
Normal file
@@ -0,0 +1,18 @@
|
||||
import cpp
|
||||
|
||||
string describe(File f) {
|
||||
f.compiledAsC() and
|
||||
result = "C"
|
||||
or
|
||||
f.compiledAsCpp() and
|
||||
result = "C++"
|
||||
or
|
||||
f instanceof XMLParent and
|
||||
result = "XMLParent" // regression tests a bug in the characteristic predicate of XMLParent
|
||||
}
|
||||
|
||||
from File f
|
||||
where f.toString() != ""
|
||||
select f.toString(), f.getRelativePath(), concat(f.getAQlClass().toString(), ", "),
|
||||
concat(describe(f), ", "), concat(f.getATopLevelDeclaration().toString(), ", "),
|
||||
concat(LocalVariable v | f.getADeclaration() = v | v.toString(), ", ")
|
||||
@@ -1 +0,0 @@
|
||||
| files1.h:0:0:0:0 | files1.h | files1.cpp:4:6:4:9 | swap |
|
||||
@@ -1,4 +0,0 @@
|
||||
import cpp
|
||||
|
||||
from HeaderFile f
|
||||
select f, f.getATopLevelDeclaration()
|
||||
@@ -1,8 +0,0 @@
|
||||
| CFile | C | --- | c.c |
|
||||
| CppFile | - | C++ | files1.cpp |
|
||||
| CppFile | - | C++ | files2.cpp |
|
||||
| HeaderFile | - | --- | files1.h |
|
||||
| MetricFile | - | --- | files1.h |
|
||||
| MetricFile | - | C++ | files1.cpp |
|
||||
| MetricFile | - | C++ | files2.cpp |
|
||||
| MetricFile | C | --- | c.c |
|
||||
@@ -1,11 +0,0 @@
|
||||
import cpp
|
||||
|
||||
string isCompiledAsC(File f) { if f.compiledAsC() then result = "C" else result = "-" }
|
||||
|
||||
string isCompiledAsCpp(File f) { if f.compiledAsCpp() then result = "C++" else result = "---" }
|
||||
|
||||
from File f
|
||||
// On 64bit Linux, __va_list_tag is in the unknown file (""). Ignore it.
|
||||
where f.getAbsolutePath() != ""
|
||||
select (f.getAQlClass().toString() + " ").prefix(10), isCompiledAsC(f), isCompiledAsCpp(f),
|
||||
f.toString()
|
||||
@@ -1,3 +0,0 @@
|
||||
| files1.cpp | files1.cpp:4:6:4:9 | swap |
|
||||
| files1.h | files1.cpp:4:6:4:9 | swap |
|
||||
| files2.cpp | files2.cpp:3:6:3:6 | g |
|
||||
@@ -1,7 +0,0 @@
|
||||
import cpp
|
||||
|
||||
from File f, Declaration d
|
||||
where
|
||||
d = f.getATopLevelDeclaration() and
|
||||
d.getName() != "__va_list_tag"
|
||||
select f.toString(), d
|
||||
@@ -1,3 +0,0 @@
|
||||
| files1.cpp | files1.cpp:6:6:6:6 | t |
|
||||
| files2.cpp | files2.cpp:4:6:4:6 | x |
|
||||
| files2.cpp | files2.cpp:5:6:5:6 | y |
|
||||
@@ -1,5 +0,0 @@
|
||||
import cpp
|
||||
|
||||
from File f, LocalVariable v
|
||||
where f.getADeclaration() = v
|
||||
select f.toString(), v
|
||||
@@ -201,6 +201,7 @@
|
||||
| file://:0:0:0:0 | ..(*)(..) |
|
||||
| file://:0:0:0:0 | ..(*)(..) |
|
||||
| file://:0:0:0:0 | ..(..) |
|
||||
| file://:0:0:0:0 | __super |
|
||||
| file://:0:0:0:0 | __va_list_tag |
|
||||
| file://:0:0:0:0 | __va_list_tag & |
|
||||
| file://:0:0:0:0 | __va_list_tag && |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
| file://:0:0:0:0 | __super | false |
|
||||
| file://:0:0:0:0 | __va_list_tag | false |
|
||||
| file://:0:0:0:0 | operator= | false |
|
||||
| file://:0:0:0:0 | operator= | false |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import cpp
|
||||
|
||||
from Expr e
|
||||
where exists(e.toString())
|
||||
select e, e.getType()
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
| file://:0:0:0:0 | X |
|
||||
| file://:0:0:0:0 | X |
|
||||
| file://:0:0:0:0 | Y |
|
||||
| file://:0:0:0:0 | __super |
|
||||
| file://:0:0:0:0 | __va_list_tag |
|
||||
| file://:0:0:0:0 | __va_list_tag & |
|
||||
| file://:0:0:0:0 | __va_list_tag && |
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
| file://:0:0:0:0 | __ptr32 |
|
||||
| file://:0:0:0:0 | __ptr64 |
|
||||
| file://:0:0:0:0 | __sptr |
|
||||
| file://:0:0:0:0 | __super |
|
||||
| file://:0:0:0:0 | __uptr |
|
||||
| file://:0:0:0:0 | __va_list_tag |
|
||||
| file://:0:0:0:0 | __va_list_tag & |
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
| file://:0:0:0:0 | __ptr32 | Other |
|
||||
| file://:0:0:0:0 | __ptr64 | Other |
|
||||
| file://:0:0:0:0 | __sptr | Other |
|
||||
| file://:0:0:0:0 | __super | Other |
|
||||
| file://:0:0:0:0 | __uptr | Other |
|
||||
| file://:0:0:0:0 | __va_list_tag | Other |
|
||||
| file://:0:0:0:0 | abstract | Other |
|
||||
|
||||
@@ -3,5 +3,6 @@ import cpp
|
||||
from Element e, string s
|
||||
where
|
||||
not e instanceof Folder and
|
||||
exists(e.toString()) and // Work around `VariableDeclarationEntry.toString()` not holding
|
||||
if e instanceof VariableAccess then s = "Variable access" else s = "Other"
|
||||
select e, s
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
| tst.c:8:1:8:18 | // lgtm: blah blah | lgtm: blah blah | lgtm | tst.c:8:1:8:18 | // lgtm: blah blah |
|
||||
| tst.c:9:1:9:32 | // lgtm blah blah #falsepositive | lgtm blah blah #falsepositive | lgtm | tst.c:9:1:9:32 | // lgtm blah blah #falsepositive |
|
||||
| tst.c:10:1:10:39 | //lgtm [js/invocation-of-non-function] | lgtm [js/invocation-of-non-function] | lgtm [js/invocation-of-non-function] | tst.c:10:1:10:39 | //lgtm [js/invocation-of-non-function] |
|
||||
| tst.c:11:1:11:10 | /* lgtm */ | lgtm | lgtm | tst.c:11:1:11:10 | /* lgtm */ |
|
||||
| tst.c:12:1:12:9 | // lgtm[] | lgtm[] | lgtm[] | tst.c:12:1:12:9 | // lgtm[] |
|
||||
| tst.c:14:1:14:6 | //lgtm | lgtm | lgtm | tst.c:14:1:14:6 | //lgtm |
|
||||
| tst.c:15:1:15:7 | //\tlgtm | \tlgtm | lgtm | tst.c:15:1:15:7 | //\tlgtm |
|
||||
@@ -22,6 +23,10 @@
|
||||
| tst.c:27:1:27:70 | // lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/invocation-of-non-function] | tst.c:27:1:27:70 | // lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] |
|
||||
| tst.c:28:1:28:36 | // lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement]; lgtm | lgtm | tst.c:28:1:28:36 | // lgtm[js/debugger-statement]; lgtm |
|
||||
| tst.c:28:1:28:36 | // lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement] | tst.c:28:1:28:36 | // lgtm[js/debugger-statement]; lgtm |
|
||||
| tst.c:29:1:29:12 | /* lgtm[] */ | lgtm[] | lgtm[] | tst.c:29:1:29:12 | /* lgtm[] */ |
|
||||
| tst.c:30:1:30:41 | /* lgtm[js/invocation-of-non-function] */ | lgtm[js/invocation-of-non-function] | lgtm[js/invocation-of-non-function] | tst.c:30:1:30:41 | /* lgtm[js/invocation-of-non-function] */ |
|
||||
| tst.c:36:1:36:55 | /* lgtm[@tag:nullness,js/invocation-of-non-function] */ | lgtm[@tag:nullness,js/invocation-of-non-function] | lgtm[@tag:nullness,js/invocation-of-non-function] | tst.c:36:1:36:55 | /* lgtm[@tag:nullness,js/invocation-of-non-function] */ |
|
||||
| tst.c:37:1:37:25 | /* lgtm[@tag:nullness] */ | lgtm[@tag:nullness] | lgtm[@tag:nullness] | tst.c:37:1:37:25 | /* lgtm[@tag:nullness] */ |
|
||||
| tstWindows.c:1:12:1:18 | // lgtm | lgtm | lgtm | tstWindows.c:1:1:1:18 | // lgtm |
|
||||
| tstWindows.c:2:1:2:30 | // lgtm[js/debugger-statement] | lgtm[js/debugger-statement] | lgtm[js/debugger-statement] | tstWindows.c:2:1:2:30 | // lgtm[js/debugger-statement] |
|
||||
| tstWindows.c:3:1:3:61 | // lgtm[js/debugger-statement, js/invocation-of-non-function] | lgtm[js/debugger-statement, js/invocation-of-non-function] | lgtm[js/debugger-statement, js/invocation-of-non-function] | tstWindows.c:3:1:3:61 | // lgtm[js/debugger-statement, js/invocation-of-non-function] |
|
||||
@@ -32,6 +37,7 @@
|
||||
| tstWindows.c:8:1:8:18 | // lgtm: blah blah | lgtm: blah blah | lgtm | tstWindows.c:8:1:8:18 | // lgtm: blah blah |
|
||||
| tstWindows.c:9:1:9:32 | // lgtm blah blah #falsepositive | lgtm blah blah #falsepositive | lgtm | tstWindows.c:9:1:9:32 | // lgtm blah blah #falsepositive |
|
||||
| tstWindows.c:10:1:10:39 | //lgtm [js/invocation-of-non-function] | lgtm [js/invocation-of-non-function] | lgtm [js/invocation-of-non-function] | tstWindows.c:10:1:10:39 | //lgtm [js/invocation-of-non-function] |
|
||||
| tstWindows.c:11:1:11:10 | /* lgtm */ | lgtm | lgtm | tstWindows.c:11:1:11:10 | /* lgtm */ |
|
||||
| tstWindows.c:12:1:12:9 | // lgtm[] | lgtm[] | lgtm[] | tstWindows.c:12:1:12:9 | // lgtm[] |
|
||||
| tstWindows.c:14:1:14:6 | //lgtm | lgtm | lgtm | tstWindows.c:14:1:14:6 | //lgtm |
|
||||
| tstWindows.c:15:1:15:7 | //\tlgtm | \tlgtm | lgtm | tstWindows.c:15:1:15:7 | //\tlgtm |
|
||||
@@ -46,3 +52,7 @@
|
||||
| tstWindows.c:27:1:27:70 | // lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/invocation-of-non-function] | tstWindows.c:27:1:27:70 | // lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] |
|
||||
| tstWindows.c:28:1:28:36 | // lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement]; lgtm | lgtm | tstWindows.c:28:1:28:36 | // lgtm[js/debugger-statement]; lgtm |
|
||||
| tstWindows.c:28:1:28:36 | // lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement] | tstWindows.c:28:1:28:36 | // lgtm[js/debugger-statement]; lgtm |
|
||||
| tstWindows.c:29:1:29:12 | /* lgtm[] */ | lgtm[] | lgtm[] | tstWindows.c:29:1:29:12 | /* lgtm[] */ |
|
||||
| tstWindows.c:30:1:30:41 | /* lgtm[js/invocation-of-non-function] */ | lgtm[js/invocation-of-non-function] | lgtm[js/invocation-of-non-function] | tstWindows.c:30:1:30:41 | /* lgtm[js/invocation-of-non-function] */ |
|
||||
| tstWindows.c:36:1:36:55 | /* lgtm[@tag:nullness,js/invocation-of-non-function] */ | lgtm[@tag:nullness,js/invocation-of-non-function] | lgtm[@tag:nullness,js/invocation-of-non-function] | tstWindows.c:36:1:36:55 | /* lgtm[@tag:nullness,js/invocation-of-non-function] */ |
|
||||
| tstWindows.c:37:1:37:25 | /* lgtm[@tag:nullness] */ | lgtm[@tag:nullness] | lgtm[@tag:nullness] | tstWindows.c:37:1:37:25 | /* lgtm[@tag:nullness] */ |
|
||||
|
||||
@@ -26,3 +26,12 @@ int x = 0; // lgtm
|
||||
// LGTM[js/debugger-statement]
|
||||
// lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function]
|
||||
// lgtm[js/debugger-statement]; lgtm
|
||||
/* lgtm[] */
|
||||
/* lgtm[js/invocation-of-non-function] */
|
||||
/* lgtm
|
||||
*/
|
||||
/* lgtm
|
||||
|
||||
*/
|
||||
/* lgtm[@tag:nullness,js/invocation-of-non-function] */
|
||||
/* lgtm[@tag:nullness] */
|
||||
@@ -26,3 +26,12 @@ int x = 0; // lgtm
|
||||
// LGTM[js/debugger-statement]
|
||||
// lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function]
|
||||
// lgtm[js/debugger-statement]; lgtm
|
||||
/* lgtm[] */
|
||||
/* lgtm[js/invocation-of-non-function] */
|
||||
/* lgtm
|
||||
*/
|
||||
/* lgtm
|
||||
|
||||
*/
|
||||
/* lgtm[@tag:nullness,js/invocation-of-non-function] */
|
||||
/* lgtm[@tag:nullness] */
|
||||
Reference in New Issue
Block a user