Merge branch 'master' into hresult-boolean-qhelp

This commit is contained in:
Jonas Jensen
2018-10-09 14:56:58 +02:00
committed by GitHub
235 changed files with 9642 additions and 1188 deletions

View File

@@ -119,7 +119,7 @@ class CommentBlock extends Comment {
*/
predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
this.lastComment().getLocation().hasLocationInfo(filepath, _, _, endline, endcolumn)
this.lastComment().getLocation().hasLocationInfo(_, _, _, endline, endcolumn)
}
}

View File

@@ -22,13 +22,15 @@ import UnsignedGEZero
// #define PRINTMSG(val,msg) { if (val >= PRINTLEVEL) printf(msg); }
//
// So to reduce the number of false positives, we do not report a result if
// the comparison is in a macro expansion.
// the comparison is in a macro expansion. Similarly for template
// instantiations.
from
ComparisonOperation cmp, SmallSide ss,
float left, float right, boolean value,
string reason
where
not cmp.isInMacroExpansion() and
not cmp.isFromTemplateInstantiation(_) and
reachablePointlessComparison(cmp, left, right, value, ss) and
// a comparison between an enum and zero is always valid because whether

View File

@@ -25,7 +25,7 @@ predicate stringType(Type t, Type charType) {
charType = t.(ArrayType).getBaseType()
) and (
charType.getUnspecifiedType() instanceof CharType or
charType.getUnspecifiedType() instanceof WideCharType
charType.getUnspecifiedType() instanceof Wchar_t
)
)
or

View File

@@ -25,7 +25,8 @@ private predicate formattingFunctionCallExpectedType(FormattingFunctionCall ffc,
ffc.getTarget() = f and
f.getFormatParameterIndex() = i and
ffc.getArgument(i) = fl and
fl.getConversionType(pos) = expected
fl.getConversionType(pos) = expected and
count(fl.getConversionType(pos)) = 1
)
}
@@ -66,30 +67,15 @@ predicate formatOtherArgType(FormattingFunctionCall ffc, int pos, Type expected,
class ExpectedType extends Type
{
ExpectedType() {
formatArgType(_, _, this, _, _) or
formatOtherArgType(_, _, this, _, _) or
exists(ExpectedType t |
this = t.(PointerType).getBaseType()
exists(Type t |
(
formatArgType(_, _, t, _, _) or
formatOtherArgType(_, _, t, _, _)
) and this = t.getUnspecifiedType()
)
}
}
/**
* Gets an 'interesting' type that can be reached from `t` by removing
* typedefs and specifiers. Note that this does not always mean removing
* all typedefs and specifiers as `Type.getUnspecifiedType()` would, for
* example if the interesting type is itself a typedef.
*/
ExpectedType getAnUnderlyingExpectedType(Type t) {
(
result = t
) or (
result = getAnUnderlyingExpectedType(t.(TypedefType).getBaseType())
) or (
result = getAnUnderlyingExpectedType(t.(SpecifiedType).getBaseType())
)
}
/**
* Holds if it is safe to display a value of type `actual` when `printf`
* expects a value of type `expected`.
@@ -100,59 +86,48 @@ ExpectedType getAnUnderlyingExpectedType(Type t) {
* are converted to `double`.
*/
predicate trivialConversion(ExpectedType expected, Type actual) {
formatArgType(_, _, expected, _, actual) and
exists(Type actualU |
actualU = actual.getUnspecifiedType() and
exists(Type exp, Type act |
formatArgType(_, _, exp, _, act) and
expected = exp.getUnspecifiedType() and
actual = act.getUnspecifiedType()
) and (
(
(
// allow a pointer type to be displayed with `%p`
expected instanceof VoidPointerType and actualU instanceof PointerType
) or (
// allow a function pointer type to be displayed with `%p`
expected instanceof VoidPointerType and actualU instanceof FunctionPointerType and expected.getSize() = actual.getSize()
) or (
// allow an `enum` type to be displayed with `%i`, `%c` etc
expected instanceof IntegralType and actualU instanceof Enum
) or (
// allow any `char *` type to be displayed with `%s`
expected instanceof CharPointerType and actualU instanceof CharPointerType
) or (
// allow `wchar_t *`, or any pointer to an integral type of the same size, to be displayed
// with `%ws`
expected.(PointerType).getBaseType().hasName("wchar_t") and
exists(Wchar_t t |
actual.getUnspecifiedType().(PointerType).getBaseType().(IntegralType).getSize() = t.getSize()
)
) or (
// allow an `int` (or anything promoted to `int`) to be displayed with `%c`
expected instanceof CharType and actualU instanceof IntType
) or (
// allow an `int` (or anything promoted to `int`) to be displayed with `%wc`
expected instanceof Wchar_t and actualU instanceof IntType
) or (
expected instanceof UnsignedCharType and actualU instanceof IntType
) or (
// allow the underlying type of a `size_t` (e.g. `unsigned long`) for
// `%zu`, since this is the type of a `sizeof` expression
expected instanceof Size_t and
actual.getUnspecifiedType() = expected.getUnspecifiedType()
) or (
// allow the underlying type of a `ssize_t` (e.g. `long`) for `%zd`
expected instanceof Ssize_t and
actual.getUnspecifiedType() = expected.getUnspecifiedType()
) or (
// allow any integral type of the same size
// (this permits signedness changes)
expected.(IntegralType).getSize() = actualU.(IntegralType).getSize()
) or (
// allow a pointer to any integral type of the same size
// (this permits signedness changes)
expected.(PointerType).getBaseType().(IntegralType).getSize() = actualU.(PointerType).getBaseType().(IntegralType).getSize()
) or (
// allow expected, or a typedef or specified version of expected
expected = getAnUnderlyingExpectedType(actual)
// allow a pointer type to be displayed with `%p`
expected instanceof VoidPointerType and actual instanceof PointerType
) or (
// allow a function pointer type to be displayed with `%p`
expected instanceof VoidPointerType and actual instanceof FunctionPointerType and expected.getSize() = actual.getSize()
) or (
// allow an `enum` type to be displayed with `%i`, `%c` etc
expected instanceof IntegralType and actual instanceof Enum
) or (
// allow any `char *` type to be displayed with `%s`
expected instanceof CharPointerType and actual instanceof CharPointerType
) or (
// allow `wchar_t *`, or any pointer to an integral type of the same size, to be displayed
// with `%ws`
expected.(PointerType).getBaseType().hasName("wchar_t") and
exists(Wchar_t t |
actual.getUnspecifiedType().(PointerType).getBaseType().(IntegralType).getSize() = t.getSize()
)
) or (
// allow an `int` (or anything promoted to `int`) to be displayed with `%c`
expected instanceof CharType and actual instanceof IntType
) or (
// allow an `int` (or anything promoted to `int`) to be displayed with `%wc`
expected instanceof Wchar_t and actual instanceof IntType
) or (
expected instanceof UnsignedCharType and actual instanceof IntType
) or (
// allow any integral type of the same size
// (this permits signedness changes)
expected.(IntegralType).getSize() = actual.(IntegralType).getSize()
) or (
// allow a pointer to any integral type of the same size
// (this permits signedness changes)
expected.(PointerType).getBaseType().(IntegralType).getSize() = actual.(PointerType).getBaseType().(IntegralType).getSize()
) or (
expected = actual
)
)
}
@@ -164,16 +139,16 @@ int sizeof_IntType() {
exists(IntType it | result = it.getSize())
}
from FormattingFunctionCall ffc, int n, Expr arg, ExpectedType expected, Type actual
from FormattingFunctionCall ffc, int n, Expr arg, Type expected, Type actual
where (
(
formatArgType(ffc, n, expected, arg, actual) and
not trivialConversion(expected, actual)
not trivialConversion(expected.getUnspecifiedType(), actual.getUnspecifiedType())
)
or
(
formatOtherArgType(ffc, n, expected, arg, actual) and
not actual.getUnderlyingType().(IntegralType).getSize() = sizeof_IntType()
not actual.getUnspecifiedType().(IntegralType).getSize() = sizeof_IntType()
)
)
and not arg.isAffectedByMacro()

View File

@@ -41,11 +41,13 @@ Type stripType(Type t) {
result = stripType(t.(ArrayType).getBaseType()) or
result = stripType(t.(ReferenceType).getBaseType()) or
result = stripType(t.(SpecifiedType).getBaseType()) or
result = stripType(t.(Decltype).getBaseType()) or
(
not t instanceof TypedefType and
not t instanceof ArrayType and
not t instanceof ReferenceType and
not t instanceof SpecifiedType and
not t instanceof Decltype and
result = t
)
}

View File

@@ -11,10 +11,21 @@
import cpp
from Initializer init, Variable v, VariableAccess va
where init.getDeclaration() = v
and va.getTarget() = v
and va.getParent*() = init
class VariableAccessInInitializer extends VariableAccess {
Variable var;
Initializer init;
VariableAccessInInitializer() {
init.getDeclaration() = var and
init.getExpr().getAChild*() = this
}
predicate initializesItself(Variable v, Initializer i) {
v = var and i = init and var = this.getTarget()
}
}
from Initializer init, Variable v, VariableAccessInInitializer va
where va.initializesItself(v, init)
and (
va.hasLValueToRValueConversion() or
exists (Assignment assn | assn.getLValue() = va) or

View File

@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Semmle C/C++ Default Queries
Bundle-SymbolicName: com.semmle.plugin.semmlecode.cpp.queries;singleton:=true
Bundle-Version: 1.18.0.qualifier
Bundle-Version: 1.18.1.qualifier
Bundle-Vendor: Semmle Ltd.
Bundle-ActivationPolicy: lazy
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.0.qualifier,1.18.0.qualifier]"
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.1.qualifier,1.18.1.qualifier]"

View File

@@ -19,7 +19,7 @@ import cpp
class AnyCharPointerType extends PointerType {
AnyCharPointerType() {
this.getBaseType().getUnderlyingType() instanceof CharType or
this.getBaseType().getUnderlyingType() instanceof WideCharType
this.getBaseType().getUnderlyingType() instanceof Wchar_t
}
}
@@ -29,7 +29,7 @@ class AnyCharPointerType extends PointerType {
class AnyCharArrayType extends ArrayType {
AnyCharArrayType() {
this.getBaseType().getUnderlyingType() instanceof CharType or
this.getBaseType().getUnderlyingType() instanceof WideCharType
this.getBaseType().getUnderlyingType() instanceof Wchar_t
}
}

View File

@@ -0,0 +1,3 @@
wchar_t* pSrc;
pSrc = (wchar_t*)"a"; // casting a byte-string literal "a" to a wide-character string

View File

@@ -0,0 +1,35 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>This rule indicates a potentially incorrect cast from an byte string (<code>char *</code>) to a wide-character string (<code>wchar_t *</code>).</p>
<p>This cast might yield strings that are not correctly terminated; including potential buffer overruns when using such strings with some dangerous APIs.</p>
</overview>
<recommendation>
<p>Do not explicitly cast byte strings to wide-character strings.</p>
<p>For string literals, prepend the literal string with the letter "L" to indicate that the string is a wide-character string (<code>wchar_t *</code>).</p>
<p>For converting a byte literal to a wide-character string literal, you would need to use the appropriate conversion function for the platform you are using. Please see the references section for options according to your platform.</p>
</recommendation>
<example>
<p>In the following example, an byte string literal (<code>"a"</code>) is cast to a wide-character string.</p>
<sample src="WcharCharConversion.cpp" />
<p>To fix this issue, prepend the literal with the letter "L" (<code>L"a"</code>) to define it as a wide-character string.</p>
</example>
<references>
<li>
General resources:
<a href="https://en.cppreference.com/w/cpp/string/multibyte/mbstowcs">std::mbstowcs</a>
</li>
<li>
Microsoft specific resources:
<a href="https://docs.microsoft.com/en-us/windows/desktop/Intl/security-considerations--international-features">Security Considerations: International Features</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,29 @@
/**
* @name Cast from char* to wchar_t*
* @description Casting a byte string to a wide-character string is likely
* to yield a string that is incorrectly terminated or aligned.
* This can lead to undefined behavior, including buffer overruns.
* @kind problem
* @id cpp/incorrect-string-type-conversion
* @problem.severity error
* @precision high
* @tags security
* external/cwe/cwe-704
* external/microsoft/c/c6276
*/
import cpp
class WideCharPointerType extends PointerType {
WideCharPointerType() {
this.getBaseType() instanceof WideCharType
}
}
from Expr e1, Cast e2
where
e2 = e1.getConversion() and
exists(WideCharPointerType w, CharPointerType c |
w = e2.getType().getUnspecifiedType().(PointerType) and
c = e1.getType().getUnspecifiedType().(PointerType)
)
select e1, "Conversion from " + e1.getType().toString() + " to " + e2.getType().toString() + ". Use of invalid string can lead to undefined behavior."

View File

@@ -3,7 +3,7 @@
* @description All functions that are not void should return a value on every exit path.
* @kind problem
* @problem.severity error
* @precision medium
* @precision high
* @id cpp/missing-return
* @tags reliability
* readability

View File

@@ -2,41 +2,38 @@ import semmle.code.cpp.Location
private import semmle.code.cpp.Enclosing
private import semmle.code.cpp.internal.ResolveClass
/**
* Get the `@element` that represents this `@element`.
* Normally this will simply be `e`, but sometimes it is not.
* For example, for an incomplete struct `e` the result may be a
* complete struct with the same name.
*/
private cached @element resolveElement(@element e) {
if isClass(e)
then result = resolveClass(e)
else result = e
}
/**
* Get the `Element` that represents this `@element`.
* Normally this will simply be a cast of `e`, but sometimes it is not.
* For example, for an incomplete struct `e` the result may be a
* complete struct with the same name.
*/
pragma[inline]
Element mkElement(@element e) {
result = resolveElement(e)
unresolveElement(result) = e
}
/**
* Get an `@element` that resolves to the `Element`. This should
* INTERNAL: Do not use.
*
* Gets an `@element` that resolves to the `Element`. This should
* normally only be called from member predicates, where `e` is not
* `this` and you need the result for an argument to a database
* extensional.
* See `underlyingElement` for when `e` is `this`.
*/
pragma[inline]
@element unresolveElement(Element e) {
resolveElement(result) = e
not result instanceof @usertype and
result = e
or
e = resolveClass(result)
}
/**
* Get the `@element` that this `Element` extends. This should normally
* INTERNAL: Do not use.
*
* Gets the `@element` that this `Element` extends. This should normally
* only be called from member predicates, where `e` is `this` and you
* need the result for an argument to a database extensional.
* See `unresolveElement` for when `e` is not `this`.
@@ -53,10 +50,6 @@ Element mkElement(@element e) {
* `getLocation`, or `hasLocationInfo`.
*/
class ElementBase extends @element {
ElementBase() {
this = resolveElement(_)
}
/** Gets a textual representation of this element. */
string toString() { none() }
}

View File

@@ -294,13 +294,13 @@ class AttributeArgument extends Element, @attribute_arg {
}
override string toString() {
if exists (@attribute_arg_empty self | mkElement(self) = this)
if exists (@attribute_arg_empty self | self = underlyingElement(this))
then result = "empty argument"
else exists (string prefix, string tail
| (if exists(getName())
then prefix = getName() + "="
else prefix = "") and
(if exists (@attribute_arg_type self | mkElement(self) = this)
(if exists (@attribute_arg_type self | self = underlyingElement(this))
then tail = getValueType().getName()
else tail = getValueText()) and
result = prefix + tail)

View File

@@ -7,6 +7,8 @@ private import semmle.code.cpp.internal.ResolveClass
* A C/C++ type.
*/
class Type extends Locatable, @type {
Type() { isType(underlyingElement(this)) }
/**
* Gets the name of this type.
*/
@@ -599,6 +601,10 @@ class VoidType extends BuiltInType {
/**
* The C/C++ wide character type.
*
* Note that on some platforms `wchar_t` doesn't exist as a built-in
* type but a typedef is provided. Consider using the `Wchar_t` QL
* class to include these types.
*/
class WideCharType extends IntegralType {

View File

@@ -1,16 +1,16 @@
/**
* A library for working with XML files and their content.
* Provides classes and predicates for working with XML files and their content.
*/
import semmle.code.cpp.Location
/** An XML element that has a location. */
abstract class XMLLocatable extends @xmllocatable {
/** The source location for this element. */
/** Gets the source location for this element. */
Location getLocation() { xmllocations(this,result) }
/**
* Whether this element has the specified location information,
* Holds if this element has the specified location information,
* including file path, start line, start column, end line and end column.
*/
predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
@@ -20,7 +20,7 @@ abstract class XMLLocatable extends @xmllocatable {
)
}
/** A printable representation of this element. */
/** Gets a printable representation of this element. */
abstract string toString();
}
@@ -30,46 +30,49 @@ abstract class XMLLocatable extends @xmllocatable {
*/
class XMLParent extends @xmlparent {
/**
* A printable representation of this XML parent.
* Gets a printable representation of this XML parent.
* (Intended to be overridden in subclasses.)
*/
abstract string getName();
/** The file to which this XML parent belongs. */
/** Gets the file to which this XML parent belongs. */
XMLFile getFile() { result = this or xmlElements(this,_,_,_,result) }
/** The child element at a specified index of this XML parent. */
/** Gets the child element at a specified index of this XML parent. */
XMLElement getChild(int index) { xmlElements(result, _, this, index, _) }
/** A child element of this XML parent. */
/** Gets a child element of this XML parent. */
XMLElement getAChild() { xmlElements(result,_,this,_,_) }
/** A child element of this XML parent with the given `name`. */
/** Gets a child element of this XML parent with the given `name`. */
XMLElement getAChild(string name) { xmlElements(result,_,this,_,_) and result.hasName(name) }
/** A comment that is a child of this XML parent. */
/** Gets a comment that is a child of this XML parent. */
XMLComment getAComment() { xmlComments(result,_,this,_) }
/** A character sequence that is a child of this XML parent. */
/** Gets a character sequence that is a child of this XML parent. */
XMLCharacters getACharactersSet() { xmlChars(result,_,this,_,_,_) }
/** The depth in the tree. (Overridden in XMLElement.) */
/** Gets the depth in the tree. (Overridden in XMLElement.) */
int getDepth() { result = 0 }
/** The number of child XML elements of this XML parent. */
/** Gets the number of child XML elements of this XML parent. */
int getNumberOfChildren() {
result = count(XMLElement e | xmlElements(e,_,this,_,_))
}
/** The number of places in the body of this XML parent where text occurs. */
/** Gets the number of places in the body of this XML parent where text occurs. */
int getNumberOfCharacterSets() {
result = count(int pos | xmlChars(_,_,this,pos,_,_))
}
/**
* DEPRECATED: Internal.
*
* Append the character sequences of this XML parent from left to right, separated by a space,
* up to a specified (zero-based) index.
*/
deprecated
string charsSetUpTo(int n) {
(n = 0 and xmlChars(_,result,this,0,_,_)) or
(n > 0 and exists(string chars | xmlChars(_,chars,this,n,_,_) |
@@ -78,18 +81,15 @@ class XMLParent extends @xmlparent {
/** Append all the character sequences of this XML parent from left to right, separated by a space. */
string allCharactersString() {
exists(int n | n = this.getNumberOfCharacterSets() |
(n = 0 and result = "") or
(n > 0 and result = this.charsSetUpTo(n-1))
)
result = concat(string chars, int pos | xmlChars(_, chars, this, pos, _, _) | chars, " " order by pos)
}
/** The text value contained in this XML parent. */
/** Gets the text value contained in this XML parent. */
string getTextValue() {
result = allCharactersString()
}
/** A printable representation of this XML parent. */
/** Gets a printable representation of this XML parent. */
string toString() { result = this.getName() }
}
@@ -99,54 +99,54 @@ class XMLFile extends XMLParent, File {
xmlEncoding(this,_)
}
/** A printable representation of this XML file. */
/** Gets a printable representation of this XML file. */
override
string toString() { result = XMLParent.super.toString() }
/** The name of this XML file. */
/** Gets the name of this XML file. */
override
string getName() { files(this,result,_,_,_) }
/** The path of this XML file. */
/** Gets the path of this XML file. */
string getPath() { files(this,_,result,_,_) }
/** The path of the folder that contains this XML file. */
/** Gets the path of the folder that contains this XML file. */
string getFolder() {
result = this.getPath().substring(0, this.getPath().length()-this.getName().length())
}
/** The encoding of this XML file. */
/** Gets the encoding of this XML file. */
string getEncoding() { xmlEncoding(this,result) }
/** The XML file itself. */
/** Gets the XML file itself. */
override
XMLFile getFile() { result = this }
/** A top-most element in an XML file. */
/** Gets a top-most element in an XML file. */
XMLElement getARootElement() { result = this.getAChild() }
/** A DTD associated with this XML file. */
/** Gets a DTD associated with this XML file. */
XMLDTD getADTD() { xmlDTDs(result,_,_,_,this) }
}
/** A "Document Type Definition" of an XML file. */
class XMLDTD extends @xmldtd {
/** The name of the root element of this DTD. */
/** Gets the name of the root element of this DTD. */
string getRoot() { xmlDTDs(this,result,_,_,_) }
/** The public ID of this DTD. */
/** Gets the public ID of this DTD. */
string getPublicId() { xmlDTDs(this,_,result,_,_) }
/** The system ID of this DTD. */
/** Gets the system ID of this DTD. */
string getSystemId() { xmlDTDs(this,_,_,result,_) }
/** Whether this DTD is public. */
/** Holds if this DTD is public. */
predicate isPublic() { not xmlDTDs(this,_,"",_,_) }
/** The parent of this DTD. */
/** Gets the parent of this DTD. */
XMLParent getParent() { xmlDTDs(this,_,_,_,result) }
/** A printable representation of this DTD. */
/** Gets a printable representation of this DTD. */
string toString() {
(this.isPublic() and result = this.getRoot() + " PUBLIC '" +
this.getPublicId() + "' '" +
@@ -159,92 +159,92 @@ class XMLDTD extends @xmldtd {
/** An XML tag in an XML file. */
class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
/** Whether this XML element has the given `name`. */
/** Holds if this XML element has the given `name`. */
predicate hasName(string name) { name = getName() }
/** The name of this XML element. */
/** Gets the name of this XML element. */
override
string getName() { xmlElements(this,result,_,_,_) }
/** The XML file in which this XML element occurs. */
/** Gets the XML file in which this XML element occurs. */
override
XMLFile getFile() { xmlElements(this,_,_,_,result) }
/** The parent of this XML element. */
/** Gets the parent of this XML element. */
XMLParent getParent() { xmlElements(this,_,result,_,_) }
/** The index of this XML element among its parent's children. */
/** Gets the index of this XML element among its parent's children. */
int getIndex() { xmlElements(this, _, _, result, _) }
/** Whether this XML element has a namespace. */
/** Holds if this XML element has a namespace. */
predicate hasNamespace() { xmlHasNs(this,_,_) }
/** The namespace of this XML element, if any. */
/** Gets the namespace of this XML element, if any. */
XMLNamespace getNamespace() { xmlHasNs(this,result,_) }
/** The index of this XML element among its parent's children. */
/** Gets the index of this XML element among its parent's children. */
int getElementPositionIndex() { xmlElements(this,_,_,result,_) }
/** The depth of this element within the XML file tree structure. */
/** Gets the depth of this element within the XML file tree structure. */
override
int getDepth() { result = this.getParent().getDepth() + 1 }
/** An XML attribute of this XML element. */
/** Gets an XML attribute of this XML element. */
XMLAttribute getAnAttribute() { result.getElement() = this }
/** The attribute with the specified `name`, if any. */
/** Gets the attribute with the specified `name`, if any. */
XMLAttribute getAttribute(string name) {
result.getElement() = this and result.getName() = name
}
/** Whether this XML element has an attribute with the specified `name`. */
/** Holds if this XML element has an attribute with the specified `name`. */
predicate hasAttribute(string name) {
exists(XMLAttribute a| a = this.getAttribute(name))
}
/** The value of the attribute with the specified `name`, if any. */
/** Gets the value of the attribute with the specified `name`, if any. */
string getAttributeValue(string name) {
result = this.getAttribute(name).getValue()
}
/** A printable representation of this XML element. */
/** Gets a printable representation of this XML element. */
override
string toString() { result = XMLParent.super.toString() }
}
/** An attribute that occurs inside an XML element. */
class XMLAttribute extends @xmlattribute, XMLLocatable {
/** The name of this attribute. */
/** Gets the name of this attribute. */
string getName() { xmlAttrs(this,_,result,_,_,_) }
/** The XML element to which this attribute belongs. */
/** Gets the XML element to which this attribute belongs. */
XMLElement getElement() { xmlAttrs(this,result,_,_,_,_) }
/** Whether this attribute has a namespace. */
/** Holds if this attribute has a namespace. */
predicate hasNamespace() { xmlHasNs(this,_,_) }
/** The namespace of this attribute, if any. */
/** Gets the namespace of this attribute, if any. */
XMLNamespace getNamespace() { xmlHasNs(this,result,_) }
/** The value of this attribute. */
/** Gets the value of this attribute. */
string getValue() { xmlAttrs(this,_,_,result,_,_) }
/** A printable representation of this XML attribute. */
/** Gets a printable representation of this XML attribute. */
override string toString() { result = this.getName() + "=" + this.getValue() }
}
/** A namespace used in an XML file */
class XMLNamespace extends @xmlnamespace {
/** The prefix of this namespace. */
/** Gets the prefix of this namespace. */
string getPrefix() { xmlNs(this,result,_,_) }
/** The URI of this namespace. */
/** Gets the URI of this namespace. */
string getURI() { xmlNs(this,_,result,_) }
/** Whether this namespace has no prefix. */
/** Holds if this namespace has no prefix. */
predicate isDefault() { this.getPrefix() = "" }
/** A printable representation of this XML namespace. */
/** Gets a printable representation of this XML namespace. */
string toString() {
(this.isDefault() and result = this.getURI()) or
(not this.isDefault() and result = this.getPrefix() + ":" + this.getURI())
@@ -253,13 +253,13 @@ class XMLNamespace extends @xmlnamespace {
/** A comment of the form `<!-- ... -->` is an XML comment. */
class XMLComment extends @xmlcomment, XMLLocatable {
/** The text content of this XML comment. */
/** Gets the text content of this XML comment. */
string getText() { xmlComments(this,result,_,_) }
/** The parent of this XML comment. */
/** Gets the parent of this XML comment. */
XMLParent getParent() { xmlComments(this,_,result,_) }
/** A printable representation of this XML comment. */
/** Gets a printable representation of this XML comment. */
override string toString() { result = this.getText() }
}
@@ -268,15 +268,15 @@ class XMLComment extends @xmlcomment, XMLLocatable {
* closing tags of an XML element, excluding other elements.
*/
class XMLCharacters extends @xmlcharacters, XMLLocatable {
/** The content of this character sequence. */
/** Gets the content of this character sequence. */
string getCharacters() { xmlChars(this,result,_,_,_,_) }
/** The parent of this character sequence. */
/** Gets the parent of this character sequence. */
XMLParent getParent() { xmlChars(this,_,result,_,_,_) }
/** Whether this character sequence is CDATA. */
/** Holds if this character sequence is CDATA. */
predicate isCDATA() { xmlChars(this,_,_,_,1,_) }
/** A printable representation of this XML character sequence. */
/** Gets a printable representation of this XML character sequence. */
override string toString() { result = this.getCharacters() }
}

View File

@@ -1,7 +1,7 @@
import semmle.code.cpp.Type
/**
* The C/C++ char* type.
* The C/C++ `char*` type.
*/
class CharPointerType extends PointerType {
@@ -10,7 +10,7 @@ class CharPointerType extends PointerType {
}
/**
* The C/C++ int* type.
* The C/C++ `int*` type.
*/
class IntPointerType extends PointerType {
@@ -20,7 +20,7 @@ class IntPointerType extends PointerType {
/**
* The C/C++ void* type.
* The C/C++ `void*` type.
*/
class VoidPointerType extends PointerType {
@@ -29,7 +29,7 @@ class VoidPointerType extends PointerType {
}
/**
* The C/C++ size_t type.
* The C/C++ `size_t` type.
*/
class Size_t extends Type {
Size_t() {
@@ -39,7 +39,7 @@ class Size_t extends Type {
}
/**
* The C/C++ ssize_t type.
* The C/C++ `ssize_t` type.
*/
class Ssize_t extends Type {
Ssize_t() {
@@ -49,7 +49,7 @@ class Ssize_t extends Type {
}
/**
* The C/C++ ptrdiff_t type.
* The C/C++ `ptrdiff_t` type.
*/
class Ptrdiff_t extends Type {
Ptrdiff_t() {
@@ -59,7 +59,7 @@ class Ptrdiff_t extends Type {
}
/**
* The C/C++ intmax_t type.
* The C/C++ `intmax_t` type.
*/
class Intmax_t extends Type {
Intmax_t() {
@@ -69,7 +69,7 @@ class Intmax_t extends Type {
}
/**
* The C/C++ uintmax_t type.
* The C/C++ `uintmax_t` type.
*/
class Uintmax_t extends Type {
Uintmax_t() {
@@ -79,7 +79,11 @@ class Uintmax_t extends Type {
}
/**
* The C/C++ wchar_t type.
* The C/C++ `wchar_t` type.
*
* Note that on some platforms `wchar_t` doesn't exist as a built-in
* type but a typedef is provided. This QL class includes both cases
* (see also `WideCharType`).
*/
class Wchar_t extends Type {
Wchar_t() {

View File

@@ -220,6 +220,32 @@ class FormatLiteral extends Literal {
getUse().getTarget().(FormattingFunction).isWideCharDefault()
}
/**
* Gets the default character type expected for `%s` by this format literal. Typically
* `char` or `wchar_t`.
*/
Type getDefaultCharType() {
result = getUse().getTarget().(FormattingFunction).getDefaultCharType()
}
/**
* Gets the non-default character type expected for `%S` by this format literal. Typically
* `wchar_t` or `char`. On some snapshots there may be multiple results where we can't tell
* which is correct for a particular function.
*/
Type getNonDefaultCharType() {
result = getUse().getTarget().(FormattingFunction).getNonDefaultCharType()
}
/**
* Gets the wide character type for this format literal. This is usually `wchar_t`. On some
* snapshots there may be multiple results where we can't tell which is correct for a
* particular function.
*/
Type getWideCharType() {
result = getUse().getTarget().(FormattingFunction).getWideCharType()
}
/**
* Holds if this `FormatLiteral` is in a context that supports
* Microsoft rules and extensions.
@@ -629,7 +655,6 @@ class FormatLiteral extends Literal {
result = getConversionType2(n) or
result = getConversionType3(n) or
result = getConversionType4(n) or
result = getConversionType5(n) or
result = getConversionType6(n) or
result = getConversionType7(n) or
result = getConversionType8(n) or
@@ -696,33 +721,35 @@ class FormatLiteral extends Literal {
}
/**
* Gets the 'effective' string type character, that is, 's' (meaning a char string) or
* 'S' (meaning a wide string).
* - in the base case this is the same as the format type character.
* - for a `wprintf` or similar function call, the meanings are reversed.
* - the size prefixes 'l'/'w' (long) and 'h' (short) override the
* type character to effectively 'S' or 's' respectively.
* Gets the string type required by the nth conversion specifier.
* - in the base case this is the default for the formatting function
* (e.g. `char` for `printf`, `wchar_t` for `wprintf`).
* - the `%S` format character reverses wideness.
* - the size prefixes 'l'/'w' and 'h' override the type character
* to wide or single-byte characters respectively.
*/
private string getEffectiveStringConversionChar(int n) {
exists(string len, string conv | this.parseConvSpec(n, _, _, _, _, _, len, conv) and (conv = "s" or conv = "S") |
(len = "l" and result = "S") or
(len = "w" and result = "S") or
(len = "h" and result = "s") or
(len != "l" and len != "w" and len != "h" and (result = "s" or result = "S") and (if isWideCharDefault() then result != conv else result = conv))
)
}
private Type getConversionType4(int n) {
exists(string cnv, CharType t | cnv = this.getEffectiveStringConversionChar(n) |
cnv="s" and t = result.(PointerType).getBaseType()
and not t.isExplicitlySigned()
and not t.isExplicitlyUnsigned()
)
}
private Type getConversionType5(int n) {
exists(string cnv | cnv = this.getEffectiveStringConversionChar(n) |
cnv="S" and result.(PointerType).getBaseType().hasName("wchar_t")
exists(string len, string conv |
this.parseConvSpec(n, _, _, _, _, _, len, conv) and
(
(
(conv = "s" or conv = "S") and
len = "h" and
result.(PointerType).getBaseType() instanceof PlainCharType
) or (
(conv = "s" or conv = "S") and
(len = "l" or len = "w") and
result.(PointerType).getBaseType() = getWideCharType()
) or (
conv = "s" and
(len != "l" and len != "w" and len != "h") and
result.(PointerType).getBaseType() = getDefaultCharType()
) or (
conv = "S" and
(len != "l" and len != "w" and len != "h") and
result.(PointerType).getBaseType() = getNonDefaultCharType()
)
)
)
}

View File

@@ -0,0 +1,485 @@
import cpp
import semmle.code.cpp.ir.IR
/**
* A Boolean condition in the AST that guards one or more basic blocks. This includes
* operands of logical operators but not switch statements.
*/
class GuardCondition extends Expr {
GuardCondition() {
exists(IRGuardCondition ir | this = ir.getUnconvertedResultExpression())
or
// no binary operators in the IR
exists(GuardCondition gc |
this.(BinaryLogicalOperation).getAnOperand()= gc
)
or
// the IR short-circuits if(!x)
(
// don't produce a guard condition for `y = !x` and other non-short-circuited cases
not exists (Instruction inst | this.getFullyConverted() = inst.getAST()) and
exists(IRGuardCondition ir | this.(NotExpr).getOperand() = ir.getAST())
)
}
/**
* Holds if this condition controls `block`, meaning that `block` is only
* entered if the value of this condition is `testIsTrue`.
*
* Illustration:
*
* ```
* [ (testIsTrue) ]
* [ this ----------------succ ---- controlled ]
* [ | | ]
* [ (testIsFalse) | ------ ... ]
* [ other ]
* ```
*
* The predicate holds if all paths to `controlled` go via the `testIsTrue`
* edge of the control-flow graph. In other words, the `testIsTrue` edge
* must dominate `controlled`. This means that `controlled` must be
* dominated by both `this` and `succ` (the target of the `testIsTrue`
* edge). It also means that any other edge into `succ` must be a back-edge
* from a node which is dominated by `succ`.
*
* The short-circuit boolean operations have slightly surprising behavior
* here: because the operation itself only dominates one branch (due to
* being short-circuited) then it will only control blocks dominated by the
* true (for `&&`) or false (for `||`) branch.
*/
cached predicate controls(BasicBlock controlled, boolean testIsTrue) {
none()
}
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
cached predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
none()
}
/** Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`.
If `isLessThan = false` then this implies `left >= right + k`. */
cached predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
none()
}
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
cached predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
none()
}
/** Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`.
If `areEqual = false` then this implies `left != right + k`. */
cached predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
none()
}
}
/**
* A binary logical operator in the AST that guards one or more basic blocks.
*/
private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
GuardConditionFromBinaryLogicalOperator() {
exists(GuardCondition gc |
this.(BinaryLogicalOperation).getAnOperand()= gc
)
}
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
exists (BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs
| this = binop and
lhs = binop.getLeftOperand() and
rhs = binop.getRightOperand() and
lhs.controls(controlled, testIsTrue) and
rhs.controls(controlled, testIsTrue))
}
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
exists(boolean partIsTrue, GuardCondition part |
this.(BinaryLogicalOperation).impliesValue(part, partIsTrue, testIsTrue) |
part.comparesLt(left, right, k, isLessThan, partIsTrue)
)
}
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
exists(boolean testIsTrue |
comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
)
}
override predicate comparesEq(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
exists(boolean partIsTrue, GuardCondition part |
this.(BinaryLogicalOperation).impliesValue(part, partIsTrue, testIsTrue) |
part.comparesEq(left, right, k, isLessThan, partIsTrue)
)
}
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
exists(boolean testIsTrue |
comparesEq(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
)
}
}
/**
* A `!` operator in the AST that guards one or more basic blocks, and does not have a corresponding
* IR instruction.
*/
private class GuardConditionFromShortCircuitNot extends GuardCondition, NotExpr {
GuardConditionFromShortCircuitNot() {
not exists (Instruction inst | this.getFullyConverted() = inst.getAST()) and
exists(IRGuardCondition ir | getOperand() = ir.getAST())
}
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
getOperand().(GuardCondition).controls(controlled, testIsTrue.booleanNot())
}
override predicate comparesLt(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
getOperand().(GuardCondition).comparesLt(left, right, k, areEqual, testIsTrue.booleanNot())
}
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean testIsTrue) {
getOperand().(GuardCondition).ensuresLt(left, right, k, block, testIsTrue.booleanNot())
}
override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
getOperand().(GuardCondition).comparesEq(left, right, k, areEqual, testIsTrue.booleanNot())
}
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean testIsTrue) {
getOperand().(GuardCondition).ensuresEq(left, right, k, block, testIsTrue.booleanNot())
}
}
/**
* A Boolean condition in the AST that guards one or more basic blocks and has a corresponding IR
* instruction.
*/
private class GuardConditionFromIR extends GuardCondition {
IRGuardCondition ir;
GuardConditionFromIR() {
this = ir.getUnconvertedResultExpression()
}
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
/* This condition must determine the flow of control; that is, this
* node must be a top-level condition. */
this.controlsBlock(controlled, testIsTrue)
}
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
exists(Instruction li, Instruction ri |
li.getUnconvertedResultExpression() = left and
ri.getUnconvertedResultExpression() = right and
ir.comparesLt(li, ri, k, isLessThan, testIsTrue)
)
}
/** Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`.
If `isLessThan = false` then this implies `left >= right + k`. */
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
exists(Instruction li, Instruction ri, boolean testIsTrue |
li.getUnconvertedResultExpression() = left and
ri.getUnconvertedResultExpression() = right and
ir.comparesLt(li, ri, k, isLessThan, testIsTrue) and
this.controls(block, testIsTrue)
)
}
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
exists(Instruction li, Instruction ri |
li.getUnconvertedResultExpression() = left and
ri.getUnconvertedResultExpression() = right and
ir.comparesEq(li, ri, k, areEqual, testIsTrue)
)
}
/** Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`.
If `areEqual = false` then this implies `left != right + k`. */
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
exists(Instruction li, Instruction ri, boolean testIsTrue |
li.getUnconvertedResultExpression() = left and
ri.getUnconvertedResultExpression() = right and
ir.comparesEq(li, ri, k, areEqual, testIsTrue)
and this.controls(block, testIsTrue)
)
}
/**
* Holds if this condition controls `block`, meaning that `block` is only
* entered if the value of this condition is `testIsTrue`. This helper
* predicate does not necessarily hold for binary logical operations like
* `&&` and `||`. See the detailed explanation on predicate `controls`.
*/
private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) {
exists(IRBlock irb |
forex(IRGuardCondition inst | inst = ir | inst.controls(irb, testIsTrue)) and
irb.getAnInstruction().getAST().(ControlFlowNode).getBasicBlock() = controlled
)
}
}
/**
* A Boolean condition in the IR that guards one or more basic blocks. This includes
* operands of logical operators but not switch statements. Note that `&&` and `||`
* don't have an explicit representation in the IR, and therefore will not appear as
* IRGuardConditions.
*/
class IRGuardCondition extends Instruction {
IRGuardCondition() {
is_condition(this)
}
/**
* Holds if this condition controls `block`, meaning that `block` is only
* entered if the value of this condition is `testIsTrue`.
*
* Illustration:
*
* ```
* [ (testIsTrue) ]
* [ this ----------------succ ---- controlled ]
* [ | | ]
* [ (testIsFalse) | ------ ... ]
* [ other ]
* ```
*
* The predicate holds if all paths to `controlled` go via the `testIsTrue`
* edge of the control-flow graph. In other words, the `testIsTrue` edge
* must dominate `controlled`. This means that `controlled` must be
* dominated by both `this` and `succ` (the target of the `testIsTrue`
* edge). It also means that any other edge into `succ` must be a back-edge
* from a node which is dominated by `succ`.
*
* The short-circuit boolean operations have slightly surprising behavior
* here: because the operation itself only dominates one branch (due to
* being short-circuited) then it will only control blocks dominated by the
* true (for `&&`) or false (for `||`) branch.
*/
cached predicate controls(IRBlock controlled, boolean testIsTrue) {
/* This condition must determine the flow of control; that is, this
* node must be a top-level condition. */
this.controlsBlock(controlled, testIsTrue)
or
exists (IRGuardCondition ne
| this = ne.(LogicalNotInstruction).getOperand() and
ne.controls(controlled, testIsTrue.booleanNot()))
}
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
cached predicate comparesLt(Instruction left, Instruction right, int k, boolean isLessThan, boolean testIsTrue) {
compares_lt(this, left, right, k, isLessThan, testIsTrue)
}
/** Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`.
If `isLessThan = false` then this implies `left >= right + k`. */
cached predicate ensuresLt(Instruction left, Instruction right, int k, IRBlock block, boolean isLessThan) {
exists(boolean testIsTrue |
compares_lt(this, left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
)
}
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
cached predicate comparesEq(Instruction left, Instruction right, int k, boolean areEqual, boolean testIsTrue) {
compares_eq(this, left, right, k, areEqual, testIsTrue)
}
/** Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`.
If `areEqual = false` then this implies `left != right + k`. */
cached predicate ensuresEq(Instruction left, Instruction right, int k, IRBlock block, boolean areEqual) {
exists(boolean testIsTrue |
compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
)
}
/**
* Holds if this condition controls `block`, meaning that `block` is only
* entered if the value of this condition is `testIsTrue`. This helper
* predicate does not necessarily hold for binary logical operations like
* `&&` and `||`. See the detailed explanation on predicate `controls`.
*/
private predicate controlsBlock(IRBlock controlled, boolean testIsTrue) {
exists(IRBlock thisblock
| thisblock.getAnInstruction() = this
| exists(IRBlock succ, ConditionalBranchInstruction branch
| testIsTrue = true and succ.getFirstInstruction() = branch.getTrueSuccessor()
or
testIsTrue = false and succ.getFirstInstruction() = branch.getFalseSuccessor()
| branch.getCondition() = this and
succ.dominates(controlled) and
forall(IRBlock pred
| pred.getASuccessor() = succ
| pred = thisblock or succ.dominates(pred) or not pred.isReachableFromFunctionEntry())))
}
}
private predicate is_condition(Instruction guard) {
exists(ConditionalBranchInstruction branch|
branch.getCondition() = guard
)
or
exists(LogicalNotInstruction cond | is_condition(cond) and cond.getOperand() = guard)
}
/**
* Holds if `left == right + k` is `areEqual` given that test is `testIsTrue`.
*
* Beware making mistaken logical implications here relating `areEqual` and `testIsTrue`.
*/
private predicate compares_eq(Instruction test, Instruction left, Instruction right, int k, boolean areEqual, boolean testIsTrue) {
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
exists(boolean eq | simple_comparison_eq(test, left, right, k, eq) |
areEqual = true and testIsTrue = eq or areEqual = false and testIsTrue = eq.booleanNot()
)
// I think this is handled by forwarding in controlsBlock.
/* or
logical_comparison_eq(test, left, right, k, areEqual, testIsTrue) */
or
/* a == b + k => b == a - k */
exists(int mk | k = -mk | compares_eq(test, right, left, mk, areEqual, testIsTrue))
or
complex_eq(test, left, right, k, areEqual, testIsTrue)
or
/* (x is true => (left == right + k)) => (!x is false => (left == right + k)) */
exists(boolean isFalse | testIsTrue = isFalse.booleanNot() |
compares_eq(test.(LogicalNotInstruction).getOperand(), left, right, k, areEqual, isFalse)
)
}
/** Rearrange various simple comparisons into `left == right + k` form. */
private predicate simple_comparison_eq(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean areEqual) {
left = cmp.getLeftOperand() and cmp instanceof CompareEQInstruction and right = cmp.getRightOperand() and k = 0 and areEqual = true
or
left = cmp.getLeftOperand() and cmp instanceof CompareNEInstruction and right = cmp.getRightOperand() and k = 0 and areEqual = false
}
private predicate complex_eq(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean areEqual, boolean testIsTrue) {
sub_eq(cmp, left, right, k, areEqual, testIsTrue)
or
add_eq(cmp, left, right, k, areEqual, testIsTrue)
}
/* Simplification of inequality expressions
* Simplify conditions in the source to the canonical form l < r + k.
*/
/** Holds if `left < right + k` evaluates to `isLt` given that test is `testIsTrue`. */
private predicate compares_lt(Instruction test, Instruction left, Instruction right, int k, boolean isLt, boolean testIsTrue) {
/* In the simple case, the test is the comparison, so isLt = testIsTrue */
simple_comparison_lt(test, left, right, k) and isLt = true and testIsTrue = true
or
simple_comparison_lt(test, left, right, k) and isLt = false and testIsTrue = false
or
complex_lt(test, left, right, k, isLt, testIsTrue)
or
/* (not (left < right + k)) => (left >= right + k) */
exists(boolean isGe | isLt = isGe.booleanNot() |
compares_ge(test, left, right, k, isGe, testIsTrue)
)
or
/* (x is true => (left < right + k)) => (!x is false => (left < right + k)) */
exists(boolean isFalse | testIsTrue = isFalse.booleanNot() |
compares_lt(test.(LogicalNotInstruction).getOperand(), left, right, k, isLt, isFalse)
)
}
/** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */
private predicate compares_ge(Instruction test, Instruction left, Instruction right, int k, boolean isGe, boolean testIsTrue) {
exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, testIsTrue))
}
/** Rearrange various simple comparisons into `left < right + k` form. */
private predicate simple_comparison_lt(CompareInstruction cmp, Instruction left, Instruction right, int k) {
left = cmp.getLeftOperand() and cmp instanceof CompareLTInstruction and right = cmp.getRightOperand() and k = 0
or
left = cmp.getLeftOperand() and cmp instanceof CompareLEInstruction and right = cmp.getRightOperand() and k = 1
or
right = cmp.getLeftOperand() and cmp instanceof CompareGTInstruction and left = cmp.getRightOperand() and k = 0
or
right = cmp.getLeftOperand() and cmp instanceof CompareGEInstruction and left = cmp.getRightOperand() and k = 1
}
private predicate complex_lt(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean isLt, boolean testIsTrue) {
sub_lt(cmp, left, right, k, isLt, testIsTrue)
or
add_lt(cmp, left, right, k, isLt, testIsTrue)
}
/* left - x < right + c => left < right + (c+x)
left < (right - x) + c => left < right + (c-x) */
private predicate sub_lt(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean isLt, boolean testIsTrue) {
exists(SubInstruction lhs, int c, int x | compares_lt(cmp, lhs, right, c, isLt, testIsTrue) and
left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand())
and k = c + x
)
or
exists(SubInstruction rhs, int c, int x | compares_lt(cmp, left, rhs, c, isLt, testIsTrue) and
right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand())
and k = c - x
)
}
/* left + x < right + c => left < right + (c-x)
left < (right + x) + c => left < right + (c+x) */
private predicate add_lt(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean isLt, boolean testIsTrue) {
exists(AddInstruction lhs, int c, int x | compares_lt(cmp, lhs, right, c, isLt, testIsTrue) and
(left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand())
or
left = lhs.getRightOperand() and x = int_value(lhs.getLeftOperand())
)
and k = c - x
)
or
exists(AddInstruction rhs, int c, int x | compares_lt(cmp, left, rhs, c, isLt, testIsTrue) and
(right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand())
or
right = rhs.getRightOperand() and x = int_value(rhs.getLeftOperand())
)
and k = c + x
)
}
/* left - x == right + c => left == right + (c+x)
left == (right - x) + c => left == right + (c-x) */
private predicate sub_eq(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean areEqual, boolean testIsTrue) {
exists(SubInstruction lhs, int c, int x | compares_eq(cmp, lhs, right, c, areEqual, testIsTrue) and
left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand())
and k = c + x
)
or
exists(SubInstruction rhs, int c, int x | compares_eq(cmp, left, rhs, c, areEqual, testIsTrue) and
right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand())
and k = c - x
)
}
/* left + x == right + c => left == right + (c-x)
left == (right + x) + c => left == right + (c+x) */
private predicate add_eq(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean areEqual, boolean testIsTrue) {
exists(AddInstruction lhs, int c, int x | compares_eq(cmp, lhs, right, c, areEqual, testIsTrue) and
(left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand())
or
left = lhs.getRightOperand() and x = int_value(lhs.getLeftOperand())
)
and k = c - x
)
or
exists(AddInstruction rhs, int c, int x | compares_eq(cmp, left, rhs, c, areEqual, testIsTrue) and
(right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand())
or
right = rhs.getRightOperand() and x = int_value(rhs.getLeftOperand())
)
and k = c + x
)
}
/** The int value of integer constant expression. */
private int int_value(Instruction i) {
result = i.(IntegerConstantInstruction).getValue().toInt()
}

View File

@@ -31,8 +31,11 @@ private cached module Cached {
// or the node's predecessor has more than one successor,
// then the node is the start of a new primitive basic block.
or
strictcount (Node pred, Node other
| successors_extended(pred,node) and successors_extended(pred,other)) > 1
strictcount(Node pred | successors_extended(pred, node)) > 1
or
exists(ControlFlowNode pred | successors_extended(pred, node) |
strictcount(ControlFlowNode other | successors_extended(pred, other)) > 1
)
// If the node has zero predecessors then it is the start of
// a BB. However, the C++ AST contains many nodes with zero
@@ -63,8 +66,14 @@ private cached module Cached {
/** Holds if `node` is the `pos`th control-flow node in primitive basic block `bb`. */
cached
predicate primitive_basic_block_member(Node node, PrimitiveBasicBlock bb, int pos) {
pos = getMemberIndex(node) and
member_step*(bb, node)
primitive_basic_block_entry_node(bb) and
(
pos = 0 and
node = bb
or
pos = getMemberIndex(node) and
member_step+(bb, node)
)
}
/** Gets the number of control-flow nodes in the primitive basic block `bb`. */

View File

@@ -54,4 +54,10 @@ cached private module Cached {
(usertypes(t,_,1) or usertypes(t,_,2) or usertypes(t,_,3) or usertypes(t,_,6)
or usertypes(t,_,10) or usertypes(t,_,11) or usertypes(t,_,12))
}
cached predicate isType(@type t) {
not isClass(t)
or
t = resolveClass(_)
}
}

View File

@@ -76,6 +76,8 @@ abstract class PointerOffsetOpcode extends PointerArithmeticOpcode {}
abstract class CompareOpcode extends BinaryOpcode {}
abstract class RelationalOpcode extends CompareOpcode {}
abstract class CopyOpcode extends Opcode {}
abstract class MemoryAccessOpcode extends Opcode {}
@@ -117,10 +119,10 @@ module Opcode {
class LogicalNot extends UnaryOpcode, TLogicalNot { override final string toString() { result = "LogicalNot" } }
class CompareEQ extends CompareOpcode, TCompareEQ { override final string toString() { result = "CompareEQ" } }
class CompareNE extends CompareOpcode, TCompareNE { override final string toString() { result = "CompareNE" } }
class CompareLT extends CompareOpcode, TCompareLT { override final string toString() { result = "CompareLT" } }
class CompareGT extends CompareOpcode, TCompareGT { override final string toString() { result = "CompareGT" } }
class CompareLE extends CompareOpcode, TCompareLE { override final string toString() { result = "CompareLE" } }
class CompareGE extends CompareOpcode, TCompareGE { override final string toString() { result = "CompareGE" } }
class CompareLT extends RelationalOpcode, TCompareLT { override final string toString() { result = "CompareLT" } }
class CompareGT extends RelationalOpcode, TCompareGT { override final string toString() { result = "CompareGT" } }
class CompareLE extends RelationalOpcode, TCompareLE { override final string toString() { result = "CompareLE" } }
class CompareGE extends RelationalOpcode, TCompareGE { override final string toString() { result = "CompareGE" } }
class PointerAdd extends PointerOffsetOpcode, TPointerAdd { override final string toString() { result = "PointerAdd" } }
class PointerSub extends PointerOffsetOpcode, TPointerSub { override final string toString() { result = "PointerSub" } }
class PointerDiff extends PointerArithmeticOpcode, TPointerDiff { override final string toString() { result = "PointerDiff" } }

View File

@@ -89,4 +89,12 @@ class IRBlock extends TIRBlock {
dominates(result.getAPredecessor()) and
not strictlyDominates(result)
}
/**
* Holds if this block is reachable from the entry point of its function
*/
final predicate isReachableFromFunctionEntry() {
this = getFunctionIR().getEntryBlock() or
getAPredecessor().isReachableFromFunctionEntry()
}
}

View File

@@ -133,6 +133,16 @@ class Instruction extends Construction::TInstruction {
}
final string toString() {
result = getOpcode().toString() + ": " + getAST().toString()
}
/**
* Gets a string showing the result, opcode, and operands of the instruction, equivalent to what
* would be printed by PrintIR.ql. For example:
*
* `mu0_28(int) = Store r0_26, r0_27`
*/
final string getDumpString() {
result = getResultString() + " = " + getOperationString() + " " + getOperandsString()
}
@@ -310,11 +320,19 @@ class Instruction extends Construction::TInstruction {
}
/**
* Gets the `Expr` whose results is computed by this instruction, if any.
* Gets the `Expr` whose result is computed by this instruction, if any.
*/
final Expr getResultExpression() {
result = Construction::getInstructionResultExpression(this)
final Expr getConvertedResultExpression() {
result = Construction::getInstructionConvertedResultExpression(this)
}
/**
* Gets the unconverted `Expr` whose result is computed by this instruction, if any.
*/
final Expr getUnconvertedResultExpression() {
result = Construction::getInstructionUnconvertedResultExpression(this)
}
/**
* Gets the type of the result produced by this instruction. If the
@@ -967,28 +985,110 @@ class CompareNEInstruction extends CompareInstruction {
}
}
class CompareLTInstruction extends CompareInstruction {
/**
* Represents an instruction that does a relative comparison of two values, such as `<` or `>=`.
*/
class RelationalInstruction extends CompareInstruction {
RelationalInstruction() {
opcode instanceof RelationalOpcode
}
/**
* Gets the operand on the "greater" (or "greater-or-equal") side
* of this relational instruction, that is, the side that is larger
* if the overall instruction evaluates to `true`; for example on
* `x <= 20` this is the `20`, and on `y > 0` it is `y`.
*/
Instruction getGreaterOperand() {
none()
}
/**
* Gets the operand on the "lesser" (or "lesser-or-equal") side
* of this relational instruction, that is, the side that is smaller
* if the overall instruction evaluates to `true`; for example on
* `x <= 20` this is `x`, and on `y > 0` it is the `0`.
*/
Instruction getLesserOperand() {
none()
}
/**
* Holds if this relational instruction is strict (is not an "or-equal" instruction).
*/
predicate isStrict() {
none()
}
}
class CompareLTInstruction extends RelationalInstruction {
CompareLTInstruction() {
opcode instanceof Opcode::CompareLT
}
override Instruction getLesserOperand() {
result = getLeftOperand()
}
override Instruction getGreaterOperand() {
result = getRightOperand()
}
override predicate isStrict() {
any()
}
}
class CompareGTInstruction extends CompareInstruction {
class CompareGTInstruction extends RelationalInstruction {
CompareGTInstruction() {
opcode instanceof Opcode::CompareGT
}
}
class CompareLEInstruction extends CompareInstruction {
CompareLEInstruction() {
opcode instanceof Opcode::CompareLE
override Instruction getLesserOperand() {
result = getRightOperand()
}
override Instruction getGreaterOperand() {
result = getLeftOperand()
}
override predicate isStrict() {
any()
}
}
class CompareGEInstruction extends CompareInstruction {
class CompareLEInstruction extends RelationalInstruction {
CompareLEInstruction() {
opcode instanceof Opcode::CompareLE
}
override Instruction getLesserOperand() {
result = getLeftOperand()
}
override Instruction getGreaterOperand() {
result = getRightOperand()
}
override predicate isStrict() {
none()
}
}
class CompareGEInstruction extends RelationalInstruction {
CompareGEInstruction() {
opcode instanceof Opcode::CompareGE
}
override Instruction getLesserOperand() {
result = getRightOperand()
}
override Instruction getGreaterOperand() {
result = getLeftOperand()
}
override predicate isStrict() {
none()
}
}
class SwitchInstruction extends Instruction {

View File

@@ -197,8 +197,12 @@ cached private module Cached {
)
}
cached Expr getInstructionResultExpression(Instruction instruction) {
result = getOldInstruction(instruction).getResultExpression()
cached Expr getInstructionConvertedResultExpression(Instruction instruction) {
result = getOldInstruction(instruction).getConvertedResultExpression()
}
cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
result = getOldInstruction(instruction).getUnconvertedResultExpression()
}
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {

View File

@@ -89,4 +89,12 @@ class IRBlock extends TIRBlock {
dominates(result.getAPredecessor()) and
not strictlyDominates(result)
}
/**
* Holds if this block is reachable from the entry point of its function
*/
final predicate isReachableFromFunctionEntry() {
this = getFunctionIR().getEntryBlock() or
getAPredecessor().isReachableFromFunctionEntry()
}
}

View File

@@ -133,6 +133,16 @@ class Instruction extends Construction::TInstruction {
}
final string toString() {
result = getOpcode().toString() + ": " + getAST().toString()
}
/**
* Gets a string showing the result, opcode, and operands of the instruction, equivalent to what
* would be printed by PrintIR.ql. For example:
*
* `mu0_28(int) = Store r0_26, r0_27`
*/
final string getDumpString() {
result = getResultString() + " = " + getOperationString() + " " + getOperandsString()
}
@@ -310,11 +320,19 @@ class Instruction extends Construction::TInstruction {
}
/**
* Gets the `Expr` whose results is computed by this instruction, if any.
* Gets the `Expr` whose result is computed by this instruction, if any.
*/
final Expr getResultExpression() {
result = Construction::getInstructionResultExpression(this)
final Expr getConvertedResultExpression() {
result = Construction::getInstructionConvertedResultExpression(this)
}
/**
* Gets the unconverted `Expr` whose result is computed by this instruction, if any.
*/
final Expr getUnconvertedResultExpression() {
result = Construction::getInstructionUnconvertedResultExpression(this)
}
/**
* Gets the type of the result produced by this instruction. If the
@@ -967,28 +985,110 @@ class CompareNEInstruction extends CompareInstruction {
}
}
class CompareLTInstruction extends CompareInstruction {
/**
* Represents an instruction that does a relative comparison of two values, such as `<` or `>=`.
*/
class RelationalInstruction extends CompareInstruction {
RelationalInstruction() {
opcode instanceof RelationalOpcode
}
/**
* Gets the operand on the "greater" (or "greater-or-equal") side
* of this relational instruction, that is, the side that is larger
* if the overall instruction evaluates to `true`; for example on
* `x <= 20` this is the `20`, and on `y > 0` it is `y`.
*/
Instruction getGreaterOperand() {
none()
}
/**
* Gets the operand on the "lesser" (or "lesser-or-equal") side
* of this relational instruction, that is, the side that is smaller
* if the overall instruction evaluates to `true`; for example on
* `x <= 20` this is `x`, and on `y > 0` it is the `0`.
*/
Instruction getLesserOperand() {
none()
}
/**
* Holds if this relational instruction is strict (is not an "or-equal" instruction).
*/
predicate isStrict() {
none()
}
}
class CompareLTInstruction extends RelationalInstruction {
CompareLTInstruction() {
opcode instanceof Opcode::CompareLT
}
override Instruction getLesserOperand() {
result = getLeftOperand()
}
override Instruction getGreaterOperand() {
result = getRightOperand()
}
override predicate isStrict() {
any()
}
}
class CompareGTInstruction extends CompareInstruction {
class CompareGTInstruction extends RelationalInstruction {
CompareGTInstruction() {
opcode instanceof Opcode::CompareGT
}
}
class CompareLEInstruction extends CompareInstruction {
CompareLEInstruction() {
opcode instanceof Opcode::CompareLE
override Instruction getLesserOperand() {
result = getRightOperand()
}
override Instruction getGreaterOperand() {
result = getLeftOperand()
}
override predicate isStrict() {
any()
}
}
class CompareGEInstruction extends CompareInstruction {
class CompareLEInstruction extends RelationalInstruction {
CompareLEInstruction() {
opcode instanceof Opcode::CompareLE
}
override Instruction getLesserOperand() {
result = getLeftOperand()
}
override Instruction getGreaterOperand() {
result = getRightOperand()
}
override predicate isStrict() {
none()
}
}
class CompareGEInstruction extends RelationalInstruction {
CompareGEInstruction() {
opcode instanceof Opcode::CompareGE
}
override Instruction getLesserOperand() {
result = getRightOperand()
}
override Instruction getGreaterOperand() {
result = getLeftOperand()
}
override predicate isStrict() {
none()
}
}
class SwitchInstruction extends Instruction {

View File

@@ -74,13 +74,25 @@ cached private module Cached {
none()
}
cached Expr getInstructionResultExpression(Instruction instruction) {
cached Expr getInstructionConvertedResultExpression(Instruction instruction) {
exists(TranslatedExpr translatedExpr |
translatedExpr = getTranslatedExpr(result) and
instruction = translatedExpr.getResult()
)
}
cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
exists(Expr converted, TranslatedExpr translatedExpr |
result = converted.(Conversion).getExpr+()
or
result = converted
|
not result instanceof Conversion and
translatedExpr = getTranslatedExpr(converted) and
instruction = translatedExpr.getResult()
)
}
cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) {
result = getInstructionTranslatedElement(instruction).getInstructionOperand(
instruction.getTag(), tag)

View File

@@ -89,4 +89,12 @@ class IRBlock extends TIRBlock {
dominates(result.getAPredecessor()) and
not strictlyDominates(result)
}
/**
* Holds if this block is reachable from the entry point of its function
*/
final predicate isReachableFromFunctionEntry() {
this = getFunctionIR().getEntryBlock() or
getAPredecessor().isReachableFromFunctionEntry()
}
}

View File

@@ -133,6 +133,16 @@ class Instruction extends Construction::TInstruction {
}
final string toString() {
result = getOpcode().toString() + ": " + getAST().toString()
}
/**
* Gets a string showing the result, opcode, and operands of the instruction, equivalent to what
* would be printed by PrintIR.ql. For example:
*
* `mu0_28(int) = Store r0_26, r0_27`
*/
final string getDumpString() {
result = getResultString() + " = " + getOperationString() + " " + getOperandsString()
}
@@ -310,11 +320,19 @@ class Instruction extends Construction::TInstruction {
}
/**
* Gets the `Expr` whose results is computed by this instruction, if any.
* Gets the `Expr` whose result is computed by this instruction, if any.
*/
final Expr getResultExpression() {
result = Construction::getInstructionResultExpression(this)
final Expr getConvertedResultExpression() {
result = Construction::getInstructionConvertedResultExpression(this)
}
/**
* Gets the unconverted `Expr` whose result is computed by this instruction, if any.
*/
final Expr getUnconvertedResultExpression() {
result = Construction::getInstructionUnconvertedResultExpression(this)
}
/**
* Gets the type of the result produced by this instruction. If the
@@ -967,28 +985,110 @@ class CompareNEInstruction extends CompareInstruction {
}
}
class CompareLTInstruction extends CompareInstruction {
/**
* Represents an instruction that does a relative comparison of two values, such as `<` or `>=`.
*/
class RelationalInstruction extends CompareInstruction {
RelationalInstruction() {
opcode instanceof RelationalOpcode
}
/**
* Gets the operand on the "greater" (or "greater-or-equal") side
* of this relational instruction, that is, the side that is larger
* if the overall instruction evaluates to `true`; for example on
* `x <= 20` this is the `20`, and on `y > 0` it is `y`.
*/
Instruction getGreaterOperand() {
none()
}
/**
* Gets the operand on the "lesser" (or "lesser-or-equal") side
* of this relational instruction, that is, the side that is smaller
* if the overall instruction evaluates to `true`; for example on
* `x <= 20` this is `x`, and on `y > 0` it is the `0`.
*/
Instruction getLesserOperand() {
none()
}
/**
* Holds if this relational instruction is strict (is not an "or-equal" instruction).
*/
predicate isStrict() {
none()
}
}
class CompareLTInstruction extends RelationalInstruction {
CompareLTInstruction() {
opcode instanceof Opcode::CompareLT
}
override Instruction getLesserOperand() {
result = getLeftOperand()
}
override Instruction getGreaterOperand() {
result = getRightOperand()
}
override predicate isStrict() {
any()
}
}
class CompareGTInstruction extends CompareInstruction {
class CompareGTInstruction extends RelationalInstruction {
CompareGTInstruction() {
opcode instanceof Opcode::CompareGT
}
}
class CompareLEInstruction extends CompareInstruction {
CompareLEInstruction() {
opcode instanceof Opcode::CompareLE
override Instruction getLesserOperand() {
result = getRightOperand()
}
override Instruction getGreaterOperand() {
result = getLeftOperand()
}
override predicate isStrict() {
any()
}
}
class CompareGEInstruction extends CompareInstruction {
class CompareLEInstruction extends RelationalInstruction {
CompareLEInstruction() {
opcode instanceof Opcode::CompareLE
}
override Instruction getLesserOperand() {
result = getLeftOperand()
}
override Instruction getGreaterOperand() {
result = getRightOperand()
}
override predicate isStrict() {
none()
}
}
class CompareGEInstruction extends RelationalInstruction {
CompareGEInstruction() {
opcode instanceof Opcode::CompareGE
}
override Instruction getLesserOperand() {
result = getRightOperand()
}
override Instruction getGreaterOperand() {
result = getLeftOperand()
}
override predicate isStrict() {
none()
}
}
class SwitchInstruction extends Instruction {

View File

@@ -197,8 +197,12 @@ cached private module Cached {
)
}
cached Expr getInstructionResultExpression(Instruction instruction) {
result = getOldInstruction(instruction).getResultExpression()
cached Expr getInstructionConvertedResultExpression(Instruction instruction) {
result = getOldInstruction(instruction).getConvertedResultExpression()
}
cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
result = getOldInstruction(instruction).getUnconvertedResultExpression()
}
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {

View File

@@ -12,7 +12,8 @@ class Printf extends FormattingFunction {
hasGlobalName("wprintf") or
hasGlobalName("wprintf_s") or
hasGlobalName("g_printf")
)
) and
not exists(getDefinition().getFile().getRelativePath())
}
override int getFormatParameterIndex() { result=0 }
@@ -26,7 +27,15 @@ class Printf extends FormattingFunction {
* The standard functions `fprintf`, `fwprintf` and their glib variants.
*/
class Fprintf extends FormattingFunction {
Fprintf() { this instanceof TopLevelFunction and (hasGlobalName("fprintf") or hasGlobalName("fwprintf") or hasGlobalName("g_fprintf"))}
Fprintf() {
this instanceof TopLevelFunction and
(
hasGlobalName("fprintf") or
hasGlobalName("fwprintf") or
hasGlobalName("g_fprintf")
) and
not exists(getDefinition().getFile().getRelativePath())
}
override int getFormatParameterIndex() { result=1 }
override predicate isWideCharDefault() { hasGlobalName("fwprintf") }
@@ -47,7 +56,8 @@ class Sprintf extends FormattingFunction {
hasGlobalName("g_strdup_printf") or
hasGlobalName("g_sprintf") or
hasGlobalName("__builtin___sprintf_chk")
)
) and
not exists(getDefinition().getFile().getRelativePath())
}
override predicate isWideCharDefault() {
@@ -100,7 +110,8 @@ class Snprintf extends FormattingFunction {
or hasGlobalName("g_snprintf")
or hasGlobalName("wnsprintf")
or hasGlobalName("__builtin___snprintf_chk")
)
) and
not exists(getDefinition().getFile().getRelativePath())
}
override int getFormatParameterIndex() {
@@ -133,10 +144,13 @@ class Snprintf extends FormattingFunction {
* in the buffer.
*/
predicate returnsFullFormatLength() {
hasGlobalName("snprintf") or
hasGlobalName("g_snprintf") or
hasGlobalName("__builtin___snprintf_chk") or
hasGlobalName("snprintf_s")
(
hasGlobalName("snprintf") or
hasGlobalName("g_snprintf") or
hasGlobalName("__builtin___snprintf_chk") or
hasGlobalName("snprintf_s")
) and
not exists(getDefinition().getFile().getRelativePath())
}
override int getSizeParameterIndex() {
@@ -158,7 +172,8 @@ class StringCchPrintf extends FormattingFunction {
or hasGlobalName("StringCbPrintfEx")
or hasGlobalName("StringCbPrintf_l")
or hasGlobalName("StringCbPrintf_lEx")
)
) and
not exists(getDefinition().getFile().getRelativePath())
}
override int getFormatParameterIndex() {
@@ -187,7 +202,8 @@ class Syslog extends FormattingFunction {
Syslog() {
this instanceof TopLevelFunction and (
hasGlobalName("syslog")
)
) and
not exists(getDefinition().getFile().getRelativePath())
}
override int getFormatParameterIndex() { result=1 }

View File

@@ -7,6 +7,38 @@
*/
import semmle.code.cpp.Function
private Type stripTopLevelSpecifiersOnly(Type t) {
(
result = stripTopLevelSpecifiersOnly(t.(SpecifiedType).getBaseType())
) or (
result = t and
not t instanceof SpecifiedType
)
}
/**
* A type that is used as a format string by any formatting function.
*/
Type getAFormatterWideType() {
exists(FormattingFunction ff |
result = stripTopLevelSpecifiersOnly(ff.getDefaultCharType()) and
result.getSize() != 1
)
}
/**
* A type that is used as a format string by any formatting function, or `wchar_t` if
* there is none.
*/
private Type getAFormatterWideTypeOrDefault() {
result = getAFormatterWideType() or
(
not exists(getAFormatterWideType()) and
result instanceof Wchar_t
)
}
/**
* A standard library function that uses a `printf`-like formatting string.
*/
@@ -20,6 +52,43 @@ abstract class FormattingFunction extends Function {
*/
predicate isWideCharDefault() { none() }
/**
* Gets the default character type expected for `%s` by this function. Typically
* `char` or `wchar_t`.
*/
Type getDefaultCharType() {
result = stripTopLevelSpecifiersOnly(getParameter(getFormatParameterIndex()).getType().
getUnderlyingType().(PointerType).getBaseType())
}
/**
* Gets the non-default character type expected for `%S` by this function. Typically
* `wchar_t` or `char`. On some snapshots there may be multiple results where we can't tell
* which is correct for a particular function.
*/
Type getNonDefaultCharType() {
(
getDefaultCharType().getSize() = 1 and
result = getAFormatterWideTypeOrDefault()
) or (
getDefaultCharType().getSize() > 1 and
result instanceof PlainCharType
)
}
/**
* Gets the wide character type for this function. This is usually `wchar_t`. On some
* snapshots there may be multiple results where we can't tell which is correct for a
* particular function.
*/
Type getWideCharType() {
(
result = getDefaultCharType() or
result = getNonDefaultCharType()
) and
result.getSize() > 1
}
/**
* Gets the position at which the output parameter, if any, occurs.
*/

View File

@@ -633,12 +633,26 @@ class PointsToExpr extends Expr
pragma[noopt]
Element pointsTo()
{
this.interesting() and exists(int set, @element thisEntity, @element resultEntity | thisEntity = underlyingElement(this) and pointstosets(set, thisEntity) and setlocations(set, resultEntity) and resultEntity = unresolveElement(result))
this.interesting() and
exists(int set, @element thisEntity, @element resultEntity |
thisEntity = underlyingElement(this) and
pointstosets(set, thisEntity) and
setlocations(set, resultEntity) and
resultEntity = localUnresolveElement(result)
)
}
float confidence() { result = 1.0 / count(this.pointsTo()) }
}
/*
* This is used above in a `pragma[noopt]` context, which prevents its
* customary inlining. We materialise it explicitly here.
*/
private @element localUnresolveElement(Element e) {
result = unresolveElement(e)
}
/**
* Holds if anything points to an element, that is, is equivalent to:
* ```

View File

@@ -44,6 +44,7 @@
import cpp
private import RangeAnalysisUtils
import RangeSSA
import SimpleRangeAnalysisCached
/**
* This fixed set of lower bounds is used when the lower bounds of an
@@ -406,27 +407,6 @@ deprecated predicate negative_overflow(Expr expr) {
exprMightOverflowNegatively(expr)
}
/**
* Holds if the expression might overflow negatively. This predicate
* does not consider the possibility that the expression might overflow
* due to a conversion.
*/
cached
predicate exprMightOverflowNegatively(Expr expr) {
getLowerBoundsImpl(expr) < exprMinVal(expr)
}
/**
* Holds if the expression might overflow negatively. Conversions
* are also taken into account. For example the expression
* `(int16)(x+y)` might overflow due to the `(int16)` cast, rather than
* due to the addition.
*/
cached
predicate convertedExprMightOverflowNegatively(Expr expr) {
exprMightOverflowNegatively(expr) or
convertedExprMightOverflowNegatively(expr.getConversion())
}
/**
* Holds if the expression might overflow positively. This predicate
@@ -439,39 +419,6 @@ deprecated predicate positive_overflow(Expr expr) {
exprMightOverflowPositively(expr)
}
/**
* Holds if the expression might overflow positively. This predicate
* does not consider the possibility that the expression might overflow
* due to a conversion.
*/
cached
predicate exprMightOverflowPositively(Expr expr) {
getUpperBoundsImpl(expr) > exprMaxVal(expr)
}
/**
* Holds if the expression might overflow positively. Conversions
* are also taken into account. For example the expression
* `(int16)(x+y)` might overflow due to the `(int16)` cast, rather than
* due to the addition.
*/
cached
predicate convertedExprMightOverflowPositively(Expr expr) {
exprMightOverflowPositively(expr) or
convertedExprMightOverflowPositively(expr.getConversion())
}
/**
* Holds if the expression might overflow (either positively or
* negatively). The possibility that the expression might overflow
* due to an implicit or explicit cast is also considered.
*/
cached
predicate convertedExprMightOverflow(Expr expr) {
convertedExprMightOverflowNegatively(expr) or
convertedExprMightOverflowPositively(expr)
}
/** Only to be called by `getTruncatedLowerBounds`. */
private
float getLowerBoundsImpl(Expr expr) {
@@ -921,28 +868,6 @@ float getDefUpperBoundsImpl(RangeSsaDefinition def, LocalScopeVariable v) {
unanalyzableDefBounds(def, v, _, result)
}
/** Holds if the definition might overflow negatively. */
cached
predicate defMightOverflowNegatively(RangeSsaDefinition def, LocalScopeVariable v) {
getDefLowerBoundsImpl(def, v) < varMinVal(v)
}
/** Holds if the definition might overflow positively. */
cached
predicate defMightOverflowPositively(RangeSsaDefinition def, LocalScopeVariable v) {
getDefUpperBoundsImpl(def, v) > varMaxVal(v)
}
/**
* Holds if the definition might overflow (either positively or
* negatively).
*/
cached
predicate defMightOverflow(RangeSsaDefinition def, LocalScopeVariable v) {
defMightOverflowNegatively(def, v) or
defMightOverflowPositively(def, v)
}
/**
* Get the lower bounds for a `RangeSsaDefinition`. Most of the work is
* done by `getDefLowerBoundsImpl`, but this is where widening is applied
@@ -1133,63 +1058,142 @@ predicate exprTypeBounds(Expr expr, float boundValue, boolean isLowerBound) {
(isLowerBound = false and boundValue = exprMaxVal(expr.getFullyConverted()))
}
/**
* Gets the lower bound of the expression.
*
* Note: expressions in C/C++ are often implicitly or explicitly cast to a
* different result type. Such casts can cause the value of the expression
* to overflow or to be truncated. This predicate computes the lower bound
* of the expression without including the effect of the casts. To compute
* the lower bound of the expression after all the casts have been applied,
* call `lowerBound` like this:
*
* `lowerBound(expr.getFullyConverted())`
*/
cached
float lowerBound(Expr expr) {
// Combine the lower bounds returned by getTruncatedLowerBounds into a
// single minimum value.
result = min(float lb | lb = getTruncatedLowerBounds(expr) | lb)
}
private cached module SimpleRangeAnalysisCached {
/**
* Gets the lower bound of the expression.
*
* Note: expressions in C/C++ are often implicitly or explicitly cast to a
* different result type. Such casts can cause the value of the expression
* to overflow or to be truncated. This predicate computes the lower bound
* of the expression without including the effect of the casts. To compute
* the lower bound of the expression after all the casts have been applied,
* call `lowerBound` like this:
*
* `lowerBound(expr.getFullyConverted())`
*/
cached
float lowerBound(Expr expr) {
// Combine the lower bounds returned by getTruncatedLowerBounds into a
// single minimum value.
result = min(float lb | lb = getTruncatedLowerBounds(expr) | lb)
}
/**
* Gets the upper bound of the expression.
*
* Note: expressions in C/C++ are often implicitly or explicitly cast to a
* different result type. Such casts can cause the value of the expression
* to overflow or to be truncated. This predicate computes the upper bound
* of the expression without including the effect of the casts. To compute
* the upper bound of the expression after all the casts have been applied,
* call `upperBound` like this:
*
* `upperBound(expr.getFullyConverted())`
*/
cached
float upperBound(Expr expr) {
// Combine the upper bounds returned by getTruncatedUpperBounds into a
// single maximum value.
result = max(float ub | ub = getTruncatedUpperBounds(expr) | ub)
}
/**
* Holds if `expr` has a provably empty range. For example:
*
* 10 < expr and expr < 5
*
* The range of an expression can only be empty if it can never be
* executed. For example:
*
* if (10 < x) {
* if (x < 5) {
* // Unreachable code
* return x; // x has an empty range: 10 < x && x < 5
* }
* }
*/
cached
predicate exprWithEmptyRange(Expr expr) {
analyzableExpr(expr) and
(not exists(lowerBound(expr)) or
not exists(upperBound(expr)) or
lowerBound(expr) > upperBound(expr))
}
/**
* Gets the upper bound of the expression.
*
* Note: expressions in C/C++ are often implicitly or explicitly cast to a
* different result type. Such casts can cause the value of the expression
* to overflow or to be truncated. This predicate computes the upper bound
* of the expression without including the effect of the casts. To compute
* the upper bound of the expression after all the casts have been applied,
* call `upperBound` like this:
*
* `upperBound(expr.getFullyConverted())`
*/
cached
float upperBound(Expr expr) {
// Combine the upper bounds returned by getTruncatedUpperBounds into a
// single maximum value.
result = max(float ub | ub = getTruncatedUpperBounds(expr) | ub)
}
/**
* Holds if `expr` has a provably empty range. For example:
*
* 10 < expr and expr < 5
*
* The range of an expression can only be empty if it can never be
* executed. For example:
*
* if (10 < x) {
* if (x < 5) {
* // Unreachable code
* return x; // x has an empty range: 10 < x && x < 5
* }
* }
*/
cached
predicate exprWithEmptyRange(Expr expr) {
analyzableExpr(expr) and
(not exists(lowerBound(expr)) or
not exists(upperBound(expr)) or
lowerBound(expr) > upperBound(expr))
/** Holds if the definition might overflow negatively. */
cached
predicate defMightOverflowNegatively(RangeSsaDefinition def, LocalScopeVariable v) {
getDefLowerBoundsImpl(def, v) < varMinVal(v)
}
/** Holds if the definition might overflow positively. */
cached
predicate defMightOverflowPositively(RangeSsaDefinition def, LocalScopeVariable v) {
getDefUpperBoundsImpl(def, v) > varMaxVal(v)
}
/**
* Holds if the definition might overflow (either positively or
* negatively).
*/
cached
predicate defMightOverflow(RangeSsaDefinition def, LocalScopeVariable v) {
defMightOverflowNegatively(def, v) or
defMightOverflowPositively(def, v)
}
/**
* Holds if the expression might overflow negatively. This predicate
* does not consider the possibility that the expression might overflow
* due to a conversion.
*/
cached
predicate exprMightOverflowNegatively(Expr expr) {
getLowerBoundsImpl(expr) < exprMinVal(expr)
}
/**
* Holds if the expression might overflow negatively. Conversions
* are also taken into account. For example the expression
* `(int16)(x+y)` might overflow due to the `(int16)` cast, rather than
* due to the addition.
*/
cached
predicate convertedExprMightOverflowNegatively(Expr expr) {
exprMightOverflowNegatively(expr) or
convertedExprMightOverflowNegatively(expr.getConversion())
}
/**
* Holds if the expression might overflow positively. This predicate
* does not consider the possibility that the expression might overflow
* due to a conversion.
*/
cached
predicate exprMightOverflowPositively(Expr expr) {
getUpperBoundsImpl(expr) > exprMaxVal(expr)
}
/**
* Holds if the expression might overflow positively. Conversions
* are also taken into account. For example the expression
* `(int16)(x+y)` might overflow due to the `(int16)` cast, rather than
* due to the addition.
*/
cached
predicate convertedExprMightOverflowPositively(Expr expr) {
exprMightOverflowPositively(expr) or
convertedExprMightOverflowPositively(expr.getConversion())
}
/**
* Holds if the expression might overflow (either positively or
* negatively). The possibility that the expression might overflow
* due to an implicit or explicit cast is also considered.
*/
cached
predicate convertedExprMightOverflow(Expr expr) {
convertedExprMightOverflowNegatively(expr) or
convertedExprMightOverflowPositively(expr)
}
}

View File

@@ -13,6 +13,7 @@ predicate guardedAbs(Operation e, Expr use) {
}
/** is the size of this use guarded to be less than something? */
pragma[nomagic]
predicate guardedLesser(Operation e, Expr use) {
exists(IfStmt c, RelationalOperation guard |
use = guard.getLesserOperand().getAChild*() and
@@ -33,6 +34,7 @@ predicate guardedLesser(Operation e, Expr use) {
}
/** is the size of this use guarded to be greater than something? */
pragma[nomagic]
predicate guardedGreater(Operation e, Expr use) {
exists(IfStmt c, RelationalOperation guard |
use = guard.getGreaterOperand().getAChild*() and

View File

@@ -312,7 +312,7 @@ private predicate analyzableLocalScopeVariable(VariableAccess access) {
strictcount (SsaDefinition def, Variable v | def.getAUse(v) = access | v) = 1 and
count (SsaDefinition def, Variable v
| def.getAUse(v) = access
| def.getDefiningValue(v)) <= 1 and
| def.getDefiningValue(v).getFullyConverted()) <= 1 and
not analyzableConst(access)
}

View File

@@ -0,0 +1,154 @@
int test(int x, int w, int z) {
int j;
long y = 50;
// simple comparison
if (x > 0) {
y = 20;
z = 10;
} else {
y = 30;
}
z = x + y;
// More complex
if(x < 0 && y > 1)
y = 40;
else
y = 20; /* The && expression does not control this block as the x<0 expression jumps here if false. */
z = 10;
// while loop
while(x > 0) {
y = 10;
x--;
}
z += y;
// for loop
for(j = 0; j < 10; j++) {
y = 0;
w = 10;
}
z += w;
// nested control flow
for(j = 0; j < 10; j++) {
y = 30;
if(z > 0)
if(y > 0) {
w = 0;
break;
} else {
w = 20;
}
else {
w = 10;
continue;
}
x = 0;
}
if (x == 0 || y < 0) {
y = 60;
z = 10;
} else
return z;
z += x;
return 0;
}
int test2(int x, int w, int z) {
int j;
long y = 50;
// simple comparison
if (x == 0) {
y = 20;
z = 10;
} else {
y = 30;
}
z = x + y;
// More complex
if(x == 0 && y != 0)
y = 40;
else
y = 20;
z = 10;
// while loop
while(x != 0) {
y = 10;
x--;
}
z += y;
// for loop
for(j = 0; j < 10; j++) {
y = 0;
w = 10;
}
z += w;
if (x == 0 || y < 0) {
y = 60;
z = 10;
} else
return z;
z += x;
return 0;
}
int test3_condition();
void test3_action();
void test3() {
int b = 0;
if (1 && test3_condition()) {
b = 1;
test3_action();
}
if (b) {
test3_action();
}
}
void test4(int i) {
if (0) {
if (i) {
;
}
}
return;
}
void test5(int x) {
if (!x) {
test3();
}
}
void test6(int x, int y) {
return x && y;
}

View File

@@ -0,0 +1,54 @@
class X
{
public:
void set();
};
class Y
{
public:
Y* f();
const X* get() const { return 0; }
X* get() { return 0; }
};
Y* Y::f()
{
if ( get() )
get()->set();
return 0;
}
class Error {
public:
Error() {}
};
bool getABool();
void doSomething(int x) {
if (x == -1) {
throw new Error();
}
}
void doSomethingElse(int x);
bool testWithCatch0(int v)
{
try
{
if( getABool() )
{
doSomething(v);
return true;
}
}
catch(Error &e)
{
doSomethingElse(v);
}
return false;
}

View File

@@ -0,0 +1,730 @@
astGuards
| test.c:7:9:7:13 | ... > ... |
| test.c:17:8:17:12 | ... < ... |
| test.c:17:8:17:21 | ... && ... |
| test.c:17:17:17:21 | ... > ... |
| test.c:26:11:26:15 | ... > ... |
| test.c:34:16:34:21 | ... < ... |
| test.c:42:16:42:21 | ... < ... |
| test.c:44:12:44:16 | ... > ... |
| test.c:45:16:45:20 | ... > ... |
| test.c:58:9:58:14 | ... == ... |
| test.c:58:9:58:23 | ... \|\| ... |
| test.c:58:19:58:23 | ... < ... |
| test.c:75:9:75:14 | ... == ... |
| test.c:85:8:85:13 | ... == ... |
| test.c:85:8:85:23 | ... && ... |
| test.c:85:18:85:23 | ... != ... |
| test.c:94:11:94:16 | ... != ... |
| test.c:102:16:102:21 | ... < ... |
| test.c:109:9:109:14 | ... == ... |
| test.c:109:9:109:23 | ... \|\| ... |
| test.c:109:19:109:23 | ... < ... |
| test.c:126:7:126:7 | 1 |
| test.c:126:7:126:28 | ... && ... |
| test.c:126:12:126:26 | call to test3_condition |
| test.c:131:7:131:7 | b |
| test.c:137:7:137:7 | 0 |
| test.c:138:9:138:9 | i |
| test.c:146:7:146:8 | ! ... |
| test.c:146:8:146:8 | x |
| test.c:152:10:152:10 | x |
| test.c:152:10:152:15 | ... && ... |
| test.c:152:15:152:15 | y |
| test.cpp:18:8:18:10 | call to get |
| test.cpp:31:7:31:13 | ... == ... |
| test.cpp:42:13:42:20 | call to getABool |
astGuardsCompare
| 7 | 0 < x+0 when ... > ... is true |
| 7 | 0 >= x+0 when ... > ... is false |
| 7 | x < 0+1 when ... > ... is false |
| 7 | x >= 0+1 when ... > ... is true |
| 17 | 0 < x+1 when ... < ... is false |
| 17 | 0 >= x+1 when ... && ... is true |
| 17 | 0 >= x+1 when ... < ... is true |
| 17 | 1 < y+0 when ... && ... is true |
| 17 | 1 < y+0 when ... > ... is true |
| 17 | 1 >= y+0 when ... > ... is false |
| 17 | x < 0+0 when ... && ... is true |
| 17 | x < 0+0 when ... < ... is true |
| 17 | x >= 0+0 when ... < ... is false |
| 17 | y < 1+1 when ... > ... is false |
| 17 | y >= 1+1 when ... && ... is true |
| 17 | y >= 1+1 when ... > ... is true |
| 26 | 0 < x+0 when ... > ... is true |
| 26 | 0 >= x+0 when ... > ... is false |
| 26 | x < 0+1 when ... > ... is false |
| 26 | x >= 0+1 when ... > ... is true |
| 31 | - ... != x+0 when ... == ... is false |
| 31 | - ... == x+0 when ... == ... is true |
| 31 | x != - ...+0 when ... == ... is false |
| 31 | x == - ...+0 when ... == ... is true |
| 34 | 10 < j+1 when ... < ... is false |
| 34 | 10 >= j+1 when ... < ... is true |
| 34 | j < 10+0 when ... < ... is true |
| 34 | j >= 10+0 when ... < ... is false |
| 42 | 10 < j+1 when ... < ... is false |
| 42 | 10 >= j+1 when ... < ... is true |
| 42 | j < 10+0 when ... < ... is true |
| 42 | j >= 10+0 when ... < ... is false |
| 44 | 0 < z+0 when ... > ... is true |
| 44 | 0 >= z+0 when ... > ... is false |
| 44 | z < 0+1 when ... > ... is false |
| 44 | z >= 0+1 when ... > ... is true |
| 45 | 0 < y+0 when ... > ... is true |
| 45 | 0 >= y+0 when ... > ... is false |
| 45 | y < 0+1 when ... > ... is false |
| 45 | y >= 0+1 when ... > ... is true |
| 58 | 0 != x+0 when ... == ... is false |
| 58 | 0 != x+0 when ... \|\| ... is false |
| 58 | 0 < y+1 when ... < ... is false |
| 58 | 0 < y+1 when ... \|\| ... is false |
| 58 | 0 == x+0 when ... == ... is true |
| 58 | 0 >= y+1 when ... < ... is true |
| 58 | x != 0+0 when ... == ... is false |
| 58 | x != 0+0 when ... \|\| ... is false |
| 58 | x == 0+0 when ... == ... is true |
| 58 | y < 0+0 when ... < ... is true |
| 58 | y >= 0+0 when ... < ... is false |
| 58 | y >= 0+0 when ... \|\| ... is false |
| 75 | 0 != x+0 when ... == ... is false |
| 75 | 0 == x+0 when ... == ... is true |
| 75 | x != 0+0 when ... == ... is false |
| 75 | x == 0+0 when ... == ... is true |
| 85 | 0 != x+0 when ... == ... is false |
| 85 | 0 != y+0 when ... != ... is true |
| 85 | 0 != y+0 when ... && ... is true |
| 85 | 0 == x+0 when ... && ... is true |
| 85 | 0 == x+0 when ... == ... is true |
| 85 | 0 == y+0 when ... != ... is false |
| 85 | x != 0+0 when ... == ... is false |
| 85 | x == 0+0 when ... && ... is true |
| 85 | x == 0+0 when ... == ... is true |
| 85 | y != 0+0 when ... != ... is true |
| 85 | y != 0+0 when ... && ... is true |
| 85 | y == 0+0 when ... != ... is false |
| 94 | 0 != x+0 when ... != ... is true |
| 94 | 0 == x+0 when ... != ... is false |
| 94 | x != 0+0 when ... != ... is true |
| 94 | x == 0+0 when ... != ... is false |
| 102 | 10 < j+1 when ... < ... is false |
| 102 | 10 >= j+1 when ... < ... is true |
| 102 | j < 10+0 when ... < ... is true |
| 102 | j >= 10+0 when ... < ... is false |
| 109 | 0 != x+0 when ... == ... is false |
| 109 | 0 != x+0 when ... \|\| ... is false |
| 109 | 0 < y+1 when ... < ... is false |
| 109 | 0 < y+1 when ... \|\| ... is false |
| 109 | 0 == x+0 when ... == ... is true |
| 109 | 0 >= y+1 when ... < ... is true |
| 109 | x != 0+0 when ... == ... is false |
| 109 | x != 0+0 when ... \|\| ... is false |
| 109 | x == 0+0 when ... == ... is true |
| 109 | y < 0+0 when ... < ... is true |
| 109 | y >= 0+0 when ... < ... is false |
| 109 | y >= 0+0 when ... \|\| ... is false |
astGuardsControl
| test.c:7:9:7:13 | ... > ... | false | 10 | 11 |
| test.c:7:9:7:13 | ... > ... | true | 7 | 9 |
| test.c:17:8:17:12 | ... < ... | true | 17 | 17 |
| test.c:17:8:17:12 | ... < ... | true | 18 | 18 |
| test.c:17:8:17:21 | ... && ... | true | 18 | 18 |
| test.c:17:17:17:21 | ... > ... | true | 18 | 18 |
| test.c:26:11:26:15 | ... > ... | false | 2 | 2 |
| test.c:26:11:26:15 | ... > ... | false | 31 | 34 |
| test.c:26:11:26:15 | ... > ... | false | 34 | 34 |
| test.c:26:11:26:15 | ... > ... | false | 39 | 42 |
| test.c:26:11:26:15 | ... > ... | false | 42 | 42 |
| test.c:26:11:26:15 | ... > ... | false | 42 | 44 |
| test.c:26:11:26:15 | ... > ... | false | 45 | 45 |
| test.c:26:11:26:15 | ... > ... | false | 45 | 47 |
| test.c:26:11:26:15 | ... > ... | false | 48 | 55 |
| test.c:26:11:26:15 | ... > ... | false | 51 | 53 |
| test.c:26:11:26:15 | ... > ... | false | 56 | 58 |
| test.c:26:11:26:15 | ... > ... | false | 58 | 58 |
| test.c:26:11:26:15 | ... > ... | false | 58 | 66 |
| test.c:26:11:26:15 | ... > ... | false | 62 | 62 |
| test.c:26:11:26:15 | ... > ... | true | 26 | 28 |
| test.c:34:16:34:21 | ... < ... | false | 2 | 2 |
| test.c:34:16:34:21 | ... < ... | false | 39 | 42 |
| test.c:34:16:34:21 | ... < ... | false | 42 | 42 |
| test.c:34:16:34:21 | ... < ... | false | 42 | 44 |
| test.c:34:16:34:21 | ... < ... | false | 45 | 45 |
| test.c:34:16:34:21 | ... < ... | false | 45 | 47 |
| test.c:34:16:34:21 | ... < ... | false | 48 | 55 |
| test.c:34:16:34:21 | ... < ... | false | 51 | 53 |
| test.c:34:16:34:21 | ... < ... | false | 56 | 58 |
| test.c:34:16:34:21 | ... < ... | false | 58 | 58 |
| test.c:34:16:34:21 | ... < ... | false | 58 | 66 |
| test.c:34:16:34:21 | ... < ... | false | 62 | 62 |
| test.c:34:16:34:21 | ... < ... | true | 34 | 34 |
| test.c:42:16:42:21 | ... < ... | true | 42 | 42 |
| test.c:42:16:42:21 | ... < ... | true | 42 | 44 |
| test.c:42:16:42:21 | ... < ... | true | 45 | 45 |
| test.c:42:16:42:21 | ... < ... | true | 45 | 47 |
| test.c:42:16:42:21 | ... < ... | true | 48 | 55 |
| test.c:42:16:42:21 | ... < ... | true | 51 | 53 |
| test.c:44:12:44:16 | ... > ... | false | 51 | 53 |
| test.c:44:12:44:16 | ... > ... | true | 45 | 45 |
| test.c:44:12:44:16 | ... > ... | true | 45 | 47 |
| test.c:44:12:44:16 | ... > ... | true | 48 | 55 |
| test.c:45:16:45:20 | ... > ... | false | 48 | 55 |
| test.c:45:16:45:20 | ... > ... | true | 45 | 47 |
| test.c:58:9:58:14 | ... == ... | false | 58 | 58 |
| test.c:58:9:58:14 | ... == ... | false | 62 | 62 |
| test.c:58:9:58:23 | ... \|\| ... | false | 62 | 62 |
| test.c:58:19:58:23 | ... < ... | false | 62 | 62 |
| test.c:75:9:75:14 | ... == ... | false | 78 | 79 |
| test.c:75:9:75:14 | ... == ... | true | 75 | 77 |
| test.c:85:8:85:13 | ... == ... | true | 85 | 85 |
| test.c:85:8:85:13 | ... == ... | true | 86 | 86 |
| test.c:85:8:85:23 | ... && ... | true | 86 | 86 |
| test.c:85:18:85:23 | ... != ... | true | 86 | 86 |
| test.c:94:11:94:16 | ... != ... | false | 70 | 70 |
| test.c:94:11:94:16 | ... != ... | false | 99 | 102 |
| test.c:94:11:94:16 | ... != ... | false | 102 | 102 |
| test.c:94:11:94:16 | ... != ... | false | 107 | 109 |
| test.c:94:11:94:16 | ... != ... | false | 109 | 109 |
| test.c:94:11:94:16 | ... != ... | false | 109 | 117 |
| test.c:94:11:94:16 | ... != ... | false | 113 | 113 |
| test.c:94:11:94:16 | ... != ... | true | 94 | 96 |
| test.c:102:16:102:21 | ... < ... | false | 70 | 70 |
| test.c:102:16:102:21 | ... < ... | false | 107 | 109 |
| test.c:102:16:102:21 | ... < ... | false | 109 | 109 |
| test.c:102:16:102:21 | ... < ... | false | 109 | 117 |
| test.c:102:16:102:21 | ... < ... | false | 113 | 113 |
| test.c:102:16:102:21 | ... < ... | true | 102 | 102 |
| test.c:109:9:109:14 | ... == ... | false | 109 | 109 |
| test.c:109:9:109:14 | ... == ... | false | 113 | 113 |
| test.c:109:9:109:23 | ... \|\| ... | false | 113 | 113 |
| test.c:109:19:109:23 | ... < ... | false | 113 | 113 |
| test.c:126:7:126:7 | 1 | true | 126 | 126 |
| test.c:126:7:126:7 | 1 | true | 126 | 128 |
| test.c:126:7:126:28 | ... && ... | true | 126 | 128 |
| test.c:126:12:126:26 | call to test3_condition | true | 126 | 128 |
| test.c:131:7:131:7 | b | true | 131 | 132 |
| test.c:137:7:137:7 | 0 | true | 137 | 138 |
| test.c:137:7:137:7 | 0 | true | 138 | 139 |
| test.c:138:9:138:9 | i | true | 138 | 139 |
| test.c:146:7:146:8 | ! ... | true | 146 | 147 |
| test.c:146:8:146:8 | x | false | 146 | 147 |
| test.c:152:10:152:10 | x | true | 151 | 152 |
| test.c:152:10:152:10 | x | true | 152 | 152 |
| test.c:152:10:152:15 | ... && ... | true | 151 | 152 |
| test.c:152:15:152:15 | y | true | 151 | 152 |
| test.cpp:18:8:18:10 | call to get | true | 19 | 19 |
| test.cpp:31:7:31:13 | ... == ... | false | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | false | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | true | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | true | 31 | 32 |
| test.cpp:42:13:42:20 | call to getABool | false | 53 | 53 |
| test.cpp:42:13:42:20 | call to getABool | true | 43 | 45 |
astGuardsEnsure
| test.c:7:9:7:13 | ... > ... | test.c:7:9:7:9 | x | < | test.c:7:13:7:13 | 0 | 1 | 10 | 11 |
| test.c:7:9:7:13 | ... > ... | test.c:7:9:7:9 | x | >= | test.c:7:13:7:13 | 0 | 1 | 7 | 9 |
| test.c:7:9:7:13 | ... > ... | test.c:7:13:7:13 | 0 | < | test.c:7:9:7:9 | x | 0 | 7 | 9 |
| test.c:7:9:7:13 | ... > ... | test.c:7:13:7:13 | 0 | >= | test.c:7:9:7:9 | x | 0 | 10 | 11 |
| test.c:17:8:17:12 | ... < ... | test.c:17:8:17:8 | x | < | test.c:17:12:17:12 | 0 | 0 | 17 | 17 |
| test.c:17:8:17:12 | ... < ... | test.c:17:8:17:8 | x | < | test.c:17:12:17:12 | 0 | 0 | 18 | 18 |
| test.c:17:8:17:12 | ... < ... | test.c:17:12:17:12 | 0 | >= | test.c:17:8:17:8 | x | 1 | 17 | 17 |
| test.c:17:8:17:12 | ... < ... | test.c:17:12:17:12 | 0 | >= | test.c:17:8:17:8 | x | 1 | 18 | 18 |
| test.c:17:8:17:21 | ... && ... | test.c:17:8:17:8 | x | < | test.c:17:12:17:12 | 0 | 0 | 18 | 18 |
| test.c:17:8:17:21 | ... && ... | test.c:17:12:17:12 | 0 | >= | test.c:17:8:17:8 | x | 1 | 18 | 18 |
| test.c:17:8:17:21 | ... && ... | test.c:17:17:17:17 | y | >= | test.c:17:21:17:21 | 1 | 1 | 18 | 18 |
| test.c:17:8:17:21 | ... && ... | test.c:17:21:17:21 | 1 | < | test.c:17:17:17:17 | y | 0 | 18 | 18 |
| test.c:17:17:17:21 | ... > ... | test.c:17:17:17:17 | y | >= | test.c:17:21:17:21 | 1 | 1 | 18 | 18 |
| test.c:17:17:17:21 | ... > ... | test.c:17:21:17:21 | 1 | < | test.c:17:17:17:17 | y | 0 | 18 | 18 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 2 | 2 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 31 | 34 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 34 | 34 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 39 | 42 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 42 | 42 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 42 | 44 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 45 | 45 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 45 | 47 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 48 | 55 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 51 | 53 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 56 | 58 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 58 | 58 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 58 | 66 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 62 | 62 |
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | >= | test.c:26:15:26:15 | 0 | 1 | 26 | 28 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | < | test.c:26:11:26:11 | x | 0 | 26 | 28 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 2 | 2 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 31 | 34 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 34 | 34 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 39 | 42 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 42 | 42 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 42 | 44 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 45 | 45 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 45 | 47 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 48 | 55 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 51 | 53 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 56 | 58 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 58 | 58 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 58 | 66 |
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 62 | 62 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | < | test.c:34:20:34:21 | 10 | 0 | 34 | 34 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 2 | 2 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 39 | 42 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 42 | 42 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 42 | 44 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 45 | 45 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 45 | 47 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 48 | 55 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 51 | 53 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 56 | 58 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 58 | 58 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 58 | 66 |
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 62 | 62 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 2 | 2 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 39 | 42 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 42 | 42 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 42 | 44 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 45 | 45 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 45 | 47 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 48 | 55 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 51 | 53 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 56 | 58 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 58 | 58 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 58 | 66 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 62 | 62 |
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | >= | test.c:34:16:34:16 | j | 1 | 34 | 34 |
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | test.c:42:20:42:21 | 10 | 0 | 42 | 42 |
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | test.c:42:20:42:21 | 10 | 0 | 42 | 44 |
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | test.c:42:20:42:21 | 10 | 0 | 45 | 45 |
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | test.c:42:20:42:21 | 10 | 0 | 45 | 47 |
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | test.c:42:20:42:21 | 10 | 0 | 48 | 55 |
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | test.c:42:20:42:21 | 10 | 0 | 51 | 53 |
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 42 | 42 |
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 42 | 44 |
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 45 | 45 |
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 45 | 47 |
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 48 | 55 |
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 51 | 53 |
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | < | test.c:44:16:44:16 | 0 | 1 | 51 | 53 |
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | >= | test.c:44:16:44:16 | 0 | 1 | 45 | 45 |
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | >= | test.c:44:16:44:16 | 0 | 1 | 45 | 47 |
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | >= | test.c:44:16:44:16 | 0 | 1 | 48 | 55 |
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | < | test.c:44:12:44:12 | z | 0 | 45 | 45 |
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | < | test.c:44:12:44:12 | z | 0 | 45 | 47 |
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | < | test.c:44:12:44:12 | z | 0 | 48 | 55 |
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | >= | test.c:44:12:44:12 | z | 0 | 51 | 53 |
| test.c:45:16:45:20 | ... > ... | test.c:45:16:45:16 | y | < | test.c:45:20:45:20 | 0 | 1 | 48 | 55 |
| test.c:45:16:45:20 | ... > ... | test.c:45:16:45:16 | y | >= | test.c:45:20:45:20 | 0 | 1 | 45 | 47 |
| test.c:45:16:45:20 | ... > ... | test.c:45:20:45:20 | 0 | < | test.c:45:16:45:16 | y | 0 | 45 | 47 |
| test.c:45:16:45:20 | ... > ... | test.c:45:20:45:20 | 0 | >= | test.c:45:16:45:16 | y | 0 | 48 | 55 |
| test.c:58:9:58:14 | ... == ... | test.c:58:9:58:9 | x | != | test.c:58:14:58:14 | 0 | 0 | 58 | 58 |
| test.c:58:9:58:14 | ... == ... | test.c:58:9:58:9 | x | != | test.c:58:14:58:14 | 0 | 0 | 62 | 62 |
| test.c:58:9:58:14 | ... == ... | test.c:58:14:58:14 | 0 | != | test.c:58:9:58:9 | x | 0 | 58 | 58 |
| test.c:58:9:58:14 | ... == ... | test.c:58:14:58:14 | 0 | != | test.c:58:9:58:9 | x | 0 | 62 | 62 |
| test.c:58:9:58:23 | ... \|\| ... | test.c:58:9:58:9 | x | != | test.c:58:14:58:14 | 0 | 0 | 62 | 62 |
| test.c:58:9:58:23 | ... \|\| ... | test.c:58:14:58:14 | 0 | != | test.c:58:9:58:9 | x | 0 | 62 | 62 |
| test.c:58:9:58:23 | ... \|\| ... | test.c:58:19:58:19 | y | >= | test.c:58:23:58:23 | 0 | 0 | 62 | 62 |
| test.c:58:9:58:23 | ... \|\| ... | test.c:58:23:58:23 | 0 | < | test.c:58:19:58:19 | y | 1 | 62 | 62 |
| test.c:58:19:58:23 | ... < ... | test.c:58:19:58:19 | y | >= | test.c:58:23:58:23 | 0 | 0 | 62 | 62 |
| test.c:58:19:58:23 | ... < ... | test.c:58:23:58:23 | 0 | < | test.c:58:19:58:19 | y | 1 | 62 | 62 |
| test.c:75:9:75:14 | ... == ... | test.c:75:9:75:9 | x | != | test.c:75:14:75:14 | 0 | 0 | 78 | 79 |
| test.c:75:9:75:14 | ... == ... | test.c:75:9:75:9 | x | == | test.c:75:14:75:14 | 0 | 0 | 75 | 77 |
| test.c:75:9:75:14 | ... == ... | test.c:75:14:75:14 | 0 | != | test.c:75:9:75:9 | x | 0 | 78 | 79 |
| test.c:75:9:75:14 | ... == ... | test.c:75:14:75:14 | 0 | == | test.c:75:9:75:9 | x | 0 | 75 | 77 |
| test.c:85:8:85:13 | ... == ... | test.c:85:8:85:8 | x | == | test.c:85:13:85:13 | 0 | 0 | 85 | 85 |
| test.c:85:8:85:13 | ... == ... | test.c:85:8:85:8 | x | == | test.c:85:13:85:13 | 0 | 0 | 86 | 86 |
| test.c:85:8:85:13 | ... == ... | test.c:85:13:85:13 | 0 | == | test.c:85:8:85:8 | x | 0 | 85 | 85 |
| test.c:85:8:85:13 | ... == ... | test.c:85:13:85:13 | 0 | == | test.c:85:8:85:8 | x | 0 | 86 | 86 |
| test.c:85:8:85:23 | ... && ... | test.c:85:8:85:8 | x | == | test.c:85:13:85:13 | 0 | 0 | 86 | 86 |
| test.c:85:8:85:23 | ... && ... | test.c:85:13:85:13 | 0 | == | test.c:85:8:85:8 | x | 0 | 86 | 86 |
| test.c:85:8:85:23 | ... && ... | test.c:85:18:85:18 | y | != | test.c:85:23:85:23 | 0 | 0 | 86 | 86 |
| test.c:85:8:85:23 | ... && ... | test.c:85:23:85:23 | 0 | != | test.c:85:18:85:18 | y | 0 | 86 | 86 |
| test.c:85:18:85:23 | ... != ... | test.c:85:18:85:18 | y | != | test.c:85:23:85:23 | 0 | 0 | 86 | 86 |
| test.c:85:18:85:23 | ... != ... | test.c:85:23:85:23 | 0 | != | test.c:85:18:85:18 | y | 0 | 86 | 86 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | != | test.c:94:16:94:16 | 0 | 0 | 94 | 96 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | test.c:94:16:94:16 | 0 | 0 | 70 | 70 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | test.c:94:16:94:16 | 0 | 0 | 99 | 102 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | test.c:94:16:94:16 | 0 | 0 | 102 | 102 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | test.c:94:16:94:16 | 0 | 0 | 107 | 109 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | test.c:94:16:94:16 | 0 | 0 | 109 | 109 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | test.c:94:16:94:16 | 0 | 0 | 109 | 117 |
| test.c:94:11:94:16 | ... != ... | test.c:94:11:94:11 | x | == | test.c:94:16:94:16 | 0 | 0 | 113 | 113 |
| test.c:94:11:94:16 | ... != ... | test.c:94:16:94:16 | 0 | != | test.c:94:11:94:11 | x | 0 | 94 | 96 |
| test.c:94:11:94:16 | ... != ... | test.c:94:16:94:16 | 0 | == | test.c:94:11:94:11 | x | 0 | 70 | 70 |
| test.c:94:11:94:16 | ... != ... | test.c:94:16:94:16 | 0 | == | test.c:94:11:94:11 | x | 0 | 99 | 102 |
| test.c:94:11:94:16 | ... != ... | test.c:94:16:94:16 | 0 | == | test.c:94:11:94:11 | x | 0 | 102 | 102 |
| test.c:94:11:94:16 | ... != ... | test.c:94:16:94:16 | 0 | == | test.c:94:11:94:11 | x | 0 | 107 | 109 |
| test.c:94:11:94:16 | ... != ... | test.c:94:16:94:16 | 0 | == | test.c:94:11:94:11 | x | 0 | 109 | 109 |
| test.c:94:11:94:16 | ... != ... | test.c:94:16:94:16 | 0 | == | test.c:94:11:94:11 | x | 0 | 109 | 117 |
| test.c:94:11:94:16 | ... != ... | test.c:94:16:94:16 | 0 | == | test.c:94:11:94:11 | x | 0 | 113 | 113 |
| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | < | test.c:102:20:102:21 | 10 | 0 | 102 | 102 |
| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | test.c:102:20:102:21 | 10 | 0 | 70 | 70 |
| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | test.c:102:20:102:21 | 10 | 0 | 107 | 109 |
| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | test.c:102:20:102:21 | 10 | 0 | 109 | 109 |
| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | test.c:102:20:102:21 | 10 | 0 | 109 | 117 |
| test.c:102:16:102:21 | ... < ... | test.c:102:16:102:16 | j | >= | test.c:102:20:102:21 | 10 | 0 | 113 | 113 |
| test.c:102:16:102:21 | ... < ... | test.c:102:20:102:21 | 10 | < | test.c:102:16:102:16 | j | 1 | 70 | 70 |
| test.c:102:16:102:21 | ... < ... | test.c:102:20:102:21 | 10 | < | test.c:102:16:102:16 | j | 1 | 107 | 109 |
| test.c:102:16:102:21 | ... < ... | test.c:102:20:102:21 | 10 | < | test.c:102:16:102:16 | j | 1 | 109 | 109 |
| test.c:102:16:102:21 | ... < ... | test.c:102:20:102:21 | 10 | < | test.c:102:16:102:16 | j | 1 | 109 | 117 |
| test.c:102:16:102:21 | ... < ... | test.c:102:20:102:21 | 10 | < | test.c:102:16:102:16 | j | 1 | 113 | 113 |
| test.c:102:16:102:21 | ... < ... | test.c:102:20:102:21 | 10 | >= | test.c:102:16:102:16 | j | 1 | 102 | 102 |
| test.c:109:9:109:14 | ... == ... | test.c:109:9:109:9 | x | != | test.c:109:14:109:14 | 0 | 0 | 109 | 109 |
| test.c:109:9:109:14 | ... == ... | test.c:109:9:109:9 | x | != | test.c:109:14:109:14 | 0 | 0 | 113 | 113 |
| test.c:109:9:109:14 | ... == ... | test.c:109:14:109:14 | 0 | != | test.c:109:9:109:9 | x | 0 | 109 | 109 |
| test.c:109:9:109:14 | ... == ... | test.c:109:14:109:14 | 0 | != | test.c:109:9:109:9 | x | 0 | 113 | 113 |
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:9:109:9 | x | != | test.c:109:14:109:14 | 0 | 0 | 113 | 113 |
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:14:109:14 | 0 | != | test.c:109:9:109:9 | x | 0 | 113 | 113 |
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:19:109:19 | y | >= | test.c:109:23:109:23 | 0 | 0 | 113 | 113 |
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:23:109:23 | 0 | < | test.c:109:19:109:19 | y | 1 | 113 | 113 |
| test.c:109:19:109:23 | ... < ... | test.c:109:19:109:19 | y | >= | test.c:109:23:109:23 | 0 | 0 | 113 | 113 |
| test.c:109:19:109:23 | ... < ... | test.c:109:23:109:23 | 0 | < | test.c:109:19:109:19 | y | 1 | 113 | 113 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | test.cpp:31:12:31:13 | - ... | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | test.cpp:31:12:31:13 | - ... | 0 | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | test.cpp:31:12:31:13 | - ... | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | test.cpp:31:12:31:13 | - ... | 0 | 31 | 32 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | != | test.cpp:31:7:31:7 | x | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | != | test.cpp:31:7:31:7 | x | 0 | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | == | test.cpp:31:7:31:7 | x | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | == | test.cpp:31:7:31:7 | x | 0 | 31 | 32 |
irGuards
| test.c:7:9:7:13 | CompareGT: ... > ... |
| test.c:17:8:17:12 | CompareLT: ... < ... |
| test.c:17:17:17:21 | CompareGT: ... > ... |
| test.c:26:11:26:15 | CompareGT: ... > ... |
| test.c:34:16:34:21 | CompareLT: ... < ... |
| test.c:42:16:42:21 | CompareLT: ... < ... |
| test.c:44:12:44:16 | CompareGT: ... > ... |
| test.c:45:16:45:20 | CompareGT: ... > ... |
| test.c:58:9:58:14 | CompareEQ: ... == ... |
| test.c:58:19:58:23 | CompareLT: ... < ... |
| test.c:75:9:75:14 | CompareEQ: ... == ... |
| test.c:85:8:85:13 | CompareEQ: ... == ... |
| test.c:85:18:85:23 | CompareNE: ... != ... |
| test.c:94:11:94:16 | CompareNE: ... != ... |
| test.c:102:16:102:21 | CompareLT: ... < ... |
| test.c:109:9:109:14 | CompareEQ: ... == ... |
| test.c:109:19:109:23 | CompareLT: ... < ... |
| test.c:126:7:126:7 | Constant: 1 |
| test.c:126:12:126:26 | Call: call to test3_condition |
| test.c:131:7:131:7 | Load: b |
| test.c:137:7:137:7 | Constant: 0 |
| test.c:138:9:138:9 | Load: i |
| test.c:146:8:146:8 | Load: x |
| test.c:152:10:152:10 | Load: x |
| test.c:152:15:152:15 | Load: y |
| test.cpp:18:8:18:12 | CompareNE: (bool)... |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... |
| test.cpp:42:13:42:20 | Call: call to getABool |
irGuardsCompare
| 7 | 0 < x+0 when CompareGT: ... > ... is true |
| 7 | 0 >= x+0 when CompareGT: ... > ... is false |
| 7 | x < 0+1 when CompareGT: ... > ... is false |
| 7 | x >= 0+1 when CompareGT: ... > ... is true |
| 17 | 0 < x+1 when CompareLT: ... < ... is false |
| 17 | 0 >= x+1 when CompareLT: ... < ... is true |
| 17 | 1 < y+0 when CompareGT: ... > ... is true |
| 17 | 1 >= y+0 when CompareGT: ... > ... is false |
| 17 | x < 0+0 when CompareLT: ... < ... is true |
| 17 | x >= 0+0 when CompareLT: ... < ... is false |
| 17 | y < 1+1 when CompareGT: ... > ... is false |
| 17 | y >= 1+1 when CompareGT: ... > ... is true |
| 26 | 0 < x+0 when CompareGT: ... > ... is true |
| 26 | 0 >= x+0 when CompareGT: ... > ... is false |
| 26 | x < 0+1 when CompareGT: ... > ... is false |
| 26 | x >= 0+1 when CompareGT: ... > ... is true |
| 31 | - ... != x+0 when CompareEQ: ... == ... is false |
| 31 | - ... == x+0 when CompareEQ: ... == ... is true |
| 31 | x != - ...+0 when CompareEQ: ... == ... is false |
| 31 | x == - ...+0 when CompareEQ: ... == ... is true |
| 34 | 10 < j+1 when CompareLT: ... < ... is false |
| 34 | 10 >= j+1 when CompareLT: ... < ... is true |
| 34 | j < 10+0 when CompareLT: ... < ... is true |
| 34 | j >= 10+0 when CompareLT: ... < ... is false |
| 42 | 10 < j+1 when CompareLT: ... < ... is false |
| 42 | 10 >= j+1 when CompareLT: ... < ... is true |
| 42 | j < 10+0 when CompareLT: ... < ... is true |
| 42 | j >= 10+0 when CompareLT: ... < ... is false |
| 44 | 0 < z+0 when CompareGT: ... > ... is true |
| 44 | 0 >= z+0 when CompareGT: ... > ... is false |
| 44 | z < 0+1 when CompareGT: ... > ... is false |
| 44 | z >= 0+1 when CompareGT: ... > ... is true |
| 45 | 0 < y+0 when CompareGT: ... > ... is true |
| 45 | 0 >= y+0 when CompareGT: ... > ... is false |
| 45 | y < 0+1 when CompareGT: ... > ... is false |
| 45 | y >= 0+1 when CompareGT: ... > ... is true |
| 58 | 0 != x+0 when CompareEQ: ... == ... is false |
| 58 | 0 < y+1 when CompareLT: ... < ... is false |
| 58 | 0 == x+0 when CompareEQ: ... == ... is true |
| 58 | 0 >= y+1 when CompareLT: ... < ... is true |
| 58 | x != 0+0 when CompareEQ: ... == ... is false |
| 58 | x == 0+0 when CompareEQ: ... == ... is true |
| 58 | y < 0+0 when CompareLT: ... < ... is true |
| 58 | y >= 0+0 when CompareLT: ... < ... is false |
| 75 | 0 != x+0 when CompareEQ: ... == ... is false |
| 75 | 0 == x+0 when CompareEQ: ... == ... is true |
| 75 | x != 0+0 when CompareEQ: ... == ... is false |
| 75 | x == 0+0 when CompareEQ: ... == ... is true |
| 85 | 0 != x+0 when CompareEQ: ... == ... is false |
| 85 | 0 != y+0 when CompareNE: ... != ... is true |
| 85 | 0 == x+0 when CompareEQ: ... == ... is true |
| 85 | 0 == y+0 when CompareNE: ... != ... is false |
| 85 | x != 0+0 when CompareEQ: ... == ... is false |
| 85 | x == 0+0 when CompareEQ: ... == ... is true |
| 85 | y != 0+0 when CompareNE: ... != ... is true |
| 85 | y == 0+0 when CompareNE: ... != ... is false |
| 94 | 0 != x+0 when CompareNE: ... != ... is true |
| 94 | 0 == x+0 when CompareNE: ... != ... is false |
| 94 | x != 0+0 when CompareNE: ... != ... is true |
| 94 | x == 0+0 when CompareNE: ... != ... is false |
| 102 | 10 < j+1 when CompareLT: ... < ... is false |
| 102 | 10 >= j+1 when CompareLT: ... < ... is true |
| 102 | j < 10+0 when CompareLT: ... < ... is true |
| 102 | j >= 10+0 when CompareLT: ... < ... is false |
| 109 | 0 != x+0 when CompareEQ: ... == ... is false |
| 109 | 0 < y+1 when CompareLT: ... < ... is false |
| 109 | 0 == x+0 when CompareEQ: ... == ... is true |
| 109 | 0 >= y+1 when CompareLT: ... < ... is true |
| 109 | x != 0+0 when CompareEQ: ... == ... is false |
| 109 | x == 0+0 when CompareEQ: ... == ... is true |
| 109 | y < 0+0 when CompareLT: ... < ... is true |
| 109 | y >= 0+0 when CompareLT: ... < ... is false |
irGuardsControl
| test.c:7:9:7:13 | CompareGT: ... > ... | false | 11 | 11 |
| test.c:7:9:7:13 | CompareGT: ... > ... | true | 8 | 8 |
| test.c:17:8:17:12 | CompareLT: ... < ... | true | 17 | 17 |
| test.c:17:8:17:12 | CompareLT: ... < ... | true | 18 | 18 |
| test.c:17:17:17:21 | CompareGT: ... > ... | true | 18 | 18 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 2 | 2 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 31 | 31 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 34 | 34 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 35 | 35 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 39 | 39 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 42 | 42 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 43 | 43 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 45 | 45 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 46 | 46 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 49 | 49 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 52 | 52 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 56 | 56 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 58 | 58 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 59 | 59 |
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 62 | 62 |
| test.c:26:11:26:15 | CompareGT: ... > ... | true | 27 | 27 |
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 2 | 2 |
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 39 | 39 |
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 42 | 42 |
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 43 | 43 |
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 45 | 45 |
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 46 | 46 |
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 49 | 49 |
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 52 | 52 |
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 56 | 56 |
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 58 | 58 |
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 59 | 59 |
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 62 | 62 |
| test.c:34:16:34:21 | CompareLT: ... < ... | true | 35 | 35 |
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 42 | 42 |
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 43 | 43 |
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 45 | 45 |
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 46 | 46 |
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 49 | 49 |
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 52 | 52 |
| test.c:44:12:44:16 | CompareGT: ... > ... | false | 52 | 52 |
| test.c:44:12:44:16 | CompareGT: ... > ... | true | 45 | 45 |
| test.c:44:12:44:16 | CompareGT: ... > ... | true | 46 | 46 |
| test.c:44:12:44:16 | CompareGT: ... > ... | true | 49 | 49 |
| test.c:45:16:45:20 | CompareGT: ... > ... | false | 49 | 49 |
| test.c:45:16:45:20 | CompareGT: ... > ... | true | 46 | 46 |
| test.c:58:9:58:14 | CompareEQ: ... == ... | false | 58 | 58 |
| test.c:58:9:58:14 | CompareEQ: ... == ... | false | 62 | 62 |
| test.c:58:19:58:23 | CompareLT: ... < ... | false | 62 | 62 |
| test.c:75:9:75:14 | CompareEQ: ... == ... | false | 79 | 79 |
| test.c:75:9:75:14 | CompareEQ: ... == ... | true | 76 | 76 |
| test.c:85:8:85:13 | CompareEQ: ... == ... | true | 85 | 85 |
| test.c:85:8:85:13 | CompareEQ: ... == ... | true | 86 | 86 |
| test.c:85:18:85:23 | CompareNE: ... != ... | true | 86 | 86 |
| test.c:94:11:94:16 | CompareNE: ... != ... | false | 70 | 70 |
| test.c:94:11:94:16 | CompareNE: ... != ... | false | 99 | 99 |
| test.c:94:11:94:16 | CompareNE: ... != ... | false | 102 | 102 |
| test.c:94:11:94:16 | CompareNE: ... != ... | false | 103 | 103 |
| test.c:94:11:94:16 | CompareNE: ... != ... | false | 107 | 107 |
| test.c:94:11:94:16 | CompareNE: ... != ... | false | 109 | 109 |
| test.c:94:11:94:16 | CompareNE: ... != ... | false | 110 | 110 |
| test.c:94:11:94:16 | CompareNE: ... != ... | false | 113 | 113 |
| test.c:94:11:94:16 | CompareNE: ... != ... | true | 95 | 95 |
| test.c:102:16:102:21 | CompareLT: ... < ... | false | 70 | 70 |
| test.c:102:16:102:21 | CompareLT: ... < ... | false | 107 | 107 |
| test.c:102:16:102:21 | CompareLT: ... < ... | false | 109 | 109 |
| test.c:102:16:102:21 | CompareLT: ... < ... | false | 110 | 110 |
| test.c:102:16:102:21 | CompareLT: ... < ... | false | 113 | 113 |
| test.c:102:16:102:21 | CompareLT: ... < ... | true | 103 | 103 |
| test.c:109:9:109:14 | CompareEQ: ... == ... | false | 109 | 109 |
| test.c:109:9:109:14 | CompareEQ: ... == ... | false | 113 | 113 |
| test.c:109:19:109:23 | CompareLT: ... < ... | false | 113 | 113 |
| test.c:126:7:126:7 | Constant: 1 | true | 126 | 126 |
| test.c:126:7:126:7 | Constant: 1 | true | 127 | 127 |
| test.c:126:12:126:26 | Call: call to test3_condition | true | 127 | 127 |
| test.c:131:7:131:7 | Load: b | true | 132 | 132 |
| test.c:137:7:137:7 | Constant: 0 | true | 138 | 138 |
| test.c:137:7:137:7 | Constant: 0 | true | 139 | 139 |
| test.c:138:9:138:9 | Load: i | true | 139 | 139 |
| test.c:146:8:146:8 | Load: x | false | 147 | 147 |
| test.c:152:10:152:10 | Load: x | true | 152 | 152 |
| test.c:152:15:152:15 | Load: y | true | 152 | 152 |
| test.cpp:18:8:18:12 | CompareNE: (bool)... | true | 0 | 0 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | false | 34 | 34 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | true | 30 | 30 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | true | 32 | 32 |
| test.cpp:42:13:42:20 | Call: call to getABool | false | 53 | 53 |
| test.cpp:42:13:42:20 | Call: call to getABool | true | 44 | 44 |
irGuardsEnsure
| test.c:7:9:7:13 | CompareGT: ... > ... | test.c:7:9:7:9 | Load: x | < | test.c:7:13:7:13 | Constant: 0 | 1 | 11 | 11 |
| test.c:7:9:7:13 | CompareGT: ... > ... | test.c:7:9:7:9 | Load: x | >= | test.c:7:13:7:13 | Constant: 0 | 1 | 8 | 8 |
| test.c:7:9:7:13 | CompareGT: ... > ... | test.c:7:13:7:13 | Constant: 0 | < | test.c:7:9:7:9 | Load: x | 0 | 8 | 8 |
| test.c:7:9:7:13 | CompareGT: ... > ... | test.c:7:13:7:13 | Constant: 0 | >= | test.c:7:9:7:9 | Load: x | 0 | 11 | 11 |
| test.c:17:8:17:12 | CompareLT: ... < ... | test.c:17:8:17:8 | Load: x | < | test.c:17:12:17:12 | Constant: 0 | 0 | 17 | 17 |
| test.c:17:8:17:12 | CompareLT: ... < ... | test.c:17:8:17:8 | Load: x | < | test.c:17:12:17:12 | Constant: 0 | 0 | 18 | 18 |
| test.c:17:8:17:12 | CompareLT: ... < ... | test.c:17:12:17:12 | Constant: 0 | >= | test.c:17:8:17:8 | Load: x | 1 | 17 | 17 |
| test.c:17:8:17:12 | CompareLT: ... < ... | test.c:17:12:17:12 | Constant: 0 | >= | test.c:17:8:17:8 | Load: x | 1 | 18 | 18 |
| test.c:17:17:17:21 | CompareGT: ... > ... | test.c:17:17:17:17 | Load: y | >= | test.c:17:21:17:21 | Constant: (long)... | 1 | 18 | 18 |
| test.c:17:17:17:21 | CompareGT: ... > ... | test.c:17:21:17:21 | Constant: (long)... | < | test.c:17:17:17:17 | Load: y | 0 | 18 | 18 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 2 | 2 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 31 | 31 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 34 | 34 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 35 | 35 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 39 | 39 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 42 | 42 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 43 | 43 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 45 | 45 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 46 | 46 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 49 | 49 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 52 | 52 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 56 | 56 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 58 | 58 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 59 | 59 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 62 | 62 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | >= | test.c:26:15:26:15 | Constant: 0 | 1 | 27 | 27 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | < | test.c:26:11:26:11 | Load: x | 0 | 27 | 27 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 2 | 2 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 31 | 31 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 34 | 34 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 35 | 35 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 39 | 39 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 42 | 42 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 43 | 43 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 45 | 45 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 46 | 46 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 49 | 49 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 52 | 52 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 56 | 56 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 58 | 58 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 59 | 59 |
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 62 | 62 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | < | test.c:34:20:34:21 | Constant: 10 | 0 | 35 | 35 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 2 | 2 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 39 | 39 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 42 | 42 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 43 | 43 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 45 | 45 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 46 | 46 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 49 | 49 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 52 | 52 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 56 | 56 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 58 | 58 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 59 | 59 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 62 | 62 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 2 | 2 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 39 | 39 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 42 | 42 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 43 | 43 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 45 | 45 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 46 | 46 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 49 | 49 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 52 | 52 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 56 | 56 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 58 | 58 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 59 | 59 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 62 | 62 |
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | >= | test.c:34:16:34:16 | Load: j | 1 | 35 | 35 |
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 42 | 42 |
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 43 | 43 |
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 45 | 45 |
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 46 | 46 |
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 49 | 49 |
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 52 | 52 |
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 42 | 42 |
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 43 | 43 |
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 45 | 45 |
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 46 | 46 |
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 49 | 49 |
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 52 | 52 |
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:12:44:12 | Load: z | < | test.c:44:16:44:16 | Constant: 0 | 1 | 52 | 52 |
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:12:44:12 | Load: z | >= | test.c:44:16:44:16 | Constant: 0 | 1 | 45 | 45 |
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:12:44:12 | Load: z | >= | test.c:44:16:44:16 | Constant: 0 | 1 | 46 | 46 |
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:12:44:12 | Load: z | >= | test.c:44:16:44:16 | Constant: 0 | 1 | 49 | 49 |
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:16:44:16 | Constant: 0 | < | test.c:44:12:44:12 | Load: z | 0 | 45 | 45 |
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:16:44:16 | Constant: 0 | < | test.c:44:12:44:12 | Load: z | 0 | 46 | 46 |
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:16:44:16 | Constant: 0 | < | test.c:44:12:44:12 | Load: z | 0 | 49 | 49 |
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:16:44:16 | Constant: 0 | >= | test.c:44:12:44:12 | Load: z | 0 | 52 | 52 |
| test.c:45:16:45:20 | CompareGT: ... > ... | test.c:45:16:45:16 | Load: y | < | test.c:45:20:45:20 | Constant: (long)... | 1 | 49 | 49 |
| test.c:45:16:45:20 | CompareGT: ... > ... | test.c:45:16:45:16 | Load: y | >= | test.c:45:20:45:20 | Constant: (long)... | 1 | 46 | 46 |
| test.c:45:16:45:20 | CompareGT: ... > ... | test.c:45:20:45:20 | Constant: (long)... | < | test.c:45:16:45:16 | Load: y | 0 | 46 | 46 |
| test.c:45:16:45:20 | CompareGT: ... > ... | test.c:45:20:45:20 | Constant: (long)... | >= | test.c:45:16:45:16 | Load: y | 0 | 49 | 49 |
| test.c:58:9:58:14 | CompareEQ: ... == ... | test.c:58:9:58:9 | Load: x | != | test.c:58:14:58:14 | Constant: 0 | 0 | 58 | 58 |
| test.c:58:9:58:14 | CompareEQ: ... == ... | test.c:58:9:58:9 | Load: x | != | test.c:58:14:58:14 | Constant: 0 | 0 | 62 | 62 |
| test.c:58:9:58:14 | CompareEQ: ... == ... | test.c:58:14:58:14 | Constant: 0 | != | test.c:58:9:58:9 | Load: x | 0 | 58 | 58 |
| test.c:58:9:58:14 | CompareEQ: ... == ... | test.c:58:14:58:14 | Constant: 0 | != | test.c:58:9:58:9 | Load: x | 0 | 62 | 62 |
| test.c:58:19:58:23 | CompareLT: ... < ... | test.c:58:19:58:19 | Load: y | >= | test.c:58:23:58:23 | Constant: (long)... | 0 | 62 | 62 |
| test.c:58:19:58:23 | CompareLT: ... < ... | test.c:58:23:58:23 | Constant: (long)... | < | test.c:58:19:58:19 | Load: y | 1 | 62 | 62 |
| test.c:75:9:75:14 | CompareEQ: ... == ... | test.c:75:9:75:9 | Load: x | != | test.c:75:14:75:14 | Constant: 0 | 0 | 79 | 79 |
| test.c:75:9:75:14 | CompareEQ: ... == ... | test.c:75:9:75:9 | Load: x | == | test.c:75:14:75:14 | Constant: 0 | 0 | 76 | 76 |
| test.c:75:9:75:14 | CompareEQ: ... == ... | test.c:75:14:75:14 | Constant: 0 | != | test.c:75:9:75:9 | Load: x | 0 | 79 | 79 |
| test.c:75:9:75:14 | CompareEQ: ... == ... | test.c:75:14:75:14 | Constant: 0 | == | test.c:75:9:75:9 | Load: x | 0 | 76 | 76 |
| test.c:85:8:85:13 | CompareEQ: ... == ... | test.c:85:8:85:8 | Load: x | == | test.c:85:13:85:13 | Constant: 0 | 0 | 85 | 85 |
| test.c:85:8:85:13 | CompareEQ: ... == ... | test.c:85:8:85:8 | Load: x | == | test.c:85:13:85:13 | Constant: 0 | 0 | 86 | 86 |
| test.c:85:8:85:13 | CompareEQ: ... == ... | test.c:85:13:85:13 | Constant: 0 | == | test.c:85:8:85:8 | Load: x | 0 | 85 | 85 |
| test.c:85:8:85:13 | CompareEQ: ... == ... | test.c:85:13:85:13 | Constant: 0 | == | test.c:85:8:85:8 | Load: x | 0 | 86 | 86 |
| test.c:85:18:85:23 | CompareNE: ... != ... | test.c:85:18:85:18 | Load: y | != | test.c:85:23:85:23 | Constant: (long)... | 0 | 86 | 86 |
| test.c:85:18:85:23 | CompareNE: ... != ... | test.c:85:23:85:23 | Constant: (long)... | != | test.c:85:18:85:18 | Load: y | 0 | 86 | 86 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:11:94:11 | Load: x | != | test.c:94:16:94:16 | Constant: 0 | 0 | 95 | 95 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:11:94:11 | Load: x | == | test.c:94:16:94:16 | Constant: 0 | 0 | 70 | 70 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:11:94:11 | Load: x | == | test.c:94:16:94:16 | Constant: 0 | 0 | 99 | 99 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:11:94:11 | Load: x | == | test.c:94:16:94:16 | Constant: 0 | 0 | 102 | 102 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:11:94:11 | Load: x | == | test.c:94:16:94:16 | Constant: 0 | 0 | 103 | 103 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:11:94:11 | Load: x | == | test.c:94:16:94:16 | Constant: 0 | 0 | 107 | 107 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:11:94:11 | Load: x | == | test.c:94:16:94:16 | Constant: 0 | 0 | 109 | 109 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:11:94:11 | Load: x | == | test.c:94:16:94:16 | Constant: 0 | 0 | 110 | 110 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:11:94:11 | Load: x | == | test.c:94:16:94:16 | Constant: 0 | 0 | 113 | 113 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:16:94:16 | Constant: 0 | != | test.c:94:11:94:11 | Load: x | 0 | 95 | 95 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:16:94:16 | Constant: 0 | == | test.c:94:11:94:11 | Load: x | 0 | 70 | 70 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:16:94:16 | Constant: 0 | == | test.c:94:11:94:11 | Load: x | 0 | 99 | 99 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:16:94:16 | Constant: 0 | == | test.c:94:11:94:11 | Load: x | 0 | 102 | 102 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:16:94:16 | Constant: 0 | == | test.c:94:11:94:11 | Load: x | 0 | 103 | 103 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:16:94:16 | Constant: 0 | == | test.c:94:11:94:11 | Load: x | 0 | 107 | 107 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:16:94:16 | Constant: 0 | == | test.c:94:11:94:11 | Load: x | 0 | 109 | 109 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:16:94:16 | Constant: 0 | == | test.c:94:11:94:11 | Load: x | 0 | 110 | 110 |
| test.c:94:11:94:16 | CompareNE: ... != ... | test.c:94:16:94:16 | Constant: 0 | == | test.c:94:11:94:11 | Load: x | 0 | 113 | 113 |
| test.c:102:16:102:21 | CompareLT: ... < ... | test.c:102:16:102:16 | Load: j | < | test.c:102:20:102:21 | Constant: 10 | 0 | 103 | 103 |
| test.c:102:16:102:21 | CompareLT: ... < ... | test.c:102:16:102:16 | Load: j | >= | test.c:102:20:102:21 | Constant: 10 | 0 | 70 | 70 |
| test.c:102:16:102:21 | CompareLT: ... < ... | test.c:102:16:102:16 | Load: j | >= | test.c:102:20:102:21 | Constant: 10 | 0 | 107 | 107 |
| test.c:102:16:102:21 | CompareLT: ... < ... | test.c:102:16:102:16 | Load: j | >= | test.c:102:20:102:21 | Constant: 10 | 0 | 109 | 109 |
| test.c:102:16:102:21 | CompareLT: ... < ... | test.c:102:16:102:16 | Load: j | >= | test.c:102:20:102:21 | Constant: 10 | 0 | 110 | 110 |
| test.c:102:16:102:21 | CompareLT: ... < ... | test.c:102:16:102:16 | Load: j | >= | test.c:102:20:102:21 | Constant: 10 | 0 | 113 | 113 |
| test.c:102:16:102:21 | CompareLT: ... < ... | test.c:102:20:102:21 | Constant: 10 | < | test.c:102:16:102:16 | Load: j | 1 | 70 | 70 |
| test.c:102:16:102:21 | CompareLT: ... < ... | test.c:102:20:102:21 | Constant: 10 | < | test.c:102:16:102:16 | Load: j | 1 | 107 | 107 |
| test.c:102:16:102:21 | CompareLT: ... < ... | test.c:102:20:102:21 | Constant: 10 | < | test.c:102:16:102:16 | Load: j | 1 | 109 | 109 |
| test.c:102:16:102:21 | CompareLT: ... < ... | test.c:102:20:102:21 | Constant: 10 | < | test.c:102:16:102:16 | Load: j | 1 | 110 | 110 |
| test.c:102:16:102:21 | CompareLT: ... < ... | test.c:102:20:102:21 | Constant: 10 | < | test.c:102:16:102:16 | Load: j | 1 | 113 | 113 |
| test.c:102:16:102:21 | CompareLT: ... < ... | test.c:102:20:102:21 | Constant: 10 | >= | test.c:102:16:102:16 | Load: j | 1 | 103 | 103 |
| test.c:109:9:109:14 | CompareEQ: ... == ... | test.c:109:9:109:9 | Load: x | != | test.c:109:14:109:14 | Constant: 0 | 0 | 109 | 109 |
| test.c:109:9:109:14 | CompareEQ: ... == ... | test.c:109:9:109:9 | Load: x | != | test.c:109:14:109:14 | Constant: 0 | 0 | 113 | 113 |
| test.c:109:9:109:14 | CompareEQ: ... == ... | test.c:109:14:109:14 | Constant: 0 | != | test.c:109:9:109:9 | Load: x | 0 | 109 | 109 |
| test.c:109:9:109:14 | CompareEQ: ... == ... | test.c:109:14:109:14 | Constant: 0 | != | test.c:109:9:109:9 | Load: x | 0 | 113 | 113 |
| test.c:109:19:109:23 | CompareLT: ... < ... | test.c:109:19:109:19 | Load: y | >= | test.c:109:23:109:23 | Constant: (long)... | 0 | 113 | 113 |
| test.c:109:19:109:23 | CompareLT: ... < ... | test.c:109:23:109:23 | Constant: (long)... | < | test.c:109:19:109:19 | Load: y | 1 | 113 | 113 |
| test.cpp:18:8:18:12 | CompareNE: (bool)... | test.cpp:18:8:18:10 | Call: call to get | != | test.cpp:18:8:18:12 | Constant: (bool)... | 0 | 0 | 0 |
| test.cpp:18:8:18:12 | CompareNE: (bool)... | test.cpp:18:8:18:12 | Constant: (bool)... | != | test.cpp:18:8:18:10 | Call: call to get | 0 | 0 | 0 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | != | test.cpp:31:12:31:13 | Constant: - ... | 0 | 34 | 34 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | == | test.cpp:31:12:31:13 | Constant: - ... | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | == | test.cpp:31:12:31:13 | Constant: - ... | 0 | 32 | 32 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:12:31:13 | Constant: - ... | != | test.cpp:31:7:31:7 | Load: x | 0 | 34 | 34 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:12:31:13 | Constant: - ... | == | test.cpp:31:7:31:7 | Load: x | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:12:31:13 | Constant: - ... | == | test.cpp:31:7:31:7 | Load: x | 0 | 32 | 32 |

View File

@@ -0,0 +1,91 @@
import cpp
import semmle.code.cpp.controlflow.IRGuards
query predicate astGuards(GuardCondition guard) {
any()
}
query predicate astGuardsCompare(int startLine, string msg) {
exists(GuardCondition guard, Expr left, Expr right, int k, string which, string op |
exists(boolean sense |
sense = true and which = "true"
or sense = false and which = "false"
|
guard.comparesLt(left, right, k, true, sense) and op = " < "
or
guard.comparesLt(left, right, k, false, sense) and op = " >= "
or
guard.comparesEq(left, right, k, true, sense) and op = " == "
or
guard.comparesEq(left, right, k, false, sense) and op = " != "
)
and startLine = guard.getLocation().getStartLine()
and msg = left + op + right + "+" + k + " when " + guard + " is " + which
)
}
query predicate astGuardsControl(GuardCondition guard, boolean sense, int start, int end) {
exists(BasicBlock block |
guard.controls(block, sense) and
block.hasLocationInfo(_, start, _, end, _)
)
}
query predicate astGuardsEnsure(GuardCondition guard, Expr left, string op, Expr right, int k, int start, int end)
{
exists(BasicBlock block |
guard.ensuresLt(left, right, k, block, true) and op = "<"
or
guard.ensuresLt(left, right, k, block, false) and op = ">="
or
guard.ensuresEq(left, right, k, block, true) and op = "=="
or
guard.ensuresEq(left, right, k, block, false) and op = "!="
|
block.hasLocationInfo(_, start, _, end, _)
)
}
query predicate irGuards(IRGuardCondition guard) {
any()
}
query predicate irGuardsCompare(int startLine, string msg) {
exists(IRGuardCondition guard, Instruction left, Instruction right, int k, string which, string op |
exists(boolean sense |
sense = true and which = "true"
or sense = false and which = "false"
|
guard.comparesLt(left, right, k, true, sense) and op = " < "
or
guard.comparesLt(left, right, k, false, sense) and op = " >= "
or
guard.comparesEq(left, right, k, true, sense) and op = " == "
or
guard.comparesEq(left, right, k, false, sense) and op = " != "
)
and startLine = guard.getLocation().getStartLine()
and msg = left.getUnconvertedResultExpression() + op + right.getUnconvertedResultExpression() + "+" + k + " when " + guard + " is " + which
)
}
query predicate irGuardsControl(IRGuardCondition guard, boolean sense, int start, int end) {
exists(IRBlock block |
guard.controls(block, sense) and
block.getLocation().hasLocationInfo(_, start, _, end, _)
)
}
query predicate irGuardsEnsure(IRGuardCondition guard, Instruction left, string op, Instruction right, int k, int start, int end)
{
exists(IRBlock block |
guard.ensuresLt(left, right, k, block, true) and op = "<"
or
guard.ensuresLt(left, right, k, block, false) and op = ">="
or
guard.ensuresEq(left, right, k, block, true) and op = "=="
or
guard.ensuresEq(left, right, k, block, false) and op = "!="
|
block.getLocation().hasLocationInfo(_, start, _, end, _)
)
}

View File

@@ -34,7 +34,6 @@
| test.cpp:8:31:8:35 | initializer for Value |
| test.cpp:11:10:11:11 | mention of EC |
| test.cpp:11:25:11:27 | mention of IsX<X> |
| test.cpp:11:25:11:27 | mention of IsX<X> |
| test.cpp:12:8:12:9 | DX<X, B> |
| test.cpp:12:8:12:9 | definition of DX<X, B> |
| test.cpp:13:17:13:20 | Type |

View File

@@ -32,3 +32,4 @@
| PointlessComparison.c:129:12:129:16 | ... > ... | Comparison is always false because a <= 3. |
| PointlessComparison.c:197:7:197:11 | ... < ... | Comparison is always false because x >= 0. |
| RegressionTests.cpp:57:7:57:22 | ... <= ... | Comparison is always true because * ... <= 4294967295. |
| Templates.cpp:9:10:9:24 | ... <= ... | Comparison is always true because local <= 32767. |

View File

@@ -0,0 +1,17 @@
template<typename T>
bool sometimesPointless(T param) {
return param <= 0xFFFF; // GOOD (hypothetical instantiations are okay)
}
template<typename T>
bool alwaysPointless(T param) {
short local = param;
return local <= 0xFFFF; // BAD (in all instantiations)
}
static int caller(int i) {
return
sometimesPointless<short>(i) ||
alwaysPointless<short>(i) ||
alwaysPointless<int>(i);
}

View File

@@ -1,5 +1,4 @@
| custom_printf.cpp:31:5:31:12 | call to myPrintf | Format expects 2 arguments but given 3 |
| custom_printf.cpp:44:2:44:7 | call to printf | Format expects 0 arguments but given 2 |
| macros.cpp:12:2:12:31 | call to printf | Format expects 2 arguments but given 3 |
| macros.cpp:16:2:16:30 | call to printf | Format expects 2 arguments but given 3 |
| test.c:7:2:7:7 | call to printf | Format expects 0 arguments but given 1 |

View File

@@ -1,5 +1,4 @@
| custom_printf.cpp:29:5:29:12 | call to myPrintf | Format expects 2 arguments but given 1 |
| custom_printf.cpp:45:2:45:7 | call to printf | Format expects 2 arguments but given 0 |
| macros.cpp:14:2:14:37 | call to printf | Format expects 4 arguments but given 3 |
| macros.cpp:21:2:21:36 | call to printf | Format expects 4 arguments but given 3 |
| test.c:9:2:9:7 | call to printf | Format expects 1 arguments but given 0 |

View File

@@ -41,6 +41,6 @@ void test_custom_printf2()
{
// notTheFormat format ...
printf(0, "%i %i", 100, 200); // GOOD
printf("", "%i %i", 100, 200); // GOOD [FALSE POSITIVE]
printf("%i %i", "" ); // GOOD [FALSE POSITIVE]
printf("", "%i %i", 100, 200); // GOOD
printf("%i %i", "" ); // GOOD
}

View File

@@ -0,0 +1,10 @@
| tests.cpp:18:15:18:22 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' |
| tests.cpp:19:15:19:22 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' |
| tests.cpp:25:17:25:23 | Hello | This argument should be of type 'wchar_t *' but is of type 'char *' |
| tests.cpp:26:17:26:24 | Hello | This argument should be of type 'wchar_t *' but is of type 'char16_t *' |
| tests.cpp:30:17:30:24 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' |
| tests.cpp:31:17:31:24 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' |
| tests.cpp:33:36:33:42 | Hello | This argument should be of type 'char16_t *' but is of type 'char *' |
| tests.cpp:35:36:35:43 | Hello | This argument should be of type 'char16_t *' but is of type 'wchar_t *' |
| tests.cpp:38:36:38:43 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' |
| tests.cpp:39:36:39:43 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' |

View File

@@ -0,0 +1 @@
Likely Bugs/Format/WrongTypeFormatArguments.ql

View File

@@ -0,0 +1,3 @@
| tests.cpp:8:5:8:10 | printf | char | char16_t, wchar_t | char16_t, wchar_t |
| tests.cpp:9:5:9:11 | wprintf | wchar_t | char | wchar_t |
| tests.cpp:10:5:10:12 | swprintf | char16_t | char | char16_t |

View File

@@ -0,0 +1,8 @@
import cpp
from FormattingFunction f
select
f,
concat(f.getDefaultCharType().toString(), ", "),
concat(f.getNonDefaultCharType().toString(), ", "),
concat(f.getWideCharType().toString(), ", ")

View File

@@ -0,0 +1,40 @@
/*
* Test for custom definitions of *wprintf using different types than the
* platform wide character type.
*/
typedef unsigned int size_t;
int printf(const char * format, ...);
int wprintf(const wchar_t * format, ...); // on wchar_t
int swprintf(char16_t * s, size_t n, const char16_t * format, ...); // on char16_t
#define BUF_SIZE (4096)
void tests() {
char16_t buffer[BUF_SIZE];
printf("%s", "Hello"); // GOOD
printf("%s", u"Hello"); // BAD: expecting char
printf("%s", L"Hello"); // BAD: expecting char
printf("%S", "Hello"); // BAD: expecting wchar_t or char16_t [NOT DETECTED]
printf("%S", u"Hello"); // GOOD
printf("%S", L"Hello"); // GOOD
wprintf(L"%s", "Hello"); // BAD: expecting wchar_t
wprintf(L"%s", u"Hello"); // BAD: expecting wchar_t
wprintf(L"%s", L"Hello"); // GOOD
wprintf(L"%S", "Hello"); // GOOD
wprintf(L"%S", u"Hello"); // BAD: expecting char
wprintf(L"%S", L"Hello"); // BAD: expecting char
swprintf(buffer, BUF_SIZE, u"%s", "Hello"); // BAD: expecting char16_t
swprintf(buffer, BUF_SIZE, u"%s", u"Hello"); // GOOD
swprintf(buffer, BUF_SIZE, u"%s", L"Hello"); // BAD: expecting char16_t
swprintf(buffer, BUF_SIZE, u"%S", "Hello"); // GOOD
swprintf(buffer, BUF_SIZE, u"%S", u"Hello"); // BAD: expecting char
swprintf(buffer, BUF_SIZE, u"%S", L"Hello"); // BAD: expecting char
}

View File

@@ -0,0 +1,2 @@
| tests_32.cpp:14:16:14:23 | void_ptr | This argument should be of type 'long' but is of type 'void *' |
| tests_64.cpp:14:16:14:23 | void_ptr | This argument should be of type 'long' but is of type 'void *' |

View File

@@ -0,0 +1 @@
Likely Bugs/Format/WrongTypeFormatArguments.ql

View File

@@ -0,0 +1,17 @@
// semmle-extractor-options: --edg --target --edg linux_i686
/*
* Test for printf in a snapshot that contains multiple word/pointer sizes.
*/
int printf(const char * format, ...);
void test_32()
{
long l;
void *void_ptr;
printf("%li", l); // GOOD
printf("%li", void_ptr); // BAD
printf("%p", l); // BAD [NOT DETECTED]
printf("%p", void_ptr); // GOOD
}

View File

@@ -0,0 +1,17 @@
// semmle-extractor-options: --edg --target --edg linux_x86_64
/*
* Test for printf in a snapshot that contains multiple word/pointer sizes.
*/
int printf(const char * format, ...);
void test_64()
{
long l;
void *void_ptr;
printf("%li", l); // GOOD
printf("%li", void_ptr); // BAD
printf("%p", l); // BAD [NOT DETECTED]
printf("%p", void_ptr); // GOOD
}

View File

@@ -11,14 +11,6 @@
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:47:19:47:21 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:68:19:68:21 | sst | This argument should be of type 'size_t' but is of type 'long' |
| printf1.h:70:19:70:20 | ul | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:71:19:71:20 | st | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:72:19:72:20 | ST | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:73:19:73:22 | c_st | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:74:19:74:22 | C_ST | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:75:19:75:28 | sizeof(<expr>) | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:83:23:83:35 | ... - ... | This argument should be of type 'size_t' but is of type 'long' |
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *' |
| real_world.h:62:22:62:23 | & ... | This argument should be of type 'short *' but is of type 'int *' |
| real_world.h:63:22:63:24 | & ... | This argument should be of type 'short *' but is of type 'unsigned int *' |

View File

@@ -65,14 +65,14 @@ void g()
printf("%zu", c_st); // ok
printf("%zu", C_ST); // ok
printf("%zu", sizeof(ul)); // ok
printf("%zu", sst); // not ok [NOT DETECTED ON MICROSOFT]
printf("%zu", sst); // not ok [NOT DETECTED]
printf("%zd", ul); // not ok
printf("%zd", st); // not ok
printf("%zd", ST); // not ok
printf("%zd", c_st); // not ok
printf("%zd", C_ST); // not ok
printf("%zd", sizeof(ul)); // not ok
printf("%zd", ul); // not ok [NOT DETECTED]
printf("%zd", st); // not ok [NOT DETECTED]
printf("%zd", ST); // not ok [NOT DETECTED]
printf("%zd", c_st); // not ok [NOT DETECTED]
printf("%zd", C_ST); // not ok [NOT DETECTED]
printf("%zd", sizeof(ul)); // not ok [NOT DETECTED]
printf("%zd", sst); // ok
{
char *ptr_a, *ptr_b;
@@ -80,8 +80,8 @@ void g()
printf("%tu", ptr_a - ptr_b); // ok
printf("%td", ptr_a - ptr_b); // ok
printf("%zu", ptr_a - ptr_b); // ok (dubious) [DETECTED ON LINUX ONLY]
printf("%zd", ptr_a - ptr_b); // ok (dubious) [DETECTED ON MICROSOFT ONLY]
printf("%zu", ptr_a - ptr_b); // ok (dubious)
printf("%zd", ptr_a - ptr_b); // ok (dubious)
}
}
@@ -92,3 +92,12 @@ void h(int i, struct some_type *j, int k)
// going on.
printf("%i %R %i", i, j, k); // GOOD (as far as we can tell)
}
typedef long ptrdiff_t;
void fun1(unsigned char* a, unsigned char* b) {
ptrdiff_t pdt;
printf("%td\n", pdt); // GOOD
printf("%td\n", a-b); // GOOD
}

View File

@@ -0,0 +1,2 @@
| printf.cpp:45:29:45:35 | test | This argument should be of type 'char *' but is of type 'char16_t *' |
| printf.cpp:52:29:52:35 | test | This argument should be of type 'char16_t *' but is of type 'wchar_t *' |

View File

@@ -0,0 +1 @@
Likely Bugs/Format/WrongTypeFormatArguments.ql

View File

@@ -0,0 +1,2 @@
| printf.cpp:15:5:15:12 | swprintf | char16_t | char | char16_t |
| printf.cpp:26:5:26:11 | sprintf | char | char16_t | char16_t |

View File

@@ -0,0 +1,8 @@
import cpp
from FormattingFunction f
select
f,
concat(f.getDefaultCharType().toString(), ", "),
concat(f.getNonDefaultCharType().toString(), ", "),
concat(f.getWideCharType().toString(), ", ")

View File

@@ -0,0 +1,53 @@
/*
* Test for custom definitions of *wprintf using different types than the
* platform wide character type.
*/
#define WCHAR char16_t
typedef void *va_list;
#define va_start(va, other)
#define va_end(args)
int vswprintf(WCHAR *dest, WCHAR *format, va_list args) {
return 0;
}
int swprintf(WCHAR *dest, WCHAR *format, ...) {
va_list args;
va_start(args, format);
int ret = vswprintf(dest, format, args);
va_end(args);
return ret;
}
int sprintf(char *dest, char *format, ...);
// ---
void test1() {
WCHAR string[20];
swprintf(string, u"test %s", u"test"); // GOOD
}
void test2() {
char string[20];
sprintf(string, "test %S", u"test"); // GOOD
}
void test3() {
char string[20];
sprintf(string, "test %s", u"test"); // BAD: `char16_t` string parameter read as `char` string
}
void test4() {
char string[20];
sprintf(string, "test %S", L"test"); // BAD: `wchar_t` string parameter read as `char16_t` string
}

View File

@@ -11,14 +11,6 @@
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:47:19:47:21 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:68:19:68:21 | sst | This argument should be of type 'size_t' but is of type 'long' |
| printf1.h:70:19:70:20 | ul | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:71:19:71:20 | st | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:72:19:72:20 | ST | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:73:19:73:22 | c_st | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:74:19:74:22 | C_ST | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:75:19:75:28 | sizeof(<expr>) | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:83:23:83:35 | ... - ... | This argument should be of type 'size_t' but is of type 'long' |
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *' |
| real_world.h:62:22:62:23 | & ... | This argument should be of type 'short *' but is of type 'int *' |
| real_world.h:63:22:63:24 | & ... | This argument should be of type 'short *' but is of type 'unsigned int *' |

View File

@@ -0,0 +1,4 @@
| common.h:12:12:12:17 | printf | char | wchar_t | wchar_t |
| format.h:4:13:4:17 | error | char | wchar_t | wchar_t |
| real_world.h:8:12:8:18 | fprintf | char | wchar_t | wchar_t |
| real_world.h:33:6:33:12 | msg_out | char | wchar_t | wchar_t |

View File

@@ -0,0 +1,8 @@
import cpp
from FormattingFunction f
select
f,
concat(f.getDefaultCharType().toString(), ", "),
concat(f.getNonDefaultCharType().toString(), ", "),
concat(f.getWideCharType().toString(), ", ")

View File

@@ -65,14 +65,14 @@ void g()
printf("%zu", c_st); // ok
printf("%zu", C_ST); // ok
printf("%zu", sizeof(ul)); // ok
printf("%zu", sst); // not ok [NOT DETECTED ON MICROSOFT]
printf("%zu", sst); // not ok [NOT DETECTED]
printf("%zd", ul); // not ok
printf("%zd", st); // not ok
printf("%zd", ST); // not ok
printf("%zd", c_st); // not ok
printf("%zd", C_ST); // not ok
printf("%zd", sizeof(ul)); // not ok
printf("%zd", ul); // not ok [NOT DETECTED]
printf("%zd", st); // not ok [NOT DETECTED]
printf("%zd", ST); // not ok [NOT DETECTED]
printf("%zd", c_st); // not ok [NOT DETECTED]
printf("%zd", C_ST); // not ok [NOT DETECTED]
printf("%zd", sizeof(ul)); // not ok [NOT DETECTED]
printf("%zd", sst); // ok
{
char *ptr_a, *ptr_b;
@@ -80,8 +80,8 @@ void g()
printf("%tu", ptr_a - ptr_b); // ok
printf("%td", ptr_a - ptr_b); // ok
printf("%zu", ptr_a - ptr_b); // ok (dubious) [DETECTED ON LINUX ONLY]
printf("%zd", ptr_a - ptr_b); // ok (dubious) [DETECTED ON MICROSOFT ONLY]
printf("%zu", ptr_a - ptr_b); // ok (dubious)
printf("%zd", ptr_a - ptr_b); // ok (dubious)
}
}
@@ -92,3 +92,12 @@ void h(int i, struct some_type *j, int k)
// going on.
printf("%i %R %i", i, j, k); // GOOD (as far as we can tell)
}
typedef long ptrdiff_t;
void fun1(unsigned char* a, unsigned char* b) {
ptrdiff_t pdt;
printf("%td\n", pdt); // GOOD
printf("%td\n", a-b); // GOOD
}

View File

@@ -11,7 +11,6 @@
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:47:19:47:21 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:70:19:70:20 | ul | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:71:19:71:20 | st | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
| printf1.h:72:19:72:20 | ST | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
| printf1.h:73:19:73:22 | c_st | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |

View File

@@ -65,9 +65,9 @@ void g()
printf("%zu", c_st); // ok
printf("%zu", C_ST); // ok
printf("%zu", sizeof(ul)); // ok
printf("%zu", sst); // not ok [NOT DETECTED ON MICROSOFT]
printf("%zu", sst); // not ok [NOT DETECTED]
printf("%zd", ul); // not ok
printf("%zd", ul); // not ok [NOT DETECTED]
printf("%zd", st); // not ok
printf("%zd", ST); // not ok
printf("%zd", c_st); // not ok
@@ -80,8 +80,8 @@ void g()
printf("%tu", ptr_a - ptr_b); // ok
printf("%td", ptr_a - ptr_b); // ok
printf("%zu", ptr_a - ptr_b); // ok (dubious) [DETECTED ON LINUX ONLY]
printf("%zd", ptr_a - ptr_b); // ok (dubious) [DETECTED ON MICROSOFT ONLY]
printf("%zu", ptr_a - ptr_b); // ok (dubious)
printf("%zd", ptr_a - ptr_b); // ok (dubious) [FALSE POSITIVE]
}
}
@@ -92,3 +92,12 @@ void h(int i, struct some_type *j, int k)
// going on.
printf("%i %R %i", i, j, k); // GOOD (as far as we can tell)
}
typedef long long ptrdiff_t;
void fun1(unsigned char* a, unsigned char* b) {
ptrdiff_t pdt;
printf("%td\n", pdt); // GOOD
printf("%td\n", a-b); // GOOD
}

View File

@@ -43,7 +43,7 @@ void someFunction()
WCHAR filename[MAX_LONGPATH];
int linenum;
msg_out("Source file: %S @ %d\n", filename, linenum); // GOOD
msg_out("Source file: %S @ %d\n", filename, linenum); // GOOD [FALSE POSITIVE]
}
// --------------------------------------------------------------

View File

@@ -11,13 +11,13 @@
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:47:19:47:21 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:70:19:70:20 | ul | This argument should be of type 'ssize_t' but is of type 'unsigned long' |
| printf1.h:71:19:71:20 | st | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
| printf1.h:72:19:72:20 | ST | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
| printf1.h:73:19:73:22 | c_st | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
| printf1.h:74:19:74:22 | C_ST | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
| printf1.h:75:19:75:28 | sizeof(<expr>) | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
| printf1.h:84:23:84:35 | ... - ... | This argument should be of type 'ssize_t' but is of type 'long long' |
| printf1.h:130:18:130:18 | 0 | This argument should be of type 'void *' but is of type 'int' |
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *' |
| real_world.h:62:22:62:23 | & ... | This argument should be of type 'short *' but is of type 'int *' |
| real_world.h:63:22:63:24 | & ... | This argument should be of type 'short *' but is of type 'unsigned int *' |

View File

@@ -65,9 +65,9 @@ void g()
printf("%zu", c_st); // ok
printf("%zu", C_ST); // ok
printf("%zu", sizeof(ul)); // ok
printf("%zu", sst); // not ok [NOT DETECTED ON MICROSOFT]
printf("%zu", sst); // not ok [NOT DETECTED]
printf("%zd", ul); // not ok
printf("%zd", ul); // not ok [NOT DETECTED]
printf("%zd", st); // not ok
printf("%zd", ST); // not ok
printf("%zd", c_st); // not ok
@@ -80,8 +80,8 @@ void g()
printf("%tu", ptr_a - ptr_b); // ok
printf("%td", ptr_a - ptr_b); // ok
printf("%zu", ptr_a - ptr_b); // ok (dubious) [DETECTED ON LINUX ONLY]
printf("%zd", ptr_a - ptr_b); // ok (dubious) [DETECTED ON MICROSOFT ONLY]
printf("%zu", ptr_a - ptr_b); // ok (dubious)
printf("%zd", ptr_a - ptr_b); // ok (dubious) [FALSE POSITIVE]
}
}
@@ -92,3 +92,40 @@ void h(int i, struct some_type *j, int k)
// going on.
printf("%i %R %i", i, j, k); // GOOD (as far as we can tell)
}
typedef long long ptrdiff_t;
void fun1(unsigned char* a, unsigned char* b) {
ptrdiff_t pdt;
printf("%td\n", pdt); // GOOD
printf("%td\n", a-b); // GOOD
}
typedef wchar_t WCHAR_T; // WCHAR_T -> wchar_t -> int
typedef int MYCHAR; // MYCHAR -> int (notably not via the wchar_t typedef)
void fun2() {
wchar_t *myString1;
WCHAR_T *myString2;
int *myString3;
MYCHAR *myString4;
printf("%S", myString1); // GOOD
printf("%S", myString2); // GOOD
printf("%S", myString3); // GOOD
printf("%S", myString4); // GOOD
}
typedef void *VOIDPTR;
typedef int (*FUNPTR)(int);
void fun3(void *p1, VOIDPTR p2, FUNPTR p3, char *p4)
{
printf("%p\n", p1); // GOOD
printf("%p\n", p2); // GOOD
printf("%p\n", p3); // GOOD
printf("%p\n", p4); // GOOD
printf("%p\n", p4 + 1); // GOOD
printf("%p\n", 0); // GOOD [FALSE POSITIVE]
}

View File

@@ -171,3 +171,10 @@ void more_tests_2()
memset(iapa, 0, sizeof(iapa)); // GOOD
memset(iapa, 0, sizeof(intArrayPointer *)); // BAD
}
void more_tests_3()
{
myStruct ms;
decltype(&ms) msPtr = &ms;
memset(msPtr, 0, sizeof(myStruct)); // GOOD
}

View File

@@ -0,0 +1,34 @@
#define NULL 0
#define CONST const
typedef wchar_t WCHAR; // wc, 16-bit UNICODE character
typedef char CHAR;
typedef WCHAR *LPWSTR;
typedef CONST WCHAR *LPCWSTR;
typedef CHAR *LPSTR;
typedef CONST CHAR *LPCSTR;
void fconstWChar(LPCWSTR p) {}
void fWChar(LPWSTR p) {}
void Test()
{
char *lpChar = NULL;
wchar_t *lpWchar = NULL;
LPCSTR lpcstr = "b";
lpWchar = (LPWSTR)"a"; // BUG
lpWchar = (LPWSTR)lpcstr; // BUG
lpWchar = (wchar_t*)lpChar; // BUG
fconstWChar((LPCWSTR)lpChar); // BUG
fWChar((LPWSTR)lpChar); // BUG
lpChar = (LPSTR)"a"; // Valid
lpWchar = (LPWSTR)L"a"; // Valid
fconstWChar((LPCWSTR)lpWchar); // Valid
fWChar(lpWchar); // Valid
}

View File

@@ -0,0 +1,5 @@
| WcharCharConversion.cpp:21:20:21:22 | array to pointer conversion | Conversion from const char * to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:22:20:22:25 | lpcstr | Conversion from LPCSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:24:22:24:27 | lpChar | Conversion from char * to wchar_t *. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:26:23:26:28 | lpChar | Conversion from char * to LPCWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:27:17:27:22 | lpChar | Conversion from char * to LPWSTR. Use of invalid string can lead to undefined behavior. |

View File

@@ -0,0 +1 @@
Security/CWE/CWE-704/WcharCharConversion.ql