Merge remote-tracking branch 'upstream/main' into wrongtypeformat

This commit is contained in:
Geoffrey White
2026-03-16 19:03:02 +00:00
1053 changed files with 70115 additions and 52703 deletions

View File

@@ -1,3 +1,18 @@
## 8.0.0
### Breaking Changes
* CodeQL version 2.24.2 accidentally introduced a syntactical breaking change to `BarrierGuard<...>::getAnIndirectBarrierNode` and `InstructionBarrierGuard<...>::getAnIndirectBarrierNode`. These breaking changes have now been reverted so that the original code compiles again.
* `MustFlow`, the inter-procedural must-flow data flow analysis library, has been re-worked to use parameterized modules. Like in the case of data flow and taint tracking, instead of extending the `MustFlowConfiguration` class, the user should now implement a module with the `MustFlow::ConfigSig` signature, and instantiate the `MustFlow::Global` parameterized module with the implemented module.
### Minor Analysis Improvements
* Refactored the "Year field changed using an arithmetic operation without checking for leap year" query (`cpp/leap-year/unchecked-after-arithmetic-year-modification`) to address large numbers of false positive results.
### Bug Fixes
* The `allowInterproceduralFlow` predicate of must-flow data flow configurations now correctly handles direct recursion.
## 7.1.1
### Minor Analysis Improvements

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Refactored the "Year field changed using an arithmetic operation without checking for leap year" query (`cpp/leap-year/unchecked-after-arithmetic-year-modification`) to address large numbers of false positive results.

View File

@@ -1,4 +0,0 @@
---
category: fix
---
* The `allowInterproceduralFlow` predicate of must-flow data flow configurations now correctly handles direct recursion.

View File

@@ -1,4 +0,0 @@
---
category: breaking
---
* `MustFlow`, the inter-procedural must-flow data flow analysis library, has been re-worked to use parameterized modules. Like in the case of data flow and taint tracking, instead of extending the `MustFlowConfiguration` class, the user should now implement a module with the `MustFlow::ConfigSig` signature, and instantiate the `MustFlow::Global` parameterized module with the implemented module.

View File

@@ -1,4 +0,0 @@
---
category: breaking
---
* CodeQL version 2.24.2 accidentially introduced a syntactical breaking change to `BarrierGuard<...>::getAnIndirectBarrierNode` and `InstructionBarrierGuard<...>::getAnIndirectBarrierNode`. These breaking changes have now been reverted so that the original code compiles again.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Inline expectations test comments, which are of the form `// $ tag` or `// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the `$` symbol.

View File

@@ -0,0 +1,14 @@
## 8.0.0
### Breaking Changes
* CodeQL version 2.24.2 accidentally introduced a syntactical breaking change to `BarrierGuard<...>::getAnIndirectBarrierNode` and `InstructionBarrierGuard<...>::getAnIndirectBarrierNode`. These breaking changes have now been reverted so that the original code compiles again.
* `MustFlow`, the inter-procedural must-flow data flow analysis library, has been re-worked to use parameterized modules. Like in the case of data flow and taint tracking, instead of extending the `MustFlowConfiguration` class, the user should now implement a module with the `MustFlow::ConfigSig` signature, and instantiate the `MustFlow::Global` parameterized module with the implemented module.
### Minor Analysis Improvements
* Refactored the "Year field changed using an arithmetic operation without checking for leap year" query (`cpp/leap-year/unchecked-after-arithmetic-year-modification`) to address large numbers of false positive results.
### Bug Fixes
* The `allowInterproceduralFlow` predicate of must-flow data flow configurations now correctly handles direct recursion.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 7.1.1
lastReleaseVersion: 8.0.0

View File

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

View File

@@ -524,6 +524,12 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
not exists(NewOrNewArrayExpr new | e = new.getAllocatorCall().getArgument(0))
)
}
/**
* Holds if this function has an ambiguous return type, meaning that zero or multiple return
* types for this function are present in the database (this can occur in `build-mode: none`).
*/
predicate hasAmbiguousReturnType() { count(this.getType()) != 1 }
}
pragma[noinline]

View File

@@ -1663,7 +1663,7 @@ private module Cached {
private predicate compares_ge(
ValueNumber test, Operand left, Operand right, int k, boolean isGe, GuardValue value
) {
exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, value))
compares_lt(test, right, left, 1 - k, isGe, value)
}
/** Rearrange various simple comparisons into `left < right + k` form. */

View File

@@ -353,12 +353,26 @@ module CsvValidation {
)
}
private string getIncorrectConstructorSummaryOutput() {
exists(string namespace, string type, string name, string output |
type = name or
type = name + "<" + any(string s)
|
summaryModel(namespace, type, _, name, _, _, _, output, _, _, _) and
output.matches("ReturnValue%") and
result =
"Constructor model for " + namespace + "." + type +
" should use `Argument[this]` in the output, not `ReturnValue`."
)
}
/** Holds if some row in a CSV-based flow model appears to contain typos. */
query predicate invalidModelRow(string msg) {
msg =
[
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
getInvalidModelSubtype(), getInvalidModelColumnCount(), KindVal::getInvalidModelKind()
getInvalidModelSubtype(), getInvalidModelColumnCount(), KindVal::getInvalidModelKind(),
getIncorrectConstructorSummaryOutput()
]
}
}

View File

@@ -6,117 +6,67 @@ private import OverlayXml
/**
* Holds always for the overlay variant and never for the base variant.
* This local predicate is used to define local predicates that behave
* differently for the base and overlay variant.
*/
overlay[local]
predicate isOverlay() { databaseMetadata("isOverlay", "true") }
overlay[local]
private string getLocationFilePath(@location_default loc) {
exists(@file file | locations_default(loc, file, _, _, _, _) | files(file, result))
}
/**
* Gets the file path for an element with a single location.
* Holds if the TRAP file or tag `t` is reachable from source file `sourceFile`
* in the base (isOverlayVariant=false) or overlay (isOverlayVariant=true) variant.
*/
overlay[local]
private string getSingleLocationFilePath(@element e) {
exists(@location_default loc |
var_decls(e, _, _, _, loc)
or
fun_decls(e, _, _, _, loc)
or
type_decls(e, _, loc)
or
namespace_decls(e, _, loc, _)
or
macroinvocations(e, _, loc, _)
or
preprocdirects(e, _, loc)
or
diagnostics(e, _, _, _, _, loc)
or
usings(e, _, loc, _)
or
static_asserts(e, _, _, loc, _)
or
derivations(e, _, _, _, loc)
or
frienddecls(e, _, _, loc)
or
comments(e, _, loc)
or
exprs(e, _, loc)
or
stmts(e, _, loc)
or
initialisers(e, _, _, loc)
or
attributes(e, _, _, _, loc)
or
attribute_args(e, _, _, _, loc)
or
namequalifiers(e, _, _, loc)
or
enumconstants(e, _, _, _, _, loc)
or
type_mentions(e, _, loc, _)
or
lambda_capture(e, _, _, _, _, _, loc)
or
concept_templates(e, _, loc)
|
result = getLocationFilePath(loc)
private predicate locallyReachableTrapOrTag(
boolean isOverlayVariant, string sourceFile, @trap_or_tag t
) {
exists(@source_file sf, @trap trap |
(if isOverlay() then isOverlayVariant = true else isOverlayVariant = false) and
source_file_uses_trap(sf, trap) and
source_file_name(sf, sourceFile) and
(t = trap or trap_uses_tag(trap, t))
)
}
/**
* Gets the file path for an element with potentially multiple locations.
* Holds if element `e` is in TRAP file or tag `t`
* in the base (isOverlayVariant=false) or overlay (isOverlayVariant=true) variant.
*/
overlay[local]
private string getMultiLocationFilePath(@element e) {
exists(@location_default loc |
var_decls(_, e, _, _, loc)
or
fun_decls(_, e, _, _, loc)
or
type_decls(_, e, loc)
or
namespace_decls(_, e, loc, _)
|
result = getLocationFilePath(loc)
)
}
/**
* A local helper predicate that holds in the base variant and never in the
* overlay variant.
*/
overlay[local]
private predicate isBase() { not isOverlay() }
/**
* Holds if `path` was extracted in the overlay database.
*/
overlay[local]
private predicate overlayHasFile(string path) {
isOverlay() and
files(_, path) and
path != ""
private predicate locallyInTrapOrTag(boolean isOverlayVariant, @element e, @trap_or_tag t) {
(if isOverlay() then isOverlayVariant = true else isOverlayVariant = false) and
in_trap_or_tag(e, t)
}
/**
* Discards an element from the base variant if:
* - It has a single location in a file extracted in the overlay, or
* - All of its locations are in files extracted in the overlay.
* - We have knowledge about what TRAP file or tag it is in (in the base).
* - It is not in any overlay TRAP file or tag that is reachable from an overlay source file.
* - For every base TRAP file or tag that contains it and is reachable from a base source file,
* either the source file has changed, or the overlay has redefined the TRAP file or tag,
* or the overlay runner has re-extracted the same source file.
*/
overlay[discard_entity]
private predicate discardElement(@element e) {
isBase() and
(
overlayHasFile(getSingleLocationFilePath(e))
or
forex(string path | path = getMultiLocationFilePath(e) | overlayHasFile(path))
// If we don't have any knowledge about what TRAP file something
// is in, then we don't want to discard it, so we only consider
// entities that are known to be in a base TRAP file or tag.
locallyInTrapOrTag(false, e, _) and
// Anything that is reachable from an overlay source file should
// not be discarded.
not exists(@trap_or_tag t | locallyInTrapOrTag(true, e, t) |
locallyReachableTrapOrTag(true, _, t)
) and
// Finally, we have to make sure the base variant does not retain it.
// If it is reachable from a base source file, then that is
// sufficient unless either the base source file has changed (in
// particular, been deleted), or the overlay has redefined the TRAP
// file or tag it is in, or the overlay runner has re-extracted the same
// source file (e.g. because a header it includes has changed).
forall(@trap_or_tag t, string sourceFile |
locallyInTrapOrTag(false, e, t) and
locallyReachableTrapOrTag(false, sourceFile, t)
|
overlayChangedFiles(sourceFile) or
locallyReachableTrapOrTag(true, _, t) or
locallyReachableTrapOrTag(true, sourceFile, _)
)
}

View File

@@ -1,3 +1,7 @@
## 1.5.12
No user-facing changes.
## 1.5.11
No user-facing changes.

View File

@@ -218,7 +218,9 @@ where
// only report if we cannot prove that the result of the
// multiplication will be less (resp. greater) than the
// maximum (resp. minimum) number we can compute.
overflows(me, t1)
overflows(me, t1) and
// exclude cases where the expression type may not have been extracted accurately
not me.getParent().(Call).getTarget().hasAmbiguousReturnType()
select me,
"Multiplication result may overflow '" + me.getType().toString() + "' before it is converted to '"
+ me.getFullyConverted().getType().toString() + "'."

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Fixed an issue with the "Multiplication result converted to larger type" (`cpp/integer-multiplication-cast-to-long`) query causing false positive results in `build-mode: none` databases.

View File

@@ -0,0 +1,3 @@
## 1.5.12
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.5.11
lastReleaseVersion: 1.5.12

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.5.12-dev
version: 1.5.13-dev
groups:
- cpp
- queries

View File

@@ -46,7 +46,7 @@ public:
{
C *c = new C();
B *b = B::make(c);
sink(b->c); // $ast,ir
sink(b->c); // $ ast,ir
}
void f2()

View File

@@ -26,9 +26,9 @@ public:
void func()
{
sink(s1); // $ast,ir
sink(s1); // $ ast,ir
sink(s2); // $ MISSING: ast,ir
sink(s3); // $ast,ir
sink(s3); // $ ast,ir
sink(s4); // $ MISSING: ast,ir
}
};

View File

@@ -19,7 +19,7 @@ public:
};
static void sinkWrap(Box2* b2) {
sink(b2->getBox1()->getElem()); // $ast,ir=28:15 ast,ir=35:15 ast,ir=42:15 ast,ir=49:15
sink(b2->getBox1()->getElem()); // $ ast,ir=28:15 ast,ir=35:15 ast,ir=42:15 ast,ir=49:15
}
Box2* boxfield;

View File

@@ -48,25 +48,25 @@ struct S {
void test_setDirectly() {
S s;
s.setDirectly(user_input());
sink(s.getDirectly()); // $ast ir
sink(s.getDirectly()); // $ ast ir
}
void test_setIndirectly() {
S s;
s.setIndirectly(user_input());
sink(s.getIndirectly()); // $ast ir
sink(s.getIndirectly()); // $ ast ir
}
void test_setThroughNonMember() {
S s;
s.setThroughNonMember(user_input());
sink(s.getThroughNonMember()); // $ast ir
sink(s.getThroughNonMember()); // $ ast ir
}
void test_nonMemberSetA() {
S s;
nonMemberSetA(&s, user_input());
sink(nonMemberGetA(&s)); // $ast,ir
sink(nonMemberGetA(&s)); // $ ast,ir
}
////////////////////
@@ -112,7 +112,7 @@ void test_outer_with_ptr(Outer *pouter) {
sink(outer.a); // $ ast,ir
sink(pouter->inner_nested.a); // $ ast,ir
sink(pouter->inner_ptr->a); // $ast,ir
sink(pouter->inner_ptr->a); // $ ast,ir
sink(pouter->a); // $ ast,ir
}

View File

@@ -64,7 +64,7 @@ void single_field_test()
A a;
a.i = user_input();
A a2 = a;
sink(a2.i); //$ ast,ir
sink(a2.i); // $ ast,ir
}
struct C {
@@ -81,7 +81,7 @@ struct C2
void m() {
f2.f1 = user_input();
sink(getf2f1()); //$ ast,ir
sink(getf2f1()); // $ ast,ir
}
};
@@ -91,7 +91,7 @@ void single_field_test_typedef(A_typedef a)
{
a.i = user_input();
A_typedef a2 = a;
sink(a2.i); //$ ast,ir
sink(a2.i); // $ ast,ir
}
namespace TestAdditionalCallTargets {
@@ -168,4 +168,4 @@ void test_union_with_two_instantiations_of_different_sizes() {
sink(u_int.y); // $ MISSING: ir
}
} // namespace Simple
} // namespace Simple

View File

@@ -12,14 +12,14 @@ struct Outer {
};
void absink(struct AB *ab) {
sink(ab->a); //$ ast,ir=20:20 ast,ir=27:7 ast,ir=40:20
sink(ab->a); // $ ast,ir=20:20 ast,ir=27:7 ast,ir=40:20
sink(ab->b); // no flow
}
int struct_init(void) {
struct AB ab = { user_input(), 0 };
sink(ab.a); //$ ast,ir
sink(ab.a); // $ ast,ir
sink(ab.b); // no flow
absink(&ab);
@@ -28,9 +28,9 @@ int struct_init(void) {
&ab,
};
sink(outer.nestedAB.a); //$ ast,ir
sink(outer.nestedAB.a); // $ ast,ir
sink(outer.nestedAB.b); // no flow
sink(outer.pointerAB->a); //$ ast,ir
sink(outer.pointerAB->a); // $ ast,ir
sink(outer.pointerAB->b); // no flow
absink(&outer.nestedAB);

View File

@@ -75,7 +75,7 @@ void test_sources() {
int e = localMadSource();
sink(e); // $ ir
sink(MyNamespace::namespaceLocalMadSource()); // $: ir
sink(MyNamespace::namespaceLocalMadSource()); // $ ir
sink(MyNamespace::namespaceLocalMadSourceVar); // $ ir
sink(MyNamespace::MyNamespace2::namespace2LocalMadSource()); // $ ir
sink(MyNamespace::localMadSource()); // $ (the MyNamespace version of this function is not a source)
@@ -475,4 +475,4 @@ void test_receive_array() {
int array[10] = {x};
int y = receive_array(array);
sink(y); // $ ir
}
}

View File

@@ -450,7 +450,7 @@ void test_qualifiers()
b.member = source();
sink(b); // $ ir MISSING: ast
sink(b.member); // $ ast,ir
sink(b.getMember()); // $ MISSING: ir ast
sink(b.getMember()); // $ MISSING: ir ast
c = new MyClass2(0);
@@ -865,4 +865,4 @@ void test_iconv(size_t size) {
size_t size_out;
iconv(0, &s, &size, &p, &size_out);
sink(*p); // $ ast,ir
}
}

View File

@@ -24,64 +24,64 @@ struct DerivedVI : virtual Base1 {
};
void Locals() {
Point pt = { //$ussa=pt
1, //$ussa=pt[0..4)<int>
2 //$ussa=pt[4..8)<int>
Point pt = { // $ ussa=pt
1, // $ ussa=pt[0..4)<int>
2 // $ ussa=pt[4..8)<int>
};
int i = pt.x; //$ussa=pt[0..4)<int>
i = pt.y; //$ussa=pt[4..8)<int>
int i = pt.x; // $ ussa=pt[0..4)<int>
i = pt.y; // $ ussa=pt[4..8)<int>
int* p = &pt.x;
i = *p; //$ussa=pt[0..4)<int>
i = *p; // $ ussa=pt[0..4)<int>
p = &pt.y;
i = *p; //$ussa=pt[4..8)<int>
i = *p; // $ ussa=pt[4..8)<int>
}
void PointsTo(
int a, //$raw=a
Point& b, //$raw=b ussa=*b
Point* c, //$raw=c ussa=*c
int* d, //$raw=d ussa=*d
DerivedSI* e, //$raw=e ussa=*e
DerivedMI* f, //$raw=f ussa=*f
DerivedVI* g //$raw=g ussa=*g
int a, // $ raw=a
Point& b, // $ raw=b ussa=*b
Point* c, // $ raw=c ussa=*c
int* d, // $ raw=d ussa=*d
DerivedSI* e, // $ raw=e ussa=*e
DerivedMI* f, // $ raw=f ussa=*f
DerivedVI* g // $ raw=g ussa=*g
) {
int i = a; //$raw=a
i = *&a; //$raw=a
i = *(&a + 0); //$raw=a
i = b.x; //$raw=b ussa=*b[0..4)<int>
i = b.y; //$raw=b ussa=*b[4..8)<int>
i = c->x; //$raw=c ussa=*c[0..4)<int>
i = c->y; //$raw=c ussa=*c[4..8)<int>
i = *d; //$raw=d ussa=*d[0..4)<int>
i = *(d + 0); //$raw=d ussa=*d[0..4)<int>
i = d[5]; //$raw=d ussa=*d[20..24)<int>
i = 5[d]; //$raw=d ussa=*d[20..24)<int>
i = d[a]; //$raw=d raw=a ussa=*d[?..?)<int>
i = a[d]; //$raw=d raw=a ussa=*d[?..?)<int>
int i = a; // $ raw=a
i = *&a; // $ raw=a
i = *(&a + 0); // $ raw=a
i = b.x; // $ raw=b ussa=*b[0..4)<int>
i = b.y; // $ raw=b ussa=*b[4..8)<int>
i = c->x; // $ raw=c ussa=*c[0..4)<int>
i = c->y; // $ raw=c ussa=*c[4..8)<int>
i = *d; // $ raw=d ussa=*d[0..4)<int>
i = *(d + 0); // $ raw=d ussa=*d[0..4)<int>
i = d[5]; // $ raw=d ussa=*d[20..24)<int>
i = 5[d]; // $ raw=d ussa=*d[20..24)<int>
i = d[a]; // $ raw=d raw=a ussa=*d[?..?)<int>
i = a[d]; // $ raw=d raw=a ussa=*d[?..?)<int>
int* p = &b.x; //$raw=b
i = *p; //$ussa=*b[0..4)<int>
p = &b.y; //$raw=b
i = *p; //$ussa=*b[4..8)<int>
p = &c->x; //$raw=c
i = *p; //$ussa=*c[0..4)<int>
p = &c->y; //$raw=c
i = *p; //$ussa=*c[4..8)<int>
p = &d[5]; //$raw=d
i = *p; //$ussa=*d[20..24)<int>
p = &d[a]; //$raw=d raw=a
i = *p; //$ussa=*d[?..?)<int>
int* p = &b.x; // $ raw=b
i = *p; // $ ussa=*b[0..4)<int>
p = &b.y; // $ raw=b
i = *p; // $ ussa=*b[4..8)<int>
p = &c->x; // $ raw=c
i = *p; // $ ussa=*c[0..4)<int>
p = &c->y; // $ raw=c
i = *p; // $ ussa=*c[4..8)<int>
p = &d[5]; // $ raw=d
i = *p; // $ ussa=*d[20..24)<int>
p = &d[a]; // $ raw=d raw=a
i = *p; // $ ussa=*d[?..?)<int>
Point* q = &c[a]; //$raw=c raw=a
i = q->x; //$ussa=*c[?..?)<int>
i = q->y; //$ussa=*c[?..?)<int>
Point* q = &c[a]; // $ raw=c raw=a
i = q->x; // $ ussa=*c[?..?)<int>
i = q->y; // $ ussa=*c[?..?)<int>
i = e->b1; //$raw=e ussa=*e[0..4)<int>
i = e->dsi; //$raw=e ussa=*e[4..8)<int>
i = f->b1; //$raw=f ussa=*f[0..4)<int>
i = f->b2; //$raw=f ussa=*f[4..8)<int>
i = f->dmi; //$raw=f ussa=*f[8..12)<int>
i = g->b1; //$raw=g ussa=*g[?..?)<int>
i = g->dvi; //$raw=g ussa=*g[8..12)<int>
}
i = e->b1; // $ raw=e ussa=*e[0..4)<int>
i = e->dsi; // $ raw=e ussa=*e[4..8)<int>
i = f->b1; // $ raw=f ussa=*f[0..4)<int>
i = f->b2; // $ raw=f ussa=*f[4..8)<int>
i = f->dmi; // $ raw=f ussa=*f[8..12)<int>
i = g->b1; // $ raw=g ussa=*g[?..?)<int>
i = g->dvi; // $ raw=g ussa=*g[8..12)<int>
}

View File

@@ -10,24 +10,24 @@ struct S {
void unique_ptr_init(S s) {
unique_ptr<S> p(new S); // MISSING: $ussa=dynamic{1}
int i = (*p).x; //$ MISSING: ussa=dynamic{1}[0..4)<int>
*p = s; //$ MISSING: ussa=dynamic{1}[0..4)<S>
int i = (*p).x; // $ MISSING: ussa=dynamic{1}[0..4)<int>
*p = s; // $ MISSING: ussa=dynamic{1}[0..4)<S>
unique_ptr<S> q = std::move(p);
*(q.get()) = s; //$ MISSING: ussa=dynamic{1}[0..4)<S>
*(q.get()) = s; // $ MISSING: ussa=dynamic{1}[0..4)<S>
shared_ptr<S> t(std::move(q));
t->x = 5; //$ MISSING: ussa=dynamic{1}[0..4)<int>
*t = s; //$ MISSING: ussa=dynamic{1}[0..4)<S>
*(t.get()) = s; //$ MISSING: ussa=dynamic{1}[0..4)<S>
t->x = 5; // $ MISSING: ussa=dynamic{1}[0..4)<int>
*t = s; // $ MISSING: ussa=dynamic{1}[0..4)<S>
*(t.get()) = s; // $ MISSING: ussa=dynamic{1}[0..4)<S>
}
void shared_ptr_init(S s) {
shared_ptr<S> p(new S); //$ MISSING: ussa=dynamic{1}
int i = (*p).x; //$ MISSING: ussa=dynamic{1}[0..4)<int>
*p = s; //$ MISSING: ussa=dynamic{1}[0..4)<S>
shared_ptr<S> p(new S); // $ MISSING: ussa=dynamic{1}
int i = (*p).x; // $ MISSING: ussa=dynamic{1}[0..4)<int>
*p = s; // $ MISSING: ussa=dynamic{1}[0..4)<S>
shared_ptr<S> q = std::move(p);
*(q.get()) = s; //$ MISSING: ussa=dynamic{1}[0..4)<S>
*(q.get()) = s; // $ MISSING: ussa=dynamic{1}[0..4)<S>
shared_ptr<S> t(q);
t->x = 5; //$ MISSING: ussa=dynamic{1}[0..4)<int>
*t = s; //$ MISSING: ussa=dynamic{1}[0..4)<S>
*(t.get()) = s; //$ MISSING: ussa=dynamic{1}[0..4)<S>
t->x = 5; // $ MISSING: ussa=dynamic{1}[0..4)<int>
*t = s; // $ MISSING: ussa=dynamic{1}[0..4)<S>
*(t.get()) = s; // $ MISSING: ussa=dynamic{1}[0..4)<S>
}

View File

@@ -46,7 +46,7 @@ int test4() {
}
range(total); // $ MISSING: range=>=0
range(i); // $ range===2
range(total + i); // $ range="<=Phi: i+2" MISSING: range===i+2 range=>=2 range=>=i+0
range(total + i); // $ range="<=Phi: i+2" MISSING: range===i+2 range=>=2 range=>=i+0
return total + i;
}
@@ -210,7 +210,7 @@ int test14(int x) {
int x3 = (int)(unsigned int)x;
range(x3);
char c0 = x;
range(c0);
range(c0);
unsigned short s0 = x;
range(s0);
range(x0 + x1 + x2 + x3 + c0 + s0); // $ overflow=+ overflow=+-
@@ -218,7 +218,7 @@ int test14(int x) {
}
long long test15(long long x) {
return (x > 0 && (range(x), x == (int)x)) ? // $ range=>=1
return (x > 0 && (range(x), x == (int)x)) ? // $ range=>=1
(range(x), x) : // $ range=>=1
(range(x), -1);
}
@@ -228,7 +228,7 @@ int test_unary(int a) {
int total = 0;
if (3 <= a && a <= 11) {
range(a); // $ range=<=11 range=>=3
range(a); // $ range=<=11 range=>=3
int b = +a;
range(b); // $ range=<=11 range=>=3
int c = -a;
@@ -384,7 +384,7 @@ int test_mult02(int a, int b) {
total += r;
range(total); // $ range=">=Phi: 0-143" range=">=Phi: 0-286"
}
range(total); // $range=">=Phi: 0-143" range=">=Phi: 0-286"
range(total); // $ range=">=Phi: 0-143" range=">=Phi: 0-286"
return total;
}
@@ -467,7 +467,7 @@ int test_mult04(int a, int b) {
range(a); // $ range=<=0 range=>=-17
range(b); // $ range=<=0 range=>=-13
int r = a*b; // 0 .. 221
range(r); // $ range=<=221 range=>=0
range(r); // $ range=<=221 range=>=0
total += r;
range(total); // $ range="<=Phi: - ...+221"
}
@@ -1030,7 +1030,7 @@ void test_negate_signed(int s) {
}
}
// By setting the guard after the use in another guard we
// By setting the guard after the use in another guard we
// don't get the useful information
void test_guard_after_use(int pos, int size, int offset) {
if (pos + offset >= size) { // $ overflow=+-
@@ -1040,12 +1040,12 @@ void test_guard_after_use(int pos, int size, int offset) {
return;
}
range(pos + 1); // $ overflow=+ range="==InitializeParameter: pos+1" MISSING: range="<=InitializeParameter: size-1"
}
}
int cond();
// This is basically what we get when we have a loop that calls
// This is basically what we get when we have a loop that calls
// realloc in some iterations
void alloc_in_loop(int origLen) {
if (origLen <= 10) {
@@ -1066,12 +1066,12 @@ void alloc_in_loop(int origLen) {
}
}
// This came from a case where it handled the leftovers before an unrolled loop
// This came from a case where it handled the leftovers before an unrolled loop
void mask_at_start(int len) {
if (len < 0) {
return;
}
int leftOver = len & 63;
int leftOver = len & 63;
for (int i = 0; i < leftOver; i++) {
range(i); // $ range=<=62 range=>=0 range="<=Store: ... & ... | Store: leftOver-1" range="<=InitializeParameter: len-1"
}

View File

@@ -1,14 +1,14 @@
void Complex(void) {
_Complex float cf; //$irtype=cfloat8
_Complex double cd; //$irtype=cfloat16
_Complex long double cld; //$irtype=cfloat32
_Complex float cf; // $ irtype=cfloat8
_Complex double cd; // $ irtype=cfloat16
_Complex long double cld; // $ irtype=cfloat32
// _Complex __float128 cf128;
}
void Imaginary(void) {
_Imaginary float jf; //$irtype=ifloat4
_Imaginary double jd; //$irtype=ifloat8
_Imaginary long double jld; //$irtype=ifloat16
_Imaginary float jf; // $ irtype=ifloat4
_Imaginary double jd; // $ irtype=ifloat8
_Imaginary long double jld; // $ irtype=ifloat16
// _Imaginary __float128 jf128;
}

View File

@@ -22,44 +22,44 @@ enum class ScopedE {
};
void IRTypes() {
char c; //$irtype=int1
signed char sc; //$irtype=int1
unsigned char uc; //$irtype=uint1
short s; //$irtype=int2
signed short ss; //$irtype=int2
unsigned short us; //$irtype=uint2
int i; //$irtype=int4
signed int si; //$irtype=int4
unsigned int ui; //$irtype=uint4
long l; //$irtype=int8
signed long sl; //$irtype=int8
unsigned long ul; //$irtype=uint8
long long ll; //$irtype=int8
signed long long sll; //$irtype=int8
unsigned long long ull; //$irtype=uint8
bool b; //$irtype=bool1
float f; //$irtype=float4
double d; //$irtype=float8
long double ld; //$irtype=float16
__float128 f128; //$irtype=float16
char c; // $ irtype=int1
signed char sc; // $ irtype=int1
unsigned char uc; // $ irtype=uint1
short s; // $ irtype=int2
signed short ss; // $ irtype=int2
unsigned short us; // $ irtype=uint2
int i; // $ irtype=int4
signed int si; // $ irtype=int4
unsigned int ui; // $ irtype=uint4
long l; // $ irtype=int8
signed long sl; // $ irtype=int8
unsigned long ul; // $ irtype=uint8
long long ll; // $ irtype=int8
signed long long sll; // $ irtype=int8
unsigned long long ull; // $ irtype=uint8
bool b; // $ irtype=bool1
float f; // $ irtype=float4
double d; // $ irtype=float8
long double ld; // $ irtype=float16
__float128 f128; // $ irtype=float16
wchar_t wc; //$irtype=uint4
// char8_t c8; //$irtype=uint1
char16_t c16; //$irtype=uint2
char32_t c32; //$irtype=uint4
wchar_t wc; // $ irtype=uint4
// char8_t c8; // $ irtype=uint1
char16_t c16; // $ irtype=uint2
char32_t c32; // $ irtype=uint4
int* pi; //$irtype=addr8
int& ri = i; //$irtype=addr8
void (*pfn)() = nullptr; //$irtype=func8
void (&rfn)() = IRTypes; //$irtype=func8
int* pi; // $ irtype=addr8
int& ri = i; // $ irtype=addr8
void (*pfn)() = nullptr; // $ irtype=func8
void (&rfn)() = IRTypes; // $ irtype=func8
A s_a; //$irtype=opaque4{A}
B s_b; //$irtype=opaque16{B}
A s_a; // $ irtype=opaque4{A}
B s_b; // $ irtype=opaque16{B}
E e; //$irtype=uint4
ScopedE se; //$irtype=uint4
E e; // $ irtype=uint4
ScopedE se; // $ irtype=uint4
B a_b[10]; //$irtype=opaque160{B[10]}
B a_b[10]; // $ irtype=opaque160{B[10]}
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -0,0 +1,28 @@
// semmle-extractor-options: --expect_errors
void test_float_double1(float f, double d) {
float r1 = f * f; // GOOD
float r2 = f * d; // GOOD
double r3 = f * f; // BAD
double r4 = f * d; // GOOD
float f1 = fabsf(f * f); // GOOD
float f2 = fabsf(f * d); // GOOD
double f3 = fabs(f * f); // BAD [NOT DETECTED]
double f4 = fabs(f * d); // GOOD
}
double fabs(double f);
float fabsf(float f);
void test_float_double2(float f, double d) {
float r1 = f * f; // GOOD
float r2 = f * d; // GOOD
double r3 = f * f; // BAD
double r4 = f * d; // GOOD
float f1 = fabsf(f * f); // GOOD
float f2 = fabsf(f * d); // GOOD
double f3 = fabs(f * f); // BAD [NOT DETECTED]
double f4 = fabs(f * d); // GOOD
}

View File

@@ -1,3 +1,5 @@
| Buildless.c:6:17:6:21 | ... * ... | Multiplication result may overflow 'float' before it is converted to 'double'. |
| Buildless.c:21:17:21:21 | ... * ... | Multiplication result may overflow 'float' before it is converted to 'double'. |
| IntMultToLong.c:4:10:4:14 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'long long'. |
| IntMultToLong.c:7:16:7:20 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'long long'. |
| IntMultToLong.c:18:19:18:23 | ... * ... | Multiplication result may overflow 'float' before it is converted to 'double'. |

View File

@@ -1338,7 +1338,7 @@ void indirect_time_conversion_check(WORD year, WORD offset){
void set_time(WORD year, WORD month, WORD day){
SYSTEMTIME tmp;
tmp.wYear = year; //$ Alert[cpp/leap-year/unchecked-after-arithmetic-year-modification]
tmp.wYear = year; // $ Alert[cpp/leap-year/unchecked-after-arithmetic-year-modification]
tmp.wMonth = month;
tmp.wDay = day;
}