mirror of
https://github.com/github/codeql.git
synced 2026-05-02 12:15:17 +02:00
Merge from main
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.EscapesTree
|
||||
import semmle.code.cpp.models.interfaces.PointerWrapper
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
|
||||
/**
|
||||
@@ -39,6 +40,10 @@ predicate hasNontrivialConversion(Expr e) {
|
||||
e instanceof ParenthesisExpr
|
||||
)
|
||||
or
|
||||
// A smart pointer can be stack-allocated while the data it points to is heap-allocated.
|
||||
// So we exclude such "conversions" from this predicate.
|
||||
e = any(PointerWrapper wrapper).getAnUnwrapperFunction().getACallToThisFunction()
|
||||
or
|
||||
hasNontrivialConversion(e.getConversion())
|
||||
}
|
||||
|
||||
|
||||
@@ -11,54 +11,32 @@
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.models.implementations.Strcat
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
|
||||
/**
|
||||
* A call to `strncat` of the form `strncat(buff, str, someExpr - strlen(buf))`, for some expression `someExpr` equal to `sizeof(buff)`.
|
||||
* Holds if `call` is a call to `strncat` such that `sizeArg` and `destArg` are the size and
|
||||
* destination arguments, respectively.
|
||||
*/
|
||||
class WrongCallStrncat extends FunctionCall {
|
||||
Expr leftsomeExpr;
|
||||
|
||||
WrongCallStrncat() {
|
||||
this.getTarget().hasGlobalOrStdName("strncat") and
|
||||
// the expression of the first argument in `strncat` and `strnlen` is identical
|
||||
globalValueNumber(this.getArgument(0)) =
|
||||
globalValueNumber(this.getArgument(2).(SubExpr).getRightOperand().(StrlenCall).getStringExpr()) and
|
||||
// using a string constant often speaks of manually calculating the length of the required buffer.
|
||||
(
|
||||
not this.getArgument(1) instanceof StringLiteral and
|
||||
not this.getArgument(1) instanceof CharLiteral
|
||||
) and
|
||||
// for use in predicates
|
||||
leftsomeExpr = this.getArgument(2).(SubExpr).getLeftOperand()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the left side of the expression `someExpr` equal to `sizeof(buf)`.
|
||||
*/
|
||||
predicate isExpressionEqualSizeof() {
|
||||
// the left side of the expression `someExpr` is `sizeof(buf)`.
|
||||
globalValueNumber(this.getArgument(0)) =
|
||||
globalValueNumber(leftsomeExpr.(SizeofExprOperator).getExprOperand())
|
||||
or
|
||||
// value of the left side of the expression `someExpr` equal `sizeof(buf)` value, and `buf` is array.
|
||||
leftsomeExpr.getValue().toInt() = this.getArgument(0).getType().getSize()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the left side of the expression `someExpr` equal to variable containing the length of the memory allocated for the buffer.
|
||||
*/
|
||||
predicate isVariableEqualValueSizegBuffer() {
|
||||
// the left side of expression `someExpr` is the variable that was used in the function of allocating memory for the buffer`.
|
||||
exists(AllocationExpr alc |
|
||||
leftsomeExpr.(VariableAccess).getTarget() =
|
||||
alc.(FunctionCall).getArgument(0).(VariableAccess).getTarget()
|
||||
)
|
||||
}
|
||||
predicate interestringCallWithArgs(Call call, Expr sizeArg, Expr destArg) {
|
||||
exists(StrcatFunction strcat |
|
||||
strcat = call.getTarget() and
|
||||
sizeArg = call.getArgument(strcat.getParamSize()) and
|
||||
destArg = call.getArgument(strcat.getParamDest())
|
||||
)
|
||||
}
|
||||
|
||||
from WrongCallStrncat sc
|
||||
from FunctionCall call, Expr sizeArg, Expr destArg, SubExpr sub, int n
|
||||
where
|
||||
sc.isExpressionEqualSizeof() or
|
||||
sc.isVariableEqualValueSizegBuffer()
|
||||
select sc, "if the used buffer is full, writing out of the buffer is possible"
|
||||
interestringCallWithArgs(call, sizeArg, destArg) and
|
||||
// The destination buffer is an array of size n
|
||||
destArg.getUnspecifiedType().(ArrayType).getSize() = n and
|
||||
// The size argument is equivalent to a subtraction
|
||||
globalValueNumber(sizeArg).getAnExpr() = sub and
|
||||
// ... where the left side of the subtraction is the constant n
|
||||
globalValueNumber(sub.getLeftOperand()).getAnExpr().getValue().toInt() = n and
|
||||
// ... and the right side of the subtraction is a call to `strlen` where the argument is the
|
||||
// destination buffer.
|
||||
globalValueNumber(sub.getRightOperand()).getAnExpr().(StrlenCall).getStringExpr() =
|
||||
globalValueNumber(destArg).getAnExpr()
|
||||
select call, "Possible out-of-bounds write due to incorrect size argument."
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
| test.c:42:3:42:24 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:43:3:43:40 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:44:3:44:40 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:45:3:45:44 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:46:3:46:44 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:47:3:47:48 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:48:3:48:48 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:49:3:49:50 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:50:3:50:50 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:54:3:54:24 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:55:3:55:40 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:56:3:56:44 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:57:3:57:44 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:58:3:58:48 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:59:3:59:48 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:60:3:60:52 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:61:3:61:50 | ... = ... | potential unsafe or redundant assignment. |
|
||||
| test.c:62:3:62:54 | ... = ... | potential unsafe or redundant assignment. |
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
| test.c:4:3:4:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible |
|
||||
| test.c:11:3:11:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible |
|
||||
| test.c:19:3:19:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible |
|
||||
| test.c:8:3:8:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
|
||||
| test.c:9:3:9:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
|
||||
| test.c:17:3:17:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
|
||||
| test.c:18:3:18:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
|
||||
| test.c:46:3:46:9 | call to strncat | Possible out-of-bounds write due to incorrect size argument. |
|
||||
|
||||
@@ -1,70 +1,84 @@
|
||||
void workFunction_0(char *s) {
|
||||
char * strncat(char*, const char*, unsigned);
|
||||
unsigned strlen(const char*);
|
||||
void* malloc(unsigned);
|
||||
|
||||
void strncat_test1(char *s) {
|
||||
char buf[80];
|
||||
strncat(buf, s, sizeof(buf)-strlen(buf)-1); // GOOD
|
||||
strncat(buf, s, sizeof(buf)-strlen(buf)); // BAD
|
||||
strncat(buf, "fix", sizeof(buf)-strlen(buf)); // BAD [NOT DETECTED]
|
||||
strncat(buf, s, sizeof(buf) - strlen(buf) - 1); // GOOD
|
||||
strncat(buf, s, sizeof(buf) - strlen(buf)); // BAD
|
||||
strncat(buf, "fix", sizeof(buf)-strlen(buf)); // BAD
|
||||
}
|
||||
void workFunction_1(char *s) {
|
||||
|
||||
#define MAX_SIZE 80
|
||||
|
||||
void strncat_test2(char *s) {
|
||||
char buf[MAX_SIZE];
|
||||
strncat(buf, s, MAX_SIZE-strlen(buf)-1); // GOOD
|
||||
strncat(buf, s, MAX_SIZE-strlen(buf)); // BAD
|
||||
strncat(buf, "fix", MAX_SIZE-strlen(buf)); // BAD [NOT DETECTED]
|
||||
strncat(buf, s, MAX_SIZE - strlen(buf) - 1); // GOOD
|
||||
strncat(buf, s, MAX_SIZE - strlen(buf)); // BAD
|
||||
strncat(buf, "fix", MAX_SIZE - strlen(buf)); // BAD
|
||||
}
|
||||
void workFunction_2_0(char *s) {
|
||||
char * buf;
|
||||
int len=80;
|
||||
buf = (char *) malloc(len);
|
||||
strncat(buf, s, len-strlen(buf)-1); // GOOD
|
||||
strncat(buf, s, len-strlen(buf)); // BAD
|
||||
strncat(buf, "fix", len-strlen(buf)); // BAD [NOT DETECTED]
|
||||
|
||||
void strncat_test3(char *s) {
|
||||
int len = 80;
|
||||
char* buf = (char *) malloc(len);
|
||||
strncat(buf, s, len - strlen(buf) - 1); // GOOD
|
||||
strncat(buf, s, len - strlen(buf)); // BAD [NOT DETECTED]
|
||||
strncat(buf, "fix", len - strlen(buf)); // BAD [NOT DETECTED]
|
||||
}
|
||||
void workFunction_2_1(char *s) {
|
||||
char * buf;
|
||||
int len=80;
|
||||
buf = (char *) malloc(len+1);
|
||||
strncat(buf, s, len-strlen(buf)-1); // GOOD
|
||||
strncat(buf, s, len-strlen(buf)); // GOOD
|
||||
|
||||
void strncat_test4(char *s) {
|
||||
int len = 80;
|
||||
char* buf = (char *) malloc(len + 1);
|
||||
strncat(buf, s, len - strlen(buf) - 1); // GOOD
|
||||
strncat(buf, s, len - strlen(buf)); // GOOD
|
||||
}
|
||||
|
||||
struct buffers
|
||||
{
|
||||
unsigned char buff1[50];
|
||||
unsigned char *buff2;
|
||||
unsigned char array[50];
|
||||
unsigned char *pointer;
|
||||
} globalBuff1,*globalBuff2,globalBuff1_c,*globalBuff2_c;
|
||||
|
||||
void strncat_test5(char* s, struct buffers* buffers) {
|
||||
unsigned len_array = strlen(buffers->array);
|
||||
unsigned max_size = sizeof(buffers->array);
|
||||
unsigned free_size = max_size - len_array;
|
||||
strncat(buffers->array, s, free_size); // BAD
|
||||
}
|
||||
|
||||
void badFunc0(){
|
||||
void strlen_test1(){
|
||||
unsigned char buff1[12];
|
||||
struct buffers buffAll;
|
||||
struct buffers * buffAll1;
|
||||
|
||||
buff1[strlen(buff1)]=0; // BAD
|
||||
buffAll.buff1[strlen(buffAll.buff1)]=0; // BAD
|
||||
buffAll.buff2[strlen(buffAll.buff2)]=0; // BAD
|
||||
buffAll1->buff1[strlen(buffAll1->buff1)]=0; // BAD
|
||||
buffAll1->buff2[strlen(buffAll1->buff2)]=0; // BAD
|
||||
globalBuff1.buff1[strlen(globalBuff1.buff1)]=0; // BAD
|
||||
globalBuff1.buff2[strlen(globalBuff1.buff2)]=0; // BAD
|
||||
globalBuff2->buff1[strlen(globalBuff2->buff1)]=0; // BAD
|
||||
globalBuff2->buff2[strlen(globalBuff2->buff2)]=0; // BAD
|
||||
buffAll.array[strlen(buffAll.array)]=0; // BAD
|
||||
buffAll.pointer[strlen(buffAll.pointer)]=0; // BAD
|
||||
buffAll1->array[strlen(buffAll1->array)]=0; // BAD
|
||||
buffAll1->pointer[strlen(buffAll1->pointer)]=0; // BAD
|
||||
globalBuff1.array[strlen(globalBuff1.array)]=0; // BAD
|
||||
globalBuff1.pointer[strlen(globalBuff1.pointer)]=0; // BAD
|
||||
globalBuff2->array[strlen(globalBuff2->array)]=0; // BAD
|
||||
globalBuff2->pointer[strlen(globalBuff2->pointer)]=0; // BAD
|
||||
}
|
||||
void noBadFunc0(){
|
||||
|
||||
void strlen_test2(){
|
||||
unsigned char buff1[12],buff1_c[12];
|
||||
struct buffers buffAll,buffAll_c;
|
||||
struct buffers * buffAll1,*buffAll1_c;
|
||||
|
||||
buff1[strlen(buff1_c)]=0; // GOOD
|
||||
buffAll.buff1[strlen(buffAll_c.buff1)]=0; // GOOD
|
||||
buffAll.buff2[strlen(buffAll.buff1)]=0; // GOOD
|
||||
buffAll1->buff1[strlen(buffAll1_c->buff1)]=0; // GOOD
|
||||
buffAll1->buff2[strlen(buffAll1->buff1)]=0; // GOOD
|
||||
globalBuff1.buff1[strlen(globalBuff1_c.buff1)]=0; // GOOD
|
||||
globalBuff1.buff2[strlen(globalBuff1.buff1)]=0; // GOOD
|
||||
globalBuff2->buff1[strlen(globalBuff2_c->buff1)]=0; // GOOD
|
||||
globalBuff2->buff2[strlen(globalBuff2->buff1)]=0; // GOOD
|
||||
buffAll.array[strlen(buffAll_c.array)]=0; // GOOD
|
||||
buffAll.pointer[strlen(buffAll.array)]=0; // GOOD
|
||||
buffAll1->array[strlen(buffAll1_c->array)]=0; // GOOD
|
||||
buffAll1->pointer[strlen(buffAll1->array)]=0; // GOOD
|
||||
globalBuff1.array[strlen(globalBuff1_c.array)]=0; // GOOD
|
||||
globalBuff1.pointer[strlen(globalBuff1.array)]=0; // GOOD
|
||||
globalBuff2->array[strlen(globalBuff2_c->array)]=0; // GOOD
|
||||
globalBuff2->pointer[strlen(globalBuff2->array)]=0; // GOOD
|
||||
}
|
||||
void goodFunc0(){
|
||||
|
||||
void strlen_test3(){
|
||||
unsigned char buffer[12];
|
||||
int i;
|
||||
for(i = 0; i < 6; i++)
|
||||
|
||||
@@ -7,7 +7,7 @@ void test_unique_ptr_int() {
|
||||
std::unique_ptr<int> p1(new int(source()));
|
||||
std::unique_ptr<int> p2 = std::make_unique<int>(source());
|
||||
|
||||
sink(*p1); // $ MISSING: ast,ir
|
||||
sink(*p1); // $ ir MISSING: ast
|
||||
sink(*p2); // $ ast ir=8:50
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ void test_unique_ptr_struct() {
|
||||
std::unique_ptr<A> p1(new A{source(), 0});
|
||||
std::unique_ptr<A> p2 = std::make_unique<A>(source(), 0);
|
||||
|
||||
sink(p1->x); // $ MISSING: ast,ir
|
||||
sink(p1->x); // $ ir MISSING: ast
|
||||
sink(p1->y);
|
||||
sink(p2->x); // $ MISSING: ast,ir
|
||||
sink(p2->y);
|
||||
@@ -31,7 +31,7 @@ void test_shared_ptr_int() {
|
||||
std::shared_ptr<int> p1(new int(source()));
|
||||
std::shared_ptr<int> p2 = std::make_shared<int>(source());
|
||||
|
||||
sink(*p1); // $ ast
|
||||
sink(*p1); // $ ast ir
|
||||
sink(*p2); // $ ast ir=32:50
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ void test_shared_ptr_struct() {
|
||||
std::shared_ptr<A> p1(new A{source(), 0});
|
||||
std::shared_ptr<A> p2 = std::make_shared<A>(source(), 0);
|
||||
|
||||
sink(p1->x); // $ MISSING: ast,ir
|
||||
sink(p1->x); // $ ir MISSING: ast
|
||||
sink(p1->y);
|
||||
sink(p2->x); // $ MISSING: ast,ir
|
||||
sink(p2->y);
|
||||
|
||||
@@ -3275,11 +3275,11 @@
|
||||
| smart_pointer.cpp:51:30:51:50 | call to make_shared | smart_pointer.cpp:52:10:52:10 | p | |
|
||||
| smart_pointer.cpp:51:52:51:57 | call to source | smart_pointer.cpp:51:30:51:50 | call to make_shared | TAINT |
|
||||
| smart_pointer.cpp:52:10:52:10 | p | smart_pointer.cpp:52:12:52:14 | call to get | |
|
||||
| smart_pointer.cpp:52:12:52:14 | ref arg call to get | smart_pointer.cpp:52:10:52:10 | ref arg p | |
|
||||
| smart_pointer.cpp:52:12:52:14 | ref arg call to get | smart_pointer.cpp:52:10:52:10 | ref arg p | TAINT |
|
||||
| smart_pointer.cpp:56:30:56:50 | call to make_unique | smart_pointer.cpp:57:10:57:10 | p | |
|
||||
| smart_pointer.cpp:56:52:56:57 | call to source | smart_pointer.cpp:56:30:56:50 | call to make_unique | TAINT |
|
||||
| smart_pointer.cpp:57:10:57:10 | p | smart_pointer.cpp:57:12:57:14 | call to get | |
|
||||
| smart_pointer.cpp:57:12:57:14 | ref arg call to get | smart_pointer.cpp:57:10:57:10 | ref arg p | |
|
||||
| smart_pointer.cpp:57:12:57:14 | ref arg call to get | smart_pointer.cpp:57:10:57:10 | ref arg p | TAINT |
|
||||
| smart_pointer.cpp:65:28:65:46 | call to make_unique | smart_pointer.cpp:66:10:66:10 | p | |
|
||||
| smart_pointer.cpp:65:28:65:46 | call to make_unique | smart_pointer.cpp:67:10:67:10 | p | |
|
||||
| smart_pointer.cpp:65:48:65:53 | call to source | smart_pointer.cpp:65:28:65:46 | call to make_unique | TAINT |
|
||||
@@ -3319,7 +3319,7 @@
|
||||
| smart_pointer.cpp:87:3:87:3 | ref arg p | smart_pointer.cpp:89:8:89:8 | p | |
|
||||
| smart_pointer.cpp:87:3:87:17 | ... = ... | smart_pointer.cpp:87:6:87:6 | x [post update] | |
|
||||
| smart_pointer.cpp:87:3:87:17 | ... = ... | smart_pointer.cpp:88:11:88:11 | x | |
|
||||
| smart_pointer.cpp:87:4:87:4 | call to operator-> [post update] | smart_pointer.cpp:87:3:87:3 | ref arg p | |
|
||||
| smart_pointer.cpp:87:4:87:4 | call to operator-> [post update] | smart_pointer.cpp:87:3:87:3 | ref arg p | TAINT |
|
||||
| smart_pointer.cpp:87:10:87:15 | call to source | smart_pointer.cpp:87:3:87:17 | ... = ... | |
|
||||
| smart_pointer.cpp:88:8:88:8 | p | smart_pointer.cpp:88:9:88:9 | call to operator-> | |
|
||||
| smart_pointer.cpp:88:8:88:8 | ref arg p | smart_pointer.cpp:86:45:86:45 | p | |
|
||||
@@ -3333,7 +3333,7 @@
|
||||
| smart_pointer.cpp:91:3:91:3 | ref arg q | smart_pointer.cpp:94:8:94:8 | q | |
|
||||
| smart_pointer.cpp:91:3:91:20 | ... = ... | smart_pointer.cpp:91:9:91:9 | x [post update] | |
|
||||
| smart_pointer.cpp:91:3:91:20 | ... = ... | smart_pointer.cpp:92:14:92:14 | x | |
|
||||
| smart_pointer.cpp:91:4:91:4 | call to operator-> [post update] | smart_pointer.cpp:91:3:91:3 | ref arg q | |
|
||||
| smart_pointer.cpp:91:4:91:4 | call to operator-> [post update] | smart_pointer.cpp:91:3:91:3 | ref arg q | TAINT |
|
||||
| smart_pointer.cpp:91:13:91:18 | call to source | smart_pointer.cpp:91:3:91:20 | ... = ... | |
|
||||
| smart_pointer.cpp:92:8:92:8 | q | smart_pointer.cpp:92:9:92:9 | call to operator-> | |
|
||||
| smart_pointer.cpp:92:8:92:8 | ref arg q | smart_pointer.cpp:86:67:86:67 | q | |
|
||||
@@ -3351,21 +3351,21 @@
|
||||
| smart_pointer.cpp:102:25:102:50 | call to unique_ptr | smart_pointer.cpp:104:8:104:8 | p | |
|
||||
| smart_pointer.cpp:103:11:103:11 | p | smart_pointer.cpp:103:13:103:15 | call to get | |
|
||||
| smart_pointer.cpp:103:11:103:11 | ref arg p | smart_pointer.cpp:104:8:104:8 | p | |
|
||||
| smart_pointer.cpp:103:13:103:15 | ref arg call to get | smart_pointer.cpp:103:11:103:11 | ref arg p | |
|
||||
| smart_pointer.cpp:103:13:103:15 | ref arg call to get | smart_pointer.cpp:103:11:103:11 | ref arg p | TAINT |
|
||||
| smart_pointer.cpp:104:8:104:8 | p | smart_pointer.cpp:104:9:104:9 | call to operator-> | |
|
||||
| smart_pointer.cpp:112:40:112:42 | ptr | smart_pointer.cpp:112:40:112:42 | ptr | |
|
||||
| smart_pointer.cpp:112:40:112:42 | ptr | smart_pointer.cpp:113:2:113:4 | ptr | |
|
||||
| smart_pointer.cpp:113:2:113:4 | ptr | smart_pointer.cpp:113:5:113:5 | call to operator-> | |
|
||||
| smart_pointer.cpp:113:2:113:4 | ref arg ptr | smart_pointer.cpp:112:40:112:42 | ptr | |
|
||||
| smart_pointer.cpp:113:2:113:18 | ... = ... | smart_pointer.cpp:113:7:113:7 | x [post update] | |
|
||||
| smart_pointer.cpp:113:5:113:5 | call to operator-> [post update] | smart_pointer.cpp:113:2:113:4 | ref arg ptr | |
|
||||
| smart_pointer.cpp:113:5:113:5 | call to operator-> [post update] | smart_pointer.cpp:113:2:113:4 | ref arg ptr | TAINT |
|
||||
| smart_pointer.cpp:113:11:113:16 | call to source | smart_pointer.cpp:113:2:113:18 | ... = ... | |
|
||||
| smart_pointer.cpp:116:52:116:54 | ptr | smart_pointer.cpp:116:52:116:54 | ptr | |
|
||||
| smart_pointer.cpp:116:52:116:54 | ptr | smart_pointer.cpp:117:2:117:4 | ptr | |
|
||||
| smart_pointer.cpp:117:2:117:4 | ptr | smart_pointer.cpp:117:5:117:5 | call to operator-> | |
|
||||
| smart_pointer.cpp:117:2:117:4 | ref arg ptr | smart_pointer.cpp:116:52:116:54 | ptr | |
|
||||
| smart_pointer.cpp:117:2:117:18 | ... = ... | smart_pointer.cpp:117:7:117:7 | x [post update] | |
|
||||
| smart_pointer.cpp:117:5:117:5 | call to operator-> [post update] | smart_pointer.cpp:117:2:117:4 | ref arg ptr | |
|
||||
| smart_pointer.cpp:117:5:117:5 | call to operator-> [post update] | smart_pointer.cpp:117:2:117:4 | ref arg ptr | TAINT |
|
||||
| smart_pointer.cpp:117:11:117:16 | call to source | smart_pointer.cpp:117:2:117:18 | ... = ... | |
|
||||
| smart_pointer.cpp:120:48:120:50 | ptr | smart_pointer.cpp:120:48:120:50 | ptr | |
|
||||
| smart_pointer.cpp:120:48:120:50 | ptr | smart_pointer.cpp:121:4:121:6 | ptr | |
|
||||
@@ -3386,12 +3386,12 @@
|
||||
| smart_pointer.cpp:125:18:125:19 | ref arg p1 | smart_pointer.cpp:124:48:124:49 | p1 | |
|
||||
| smart_pointer.cpp:125:18:125:19 | ref arg p1 | smart_pointer.cpp:126:8:126:9 | p1 | |
|
||||
| smart_pointer.cpp:125:18:125:22 | ref arg call to shared_ptr | smart_pointer.cpp:125:22:125:22 | q [inner post update] | |
|
||||
| smart_pointer.cpp:125:20:125:20 | call to operator-> [post update] | smart_pointer.cpp:125:18:125:19 | ref arg p1 | |
|
||||
| smart_pointer.cpp:125:20:125:20 | call to operator-> [post update] | smart_pointer.cpp:125:18:125:19 | ref arg p1 | TAINT |
|
||||
| smart_pointer.cpp:125:22:125:22 | q | smart_pointer.cpp:125:18:125:22 | call to shared_ptr | |
|
||||
| smart_pointer.cpp:125:22:125:22 | ref arg q | smart_pointer.cpp:125:22:125:22 | q [inner post update] | |
|
||||
| smart_pointer.cpp:126:8:126:9 | p1 | smart_pointer.cpp:126:10:126:10 | call to operator-> | |
|
||||
| smart_pointer.cpp:126:8:126:9 | ref arg p1 | smart_pointer.cpp:124:48:124:49 | p1 | |
|
||||
| smart_pointer.cpp:126:10:126:10 | call to operator-> [post update] | smart_pointer.cpp:126:8:126:9 | ref arg p1 | |
|
||||
| smart_pointer.cpp:126:10:126:10 | call to operator-> [post update] | smart_pointer.cpp:126:8:126:9 | ref arg p1 | TAINT |
|
||||
| smart_pointer.cpp:126:12:126:12 | q | smart_pointer.cpp:126:13:126:13 | call to operator-> | |
|
||||
| smart_pointer.cpp:128:13:128:13 | call to operator* | smart_pointer.cpp:128:13:128:15 | call to shared_ptr | TAINT |
|
||||
| smart_pointer.cpp:128:13:128:13 | ref arg call to operator* | smart_pointer.cpp:124:90:124:91 | p2 | |
|
||||
@@ -3422,10 +3422,10 @@
|
||||
| smart_pointer.cpp:133:23:133:24 | p1 | smart_pointer.cpp:133:25:133:25 | call to operator-> | |
|
||||
| smart_pointer.cpp:133:23:133:24 | ref arg p1 | smart_pointer.cpp:132:53:132:54 | p1 | |
|
||||
| smart_pointer.cpp:133:23:133:24 | ref arg p1 | smart_pointer.cpp:134:8:134:9 | p1 | |
|
||||
| smart_pointer.cpp:133:25:133:25 | call to operator-> [post update] | smart_pointer.cpp:133:23:133:24 | ref arg p1 | |
|
||||
| smart_pointer.cpp:133:25:133:25 | call to operator-> [post update] | smart_pointer.cpp:133:23:133:24 | ref arg p1 | TAINT |
|
||||
| smart_pointer.cpp:134:8:134:9 | p1 | smart_pointer.cpp:134:10:134:10 | call to operator-> | |
|
||||
| smart_pointer.cpp:134:8:134:9 | ref arg p1 | smart_pointer.cpp:132:53:132:54 | p1 | |
|
||||
| smart_pointer.cpp:134:10:134:10 | call to operator-> [post update] | smart_pointer.cpp:134:8:134:9 | ref arg p1 | |
|
||||
| smart_pointer.cpp:134:10:134:10 | call to operator-> [post update] | smart_pointer.cpp:134:8:134:9 | ref arg p1 | TAINT |
|
||||
| smart_pointer.cpp:134:12:134:12 | q | smart_pointer.cpp:134:13:134:13 | call to operator-> | |
|
||||
| smart_pointer.cpp:136:17:136:17 | ref arg call to operator* | smart_pointer.cpp:132:95:132:96 | p2 | |
|
||||
| smart_pointer.cpp:136:17:136:17 | ref arg call to operator* | smart_pointer.cpp:136:18:136:19 | p2 [inner post update] | |
|
||||
|
||||
@@ -189,3 +189,30 @@ int *&conversionInFlow() {
|
||||
int *&pRef = p; // has conversion in the middle of data flow
|
||||
return pRef; // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<typename T>
|
||||
class shared_ptr {
|
||||
public:
|
||||
shared_ptr() noexcept;
|
||||
explicit shared_ptr(T*);
|
||||
shared_ptr(const shared_ptr&) noexcept;
|
||||
template<class U> shared_ptr(const shared_ptr<U>&) noexcept;
|
||||
template<class U> shared_ptr(shared_ptr<U>&&) noexcept;
|
||||
|
||||
shared_ptr<T>& operator=(const shared_ptr<T>&) noexcept;
|
||||
shared_ptr<T>& operator=(shared_ptr<T>&&) noexcept;
|
||||
|
||||
T& operator*() const noexcept;
|
||||
T* operator->() const noexcept;
|
||||
|
||||
T* get() const noexcept;
|
||||
};
|
||||
}
|
||||
|
||||
auto make_read_port()
|
||||
{
|
||||
auto port = std::shared_ptr<int>(new int);
|
||||
auto ptr = port.get();
|
||||
return ptr; // GOOD
|
||||
}
|
||||
Reference in New Issue
Block a user