From bddb5fd9f9ff7d6615f48d162c1f9c290e637493 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Fri, 25 Feb 2022 11:14:20 +0300 Subject: [PATCH 01/21] Add files via upload --- .../CWE-754/ImproperCheckReturnValueScanf.cpp | 10 ++ .../ImproperCheckReturnValueScanf.qhelp | 22 ++++ .../CWE-754/ImproperCheckReturnValueScanf.ql | 108 ++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.cpp create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.cpp b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.cpp new file mode 100644 index 000000000000..432f144b4bb2 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.cpp @@ -0,0 +1,10 @@ +... + r = scanf("%i", i); + if (r == 1) // GOOD + return i; + else + return -1; +... + scanf("%i", i); // BAD + return i; +... diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp new file mode 100644 index 000000000000..2e60d33f89ab --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp @@ -0,0 +1,22 @@ + + + +

Working with reading data without validation procedures and with uninitialized arguments can lead to unpredictable consequences.

+ + + +

The following example demonstrates erroneous and corrected work with a function call.

+ + +
+ + +
  • + CERT C Coding Standard: + EXP12-C. Do not ignore values returned by functions. +
  • + +
    +
    diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql new file mode 100644 index 000000000000..4dc141be2474 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql @@ -0,0 +1,108 @@ +/** + * @name Improper check return value scanf. + * @description Using a function call without the ability to evaluate the correctness of the work can lead to unexpected results. + * @kind problem + * @id cpp/improper-check-return-value-scanf + * @problem.severity warning + * @precision medium + * @tags correctness + * security + * external/cwe/cwe-754 + * external/cwe/cwe-908 + */ + +import cpp +import semmle.code.cpp.commons.Exclusions +import semmle.code.cpp.valuenumbering.GlobalValueNumbering + +/** Returns the starting position of the argument being filled. */ +int posArgumentInFunctionCall(FunctionCall fc) { + ( + ( + fc.getTarget().hasGlobalOrStdName("scanf") or + fc.getTarget().hasGlobalOrStdName("scanf_s") + ) and + result = 1 + or + ( + fc.getTarget().hasGlobalOrStdName("fscanf") or + fc.getTarget().hasGlobalOrStdName("sscanf") or + fc.getTarget().hasGlobalOrStdName("fscanf_s") or + fc.getTarget().hasGlobalOrStdName("sscanf_s") + ) and + result = 2 + ) +} + +from FunctionCall fc, int n +where + n = posArgumentInFunctionCall(fc) and + // Function return value is not evaluated. + fc instanceof ExprInVoidContext and + not isFromMacroDefinition(fc) and + exists(Expr e0, int i | + i in [n .. fc.getNumberOfArguments() - 1] and + // Fillable argument was not initialized. + ( + fc.getArgument(i).(VariableAccess).getTarget() instanceof LocalScopeVariable or + fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() instanceof + LocalScopeVariable + ) and + ( + not fc.getArgument(i).(VariableAccess).getTarget().hasInitializer() and + not fc.getArgument(i) + .(AddressOfExpr) + .getOperand() + .(VariableAccess) + .getTarget() + .hasInitializer() + ) and + ( + not fc.getArgument(i).(VariableAccess).getTarget().getAnAssignment().getASuccessor+() = fc and + not fc.getArgument(i) + .(AddressOfExpr) + .getOperand() + .(VariableAccess) + .getTarget() + .getAnAssignment() + .getASuccessor+() = fc + ) and + // After the call, the completed arguments are assigned or returned as the result of the operation of the upper function. + fc.getASuccessor+() = e0 and + ( + ( + e0.(Assignment).getRValue().(VariableAccess).getTarget() = + fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() or + e0.(Assignment).getRValue().(VariableAccess).getTarget() = + fc.getArgument(i).(VariableAccess).getTarget() + ) + or + e0.getEnclosingStmt() instanceof ReturnStmt and + ( + e0.(VariableAccess).getTarget() = + fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() or + e0.(VariableAccess).getTarget() = fc.getArgument(i).(VariableAccess).getTarget() + ) + or + not exists(Expr e1 | + fc.getASuccessor+() = e1 and + ( + e1.(VariableAccess).getTarget() = + fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() or + e1.(VariableAccess).getTarget() = fc.getArgument(i).(VariableAccess).getTarget() + ) + ) + ) + ) and + // After the call, filled arguments are not evaluated. + not exists(Expr e0, int i | + i in [n .. fc.getNumberOfArguments() - 1] and + fc.getASuccessor+() = e0 and + e0.getEnclosingElement() instanceof ComparisonOperation and + ( + e0.(VariableAccess).getTarget() = fc.getArgument(i).(VariableAccess).getTarget() or + e0.(VariableAccess).getTarget() = + fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() + ) + ) +select fc, "Unchecked return value for call to '" + fc.getTarget().getName() + "'." From 0c8a07218c9c201e376f72e0547399773604fd97 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Fri, 25 Feb 2022 11:16:05 +0300 Subject: [PATCH 02/21] Add files via upload --- .../ImproperCheckReturnValueScanf.expected | 2 + .../tests/ImproperCheckReturnValueScanf.qlref | 1 + .../CWE/CWE-754/semmle/tests/test.cpp | 53 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.qlref create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected new file mode 100644 index 000000000000..7ba0580ca901 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected @@ -0,0 +1,2 @@ +| test.cpp:23:3:23:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:41:3:41:7 | call to scanf | Unchecked return value for call to 'scanf'. | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.qlref new file mode 100644 index 000000000000..f0cb9dd57c1e --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp new file mode 100644 index 000000000000..4389cb506a2e --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -0,0 +1,53 @@ +int scanf(const char *format, ...); +int globalVal; +int functionWork1() { + int i; + if (scanf("%i", i) == 1) // GOOD + return i; + else + return -1; +} + +int functionWork1_() { + int i; + int r; + r = scanf("%i", i); + if (r == 1) // GOOD + return i; + else + return -1; +} + +int functionWork1b() { + int i; + scanf("%i", i); // BAD + return i; +} + +int functionWork2() { + int i = 0; + scanf("%i", i); // GOOD:the error can be determined by examining the initial value. + return i; +} + +int functionWork2_() { + int i; + i = 0; + scanf("%i", i); // GOOD:the error can be determined by examining the initial value. + return i; +} +int functionWork2b() { + int i; + scanf("%i", i); // BAD + globalVal = i; + return 0; +} + +void functionRunner() { + functionWork1(); + functionWork1_(); + functionWork1b(); + functionWork2(); + functionWork2_(); + functionWork2b(); +} From d772ea0efe81f9f4917f84d6f95b7eed40cc222b Mon Sep 17 00:00:00 2001 From: ihsinme Date: Tue, 1 Mar 2022 10:49:36 +0300 Subject: [PATCH 03/21] Apply suggestions from code review Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com> --- .../CWE/CWE-754/ImproperCheckReturnValueScanf.cpp | 4 ++-- .../CWE/CWE-754/ImproperCheckReturnValueScanf.ql | 12 ++++-------- .../Security/CWE/CWE-754/semmle/tests/test.cpp | 12 ++++++------ 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.cpp b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.cpp index 432f144b4bb2..4928db37a178 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.cpp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.cpp @@ -1,10 +1,10 @@ ... - r = scanf("%i", i); + r = scanf("%i", &i); if (r == 1) // GOOD return i; else return -1; ... - scanf("%i", i); // BAD + scanf("%i", &i); // BAD return i; ... diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql index 4dc141be2474..67eebb62bb9e 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql @@ -1,5 +1,5 @@ /** - * @name Improper check return value scanf. + * @name Improper check return value scanf * @description Using a function call without the ability to evaluate the correctness of the work can lead to unexpected results. * @kind problem * @id cpp/improper-check-return-value-scanf @@ -15,20 +15,16 @@ import cpp import semmle.code.cpp.commons.Exclusions import semmle.code.cpp.valuenumbering.GlobalValueNumbering -/** Returns the starting position of the argument being filled. */ +/** Returns the position of the first argument being filled. */ int posArgumentInFunctionCall(FunctionCall fc) { ( ( - fc.getTarget().hasGlobalOrStdName("scanf") or - fc.getTarget().hasGlobalOrStdName("scanf_s") + fc.getTarget().hasGlobalOrStdName(["scanf", "scanf_s"]) ) and result = 1 or ( - fc.getTarget().hasGlobalOrStdName("fscanf") or - fc.getTarget().hasGlobalOrStdName("sscanf") or - fc.getTarget().hasGlobalOrStdName("fscanf_s") or - fc.getTarget().hasGlobalOrStdName("sscanf_s") + fc.getTarget().hasGlobalOrStdName(["fscanf", "sscanf", "fscanf_s", "sscanf_s"]) ) and result = 2 ) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp index 4389cb506a2e..588100e5b786 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -2,7 +2,7 @@ int scanf(const char *format, ...); int globalVal; int functionWork1() { int i; - if (scanf("%i", i) == 1) // GOOD + if (scanf("%i", &i) == 1) // GOOD return i; else return -1; @@ -11,7 +11,7 @@ int functionWork1() { int functionWork1_() { int i; int r; - r = scanf("%i", i); + r = scanf("%i", &i); if (r == 1) // GOOD return i; else @@ -20,25 +20,25 @@ int functionWork1_() { int functionWork1b() { int i; - scanf("%i", i); // BAD + scanf("%i", &i); // BAD return i; } int functionWork2() { int i = 0; - scanf("%i", i); // GOOD:the error can be determined by examining the initial value. + scanf("%i", &i); // GOOD:the error can be determined by examining the initial value. return i; } int functionWork2_() { int i; i = 0; - scanf("%i", i); // GOOD:the error can be determined by examining the initial value. + scanf("%i", &i); // GOOD:the error can be determined by examining the initial value. return i; } int functionWork2b() { int i; - scanf("%i", i); // BAD + scanf("%i", &i); // BAD globalVal = i; return 0; } From bfec3c5e6ebd99db051205d8c83c0371c50447a1 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Tue, 1 Mar 2022 16:35:31 +0300 Subject: [PATCH 04/21] Update ImproperCheckReturnValueScanf.expected --- .../semmle/tests/ImproperCheckReturnValueScanf.expected | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected index 7ba0580ca901..abea6ce76399 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected @@ -1,2 +1,7 @@ -| test.cpp:23:3:23:7 | call to scanf | Unchecked return value for call to 'scanf'. | -| test.cpp:41:3:41:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:43:3:43:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:44:3:44:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:45:3:45:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:78:3:78:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:79:3:79:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:80:3:80:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:88:3:88:7 | call to scanf | Unchecked return value for call to 'scanf'. | From e9fefab9b150bc33bff313b91be50211ba02d90d Mon Sep 17 00:00:00 2001 From: ihsinme Date: Tue, 1 Mar 2022 16:36:24 +0300 Subject: [PATCH 05/21] Update test.cpp --- .../CWE/CWE-754/semmle/tests/test.cpp | 58 +++++++++++++++++-- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp index 588100e5b786..e3a464ed6f5e 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -1,45 +1,92 @@ int scanf(const char *format, ...); int globalVal; +char * globalVala; +int * globalValp; +char globalVala2; int functionWork1() { int i; - if (scanf("%i", &i) == 1) // GOOD - return i; - else + char a[10]; + int b; + int *p = &b; + if (scanf("%i", &i) != 1) // GOOD return -1; + if (scanf("%s", a) != 1) // GOOD + return -1; + if (scanf("%i", p) != 1) // GOOD + return -1; + return i; } int functionWork1_() { int i; + char a[10]; + int b; + int *p = &b; int r; r = scanf("%i", &i); + if (r != 1) // GOOD + return -1; + r = scanf("%s", a); if (r == 1) // GOOD - return i; - else return -1; + r = scanf("%i", p); + if (r != 1) // GOOD + return -1; + return i; } int functionWork1b() { int i; + char a[10]; + int b; + int *p = &b; scanf("%i", &i); // BAD + scanf("%s", a); // BAD + scanf("%i", p); // BAD return i; } int functionWork2() { int i = 0; + char a[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int b = 1; + int *p = &b; scanf("%i", &i); // GOOD:the error can be determined by examining the initial value. + scanf("%s", a); // GOOD:the error can be determined by examining the initial value. + scanf("%i", p); // GOOD:the error can be determined by examining the initial value. return i; } int functionWork2_() { int i; i = 0; + char a[10]; + a[0] = 0; + int b; + b=1; + int *p = &b; scanf("%i", &i); // GOOD:the error can be determined by examining the initial value. + scanf("%s", a); // GOOD:the error can be determined by examining the initial value. + scanf("%i", p); // GOOD:the error can be determined by examining the initial value. return i; } int functionWork2b() { int i; + char a[10]; + int b; + int *p = &b; scanf("%i", &i); // BAD + scanf("%s", a); // BAD + scanf("%i", p); // BAD globalVal = i; + globalVala = a; + globalValp = p; + return 0; +} +int functionWork2b_() { + char a[10]; + scanf("%s", a); // BAD + globalVala2 = a[0]; return 0; } @@ -50,4 +97,5 @@ void functionRunner() { functionWork2(); functionWork2_(); functionWork2b(); + functionWork2b_(); } From a6654fce4acc64503f993046abfca5c4c44ece39 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Tue, 1 Mar 2022 16:37:29 +0300 Subject: [PATCH 06/21] Update ImproperCheckReturnValueScanf.ql --- .../CWE-754/ImproperCheckReturnValueScanf.ql | 105 +++++++++--------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql index 67eebb62bb9e..1716632cab89 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql @@ -13,92 +13,91 @@ import cpp import semmle.code.cpp.commons.Exclusions -import semmle.code.cpp.valuenumbering.GlobalValueNumbering /** Returns the position of the first argument being filled. */ int posArgumentInFunctionCall(FunctionCall fc) { ( - ( - fc.getTarget().hasGlobalOrStdName(["scanf", "scanf_s"]) - ) and + fc.getTarget().hasGlobalOrStdName(["scanf", "scanf_s"]) and result = 1 or - ( - fc.getTarget().hasGlobalOrStdName(["fscanf", "sscanf", "fscanf_s", "sscanf_s"]) - ) and + fc.getTarget().hasGlobalOrStdName(["fscanf", "sscanf", "fscanf_s", "sscanf_s"]) and result = 2 ) } -from FunctionCall fc, int n -where - n = posArgumentInFunctionCall(fc) and - // Function return value is not evaluated. - fc instanceof ExprInVoidContext and - not isFromMacroDefinition(fc) and - exists(Expr e0, int i | - i in [n .. fc.getNumberOfArguments() - 1] and +/** Holds if a function argument was not initialized but used after the call. */ +predicate argumentIsNotInitializedAndIsUsed(Variable vt, FunctionCall fc) { + exists(Expr e0 | // Fillable argument was not initialized. + vt instanceof LocalScopeVariable and + not vt.getAnAssignment().getASuccessor+() = fc and ( - fc.getArgument(i).(VariableAccess).getTarget() instanceof LocalScopeVariable or - fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() instanceof - LocalScopeVariable + not vt.hasInitializer() + or + exists(Expr e1, Variable v1 | + e1 = vt.getInitializer().getExpr() and + v1 = e1.(AddressOfExpr).getOperand().(VariableAccess).getTarget() and + ( + not v1.hasInitializer() and + not v1.getAnAssignment().getASuccessor+() = fc + ) + ) ) and - ( - not fc.getArgument(i).(VariableAccess).getTarget().hasInitializer() and - not fc.getArgument(i) - .(AddressOfExpr) - .getOperand() - .(VariableAccess) - .getTarget() - .hasInitializer() + not exists(AssignExpr ae | + ae.getLValue() = vt.getAnAccess().getParent() and + ae.getASuccessor+() = fc ) and - ( - not fc.getArgument(i).(VariableAccess).getTarget().getAnAssignment().getASuccessor+() = fc and - not fc.getArgument(i) - .(AddressOfExpr) - .getOperand() - .(VariableAccess) - .getTarget() - .getAnAssignment() - .getASuccessor+() = fc + not exists(FunctionCall f0 | + f0.getAnArgument().getAChild() = vt.getAnAccess() and + f0.getASuccessor+() = fc ) and // After the call, the completed arguments are assigned or returned as the result of the operation of the upper function. fc.getASuccessor+() = e0 and ( ( - e0.(Assignment).getRValue().(VariableAccess).getTarget() = - fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() or - e0.(Assignment).getRValue().(VariableAccess).getTarget() = - fc.getArgument(i).(VariableAccess).getTarget() + e0.(Assignment).getRValue().(VariableAccess).getTarget() = vt or + e0.(Assignment).getRValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() = vt ) or e0.getEnclosingStmt() instanceof ReturnStmt and - ( - e0.(VariableAccess).getTarget() = - fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() or - e0.(VariableAccess).getTarget() = fc.getArgument(i).(VariableAccess).getTarget() - ) + e0.(VariableAccess).getTarget() = vt or not exists(Expr e1 | fc.getASuccessor+() = e1 and - ( - e1.(VariableAccess).getTarget() = - fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() or - e1.(VariableAccess).getTarget() = fc.getArgument(i).(VariableAccess).getTarget() - ) + e1.(VariableAccess).getTarget() = vt ) ) + ) +} + +from FunctionCall fc, int i +where + // Function return value is not evaluated. + fc instanceof ExprInVoidContext and + not isFromMacroDefinition(fc) and + i in [posArgumentInFunctionCall(fc) .. fc.getNumberOfArguments() - 1] and + ( + argumentIsNotInitializedAndIsUsed(fc.getArgument(i).(VariableAccess).getTarget(), fc) or + argumentIsNotInitializedAndIsUsed(fc.getArgument(i) + .(AddressOfExpr) + .getOperand() + .(VariableAccess) + .getTarget(), fc) or + argumentIsNotInitializedAndIsUsed(fc.getArgument(i) + .(ArrayExpr) + .getArrayBase() + .(VariableAccess) + .getTarget(), fc) ) and // After the call, filled arguments are not evaluated. - not exists(Expr e0, int i | - i in [n .. fc.getNumberOfArguments() - 1] and + not exists(Expr e0, int i1 | + i1 in [posArgumentInFunctionCall(fc) .. fc.getNumberOfArguments() - 1] and fc.getASuccessor+() = e0 and e0.getEnclosingElement() instanceof ComparisonOperation and ( - e0.(VariableAccess).getTarget() = fc.getArgument(i).(VariableAccess).getTarget() or + e0.(VariableAccess).getTarget() = fc.getArgument(i1).(VariableAccess).getTarget() or e0.(VariableAccess).getTarget() = - fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() + fc.getArgument(i1).(AddressOfExpr).getOperand().(VariableAccess).getTarget() ) ) select fc, "Unchecked return value for call to '" + fc.getTarget().getName() + "'." From 1a30b8d467b105dffab76ba9e19a0f1461e1d892 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 3 Mar 2022 10:14:22 +0300 Subject: [PATCH 07/21] Apply suggestions from code review Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com> --- .../query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp index e3a464ed6f5e..9b4d78e9f25e 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -48,7 +48,7 @@ int functionWork1b() { int functionWork2() { int i = 0; - char a[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + char a[10] = ""; int b = 1; int *p = &b; scanf("%i", &i); // GOOD:the error can be determined by examining the initial value. @@ -61,7 +61,7 @@ int functionWork2_() { int i; i = 0; char a[10]; - a[0] = 0; + a[0] = '\0'; int b; b=1; int *p = &b; From 547342cd61a336d911075f7cd0847b81b2296334 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 3 Mar 2022 10:16:00 +0300 Subject: [PATCH 08/21] Update test.cpp --- .../Security/CWE/CWE-754/semmle/tests/test.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp index 9b4d78e9f25e..0181915b4e0f 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -51,9 +51,9 @@ int functionWork2() { char a[10] = ""; int b = 1; int *p = &b; - scanf("%i", &i); // GOOD:the error can be determined by examining the initial value. - scanf("%s", a); // GOOD:the error can be determined by examining the initial value. - scanf("%i", p); // GOOD:the error can be determined by examining the initial value. + scanf("%i", &i); // GOOD:Argument initialized even when scanf fails. + scanf("%s", a); // GOOD:Argument initialized even when scanf fails. + scanf("%i", p); // GOOD:Argument initialized even when scanf fails. return i; } @@ -65,9 +65,9 @@ int functionWork2_() { int b; b=1; int *p = &b; - scanf("%i", &i); // GOOD:the error can be determined by examining the initial value. - scanf("%s", a); // GOOD:the error can be determined by examining the initial value. - scanf("%i", p); // GOOD:the error can be determined by examining the initial value. + scanf("%i", &i); // GOOD:Argument initialized even when scanf fails. + scanf("%s", a); // GOOD:Argument initialized even when scanf fails. + scanf("%i", p); // GOOD:Argument initialized even when scanf fails. return i; } int functionWork2b() { From 2dc85e183c56cf381c3f1bc03b589c4ea04bd3f0 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 3 Mar 2022 10:20:41 +0300 Subject: [PATCH 09/21] Update test.cpp --- .../query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp index 0181915b4e0f..e9f05e4cd965 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -35,7 +35,7 @@ int functionWork1_() { return i; } -int functionWork1b() { +int functionWork1b(int retIndex) { int i; char a[10]; int b; @@ -43,6 +43,10 @@ int functionWork1b() { scanf("%i", &i); // BAD scanf("%s", a); // BAD scanf("%i", p); // BAD + if(retIndex == 0) + return (int)a; + if(retIndex == 1) + return *p; return i; } From 25b3aba8236a67535044b72f47e8215347b44372 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 3 Mar 2022 10:21:38 +0300 Subject: [PATCH 10/21] Update test.cpp --- .../Security/CWE/CWE-754/semmle/tests/test.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp index e9f05e4cd965..227df8fe731d 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -93,13 +93,3 @@ int functionWork2b_() { globalVala2 = a[0]; return 0; } - -void functionRunner() { - functionWork1(); - functionWork1_(); - functionWork1b(); - functionWork2(); - functionWork2_(); - functionWork2b(); - functionWork2b_(); -} From 8e0c0ad200fa30a51dd4a3aee0b0410d23842cb0 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 3 Mar 2022 10:37:31 +0300 Subject: [PATCH 11/21] Update test.cpp --- .../CWE/CWE-754/semmle/tests/test.cpp | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp index 227df8fe731d..14c0328050bb 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -3,7 +3,7 @@ int globalVal; char * globalVala; int * globalValp; char globalVala2; -int functionWork1() { +int functionWork1(int retIndex) { int i; char a[10]; int b; @@ -14,10 +14,14 @@ int functionWork1() { return -1; if (scanf("%i", p) != 1) // GOOD return -1; + if(retIndex == 0) + return (int)a; + if(retIndex == 1) + return *p; return i; } -int functionWork1_() { +int functionWork1_(int retIndex) { int i; char a[10]; int b; @@ -32,6 +36,10 @@ int functionWork1_() { r = scanf("%i", p); if (r != 1) // GOOD return -1; + if(retIndex == 0) + return (int)a; + if(retIndex == 1) + return *p; return i; } @@ -49,8 +57,14 @@ int functionWork1b(int retIndex) { return *p; return i; } - -int functionWork2() { +int functionWork1_() { + int i; + scanf("%i",&i); + if(i<10) + return -1; + return i; +} +int functionWork2(int retIndex) { int i = 0; char a[10] = ""; int b = 1; @@ -58,10 +72,14 @@ int functionWork2() { scanf("%i", &i); // GOOD:Argument initialized even when scanf fails. scanf("%s", a); // GOOD:Argument initialized even when scanf fails. scanf("%i", p); // GOOD:Argument initialized even when scanf fails. + if(retIndex == 0) + return (int)a; + if(retIndex == 1) + return *p; return i; } -int functionWork2_() { +int functionWork2_(int retIndex) { int i; i = 0; char a[10]; @@ -72,6 +90,10 @@ int functionWork2_() { scanf("%i", &i); // GOOD:Argument initialized even when scanf fails. scanf("%s", a); // GOOD:Argument initialized even when scanf fails. scanf("%i", p); // GOOD:Argument initialized even when scanf fails. + if(retIndex == 0) + return (int)a; + if(retIndex == 1) + return *p; return i; } int functionWork2b() { From bec4170bdfa1fba2037c8e6d125d6a83d64aa912 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 3 Mar 2022 10:39:19 +0300 Subject: [PATCH 12/21] Update ImproperCheckReturnValueScanf.expected --- .../tests/ImproperCheckReturnValueScanf.expected | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected index abea6ce76399..1a5d816f3f18 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected @@ -1,7 +1,7 @@ -| test.cpp:43:3:43:7 | call to scanf | Unchecked return value for call to 'scanf'. | -| test.cpp:44:3:44:7 | call to scanf | Unchecked return value for call to 'scanf'. | -| test.cpp:45:3:45:7 | call to scanf | Unchecked return value for call to 'scanf'. | -| test.cpp:78:3:78:7 | call to scanf | Unchecked return value for call to 'scanf'. | -| test.cpp:79:3:79:7 | call to scanf | Unchecked return value for call to 'scanf'. | -| test.cpp:80:3:80:7 | call to scanf | Unchecked return value for call to 'scanf'. | -| test.cpp:88:3:88:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:51:3:51:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:52:3:52:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:53:3:53:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:104:3:104:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:105:3:105:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:106:3:106:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:114:3:114:7 | call to scanf | Unchecked return value for call to 'scanf'. | From 01f9114a80ab767d3f618dab03ef5df30d318870 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 3 Mar 2022 10:57:11 +0300 Subject: [PATCH 13/21] Update test.cpp --- .../Security/CWE/CWE-754/semmle/tests/test.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp index 14c0328050bb..051d2e00ddc7 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -15,7 +15,7 @@ int functionWork1(int retIndex) { if (scanf("%i", p) != 1) // GOOD return -1; if(retIndex == 0) - return (int)a; + return (int)*a; if(retIndex == 1) return *p; return i; @@ -37,7 +37,7 @@ int functionWork1_(int retIndex) { if (r != 1) // GOOD return -1; if(retIndex == 0) - return (int)a; + return (int)*a; if(retIndex == 1) return *p; return i; @@ -52,14 +52,14 @@ int functionWork1b(int retIndex) { scanf("%s", a); // BAD scanf("%i", p); // BAD if(retIndex == 0) - return (int)a; + return (int)*a; if(retIndex == 1) return *p; return i; } int functionWork1_() { int i; - scanf("%i",&i); + scanf("%i",&i); // GOOD if(i<10) return -1; return i; @@ -73,7 +73,7 @@ int functionWork2(int retIndex) { scanf("%s", a); // GOOD:Argument initialized even when scanf fails. scanf("%i", p); // GOOD:Argument initialized even when scanf fails. if(retIndex == 0) - return (int)a; + return (int)*a; if(retIndex == 1) return *p; return i; @@ -91,7 +91,7 @@ int functionWork2_(int retIndex) { scanf("%s", a); // GOOD:Argument initialized even when scanf fails. scanf("%i", p); // GOOD:Argument initialized even when scanf fails. if(retIndex == 0) - return (int)a; + return (int)*a; if(retIndex == 1) return *p; return i; From c0c7748c5ed8e1bf12f99574410ed03042a0b9c8 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Tue, 8 Mar 2022 07:42:35 +0300 Subject: [PATCH 14/21] Apply suggestions from code review Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com> --- .../ImproperCheckReturnValueScanf.qhelp | 5 ++ .../CWE-754/ImproperCheckReturnValueScanf.ql | 50 +++++++++---------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp index 2e60d33f89ab..b4571cce6bdb 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp @@ -4,7 +4,12 @@

    Working with reading data without validation procedures and with uninitialized arguments can lead to unpredictable consequences.

    +
    + +

    +The user should check the return value of `scanf` and related functions and check that any additional argument was assigned a value before reading the additional argument. +

    The following example demonstrates erroneous and corrected work with a function call.

    diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql index 1716632cab89..5f296752c1c4 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql @@ -1,6 +1,6 @@ /** - * @name Improper check return value scanf - * @description Using a function call without the ability to evaluate the correctness of the work can lead to unexpected results. + * @name Improper check of return value of scanf + * @description Not checking the return value of scanf and related functions may lead to undefined behavior. * @kind problem * @id cpp/improper-check-return-value-scanf * @problem.severity warning @@ -27,30 +27,30 @@ int posArgumentInFunctionCall(FunctionCall fc) { /** Holds if a function argument was not initialized but used after the call. */ predicate argumentIsNotInitializedAndIsUsed(Variable vt, FunctionCall fc) { - exists(Expr e0 | - // Fillable argument was not initialized. - vt instanceof LocalScopeVariable and - not vt.getAnAssignment().getASuccessor+() = fc and - ( - not vt.hasInitializer() - or - exists(Expr e1, Variable v1 | - e1 = vt.getInitializer().getExpr() and - v1 = e1.(AddressOfExpr).getOperand().(VariableAccess).getTarget() and - ( - not v1.hasInitializer() and - not v1.getAnAssignment().getASuccessor+() = fc - ) + // Fillable argument was not initialized. + vt instanceof LocalScopeVariable and + not vt.getAnAssignment().getASuccessor+() = fc and + ( + not vt.hasInitializer() + or + exists(Expr e, Variable v | + e = vt.getInitializer().getExpr() and + v = e.(AddressOfExpr).getOperand().(VariableAccess).getTarget() and + ( + not v.hasInitializer() and + not v.getAnAssignment().getASuccessor+() = fc ) - ) and - not exists(AssignExpr ae | - ae.getLValue() = vt.getAnAccess().getParent() and - ae.getASuccessor+() = fc - ) and - not exists(FunctionCall f0 | - f0.getAnArgument().getAChild() = vt.getAnAccess() and - f0.getASuccessor+() = fc - ) and + ) + ) and + not exists(AssignExpr ae | + ae.getLValue() = vt.getAnAccess().getParent() and + ae.getASuccessor+() = fc + ) and + not exists(FunctionCall f0 | + f0.getAnArgument().getAChild() = vt.getAnAccess() and + f0.getASuccessor+() = fc + ) and + exists(Expr e0 | // After the call, the completed arguments are assigned or returned as the result of the operation of the upper function. fc.getASuccessor+() = e0 and ( From 8335778e20f4bf074000491626f2b79b63b35dc3 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Tue, 8 Mar 2022 07:45:07 +0300 Subject: [PATCH 15/21] Update ImproperCheckReturnValueScanf.qhelp --- .../Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp index b4571cce6bdb..ab40910f5d3f 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp @@ -3,7 +3,7 @@ "qhelp.dtd"> -

    Working with reading data without validation procedures and with uninitialized arguments can lead to unpredictable consequences.

    +

    The `scanf` family functions does not require the memory pointed to by its additional pointer arguments to be initialized before calling. The user is required to check the return value of `scanf` and similar functions to establish how many of the additional arguments were assigned values. Not checking the return value and reading one of the arguments not assigned a value is undefined behavior and may have unexpected consequences.

    @@ -12,7 +12,7 @@ The user should check the return value of `scanf` and related functions and chec

    -

    The following example demonstrates erroneous and corrected work with a function call.

    +

    The first first example below is correct, as value of `i` is only read once it is checked that `scanf` has read one item. The second example is incorrect, as the return value of `scanf` is not checked, and as `scanf` might have failed to read any item before returning.

    From 5e23615be7f4f9ddb1d427011379a28708bd0df4 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 10 Mar 2022 10:12:29 +0300 Subject: [PATCH 16/21] Update test.cpp --- .../query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp index 051d2e00ddc7..d548f8f15077 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -59,7 +59,7 @@ int functionWork1b(int retIndex) { } int functionWork1_() { int i; - scanf("%i",&i); // GOOD + scanf("%i",&i); // BAD [NOT DETECTED] if(i<10) return -1; return i; @@ -115,3 +115,7 @@ int functionWork2b_() { globalVala2 = a[0]; return 0; } +int functionWork3b(int i) { + scanf("%i", &i); // BAD + return 0; +} From 4b451cfee6b137e58bce0d9144e71e8da134c69a Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 10 Mar 2022 10:13:04 +0300 Subject: [PATCH 17/21] Update ImproperCheckReturnValueScanf.expected --- .../CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected index 1a5d816f3f18..845f20149a39 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected @@ -5,3 +5,4 @@ | test.cpp:105:3:105:7 | call to scanf | Unchecked return value for call to 'scanf'. | | test.cpp:106:3:106:7 | call to scanf | Unchecked return value for call to 'scanf'. | | test.cpp:114:3:114:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:119:3:119:7 | call to scanf | Unchecked return value for call to 'scanf'. | From fa3ce61369c3963b7b9fa6635d8e0819c15724ae Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 10 Mar 2022 17:54:03 +0300 Subject: [PATCH 18/21] Update test.cpp --- .../query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp index d548f8f15077..d7495392bba4 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -119,3 +119,10 @@ int functionWork3b(int i) { scanf("%i", &i); // BAD return 0; } +int functionWork3() { + char number[] = "42"; + int d; + sscanf(number, "%d", &d); // GOOD: sscanf always succeeds + if (d < 16) + return -1; +} From a094e6f63b969138d5bfee0600d623a45abac7f0 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 10 Mar 2022 17:56:34 +0300 Subject: [PATCH 19/21] Update test.cpp --- .../query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp index d7495392bba4..dd7858655528 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -115,8 +115,8 @@ int functionWork2b_() { globalVala2 = a[0]; return 0; } -int functionWork3b(int i) { - scanf("%i", &i); // BAD +int functionWork3b(int * i) { + scanf("%i", i); // BAD return 0; } int functionWork3() { From 623f3fbe21848d6e851b608b388af8b9e8e256ab Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 10 Mar 2022 21:10:41 +0300 Subject: [PATCH 20/21] Update test.cpp --- .../query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp index dd7858655528..b9608b757b9c 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/test.cpp @@ -1,4 +1,5 @@ int scanf(const char *format, ...); +int sscanf(const char *str, const char *format, ...); int globalVal; char * globalVala; int * globalValp; From ac8adeabf57582b26be95a037836e294142e7d32 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Thu, 10 Mar 2022 21:12:23 +0300 Subject: [PATCH 21/21] Update ImproperCheckReturnValueScanf.expected --- .../semmle/tests/ImproperCheckReturnValueScanf.expected | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected index 845f20149a39..85a929ed39c9 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-754/semmle/tests/ImproperCheckReturnValueScanf.expected @@ -1,8 +1,8 @@ -| test.cpp:51:3:51:7 | call to scanf | Unchecked return value for call to 'scanf'. | | test.cpp:52:3:52:7 | call to scanf | Unchecked return value for call to 'scanf'. | | test.cpp:53:3:53:7 | call to scanf | Unchecked return value for call to 'scanf'. | -| test.cpp:104:3:104:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:54:3:54:7 | call to scanf | Unchecked return value for call to 'scanf'. | | test.cpp:105:3:105:7 | call to scanf | Unchecked return value for call to 'scanf'. | | test.cpp:106:3:106:7 | call to scanf | Unchecked return value for call to 'scanf'. | -| test.cpp:114:3:114:7 | call to scanf | Unchecked return value for call to 'scanf'. | -| test.cpp:119:3:119:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:107:3:107:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:115:3:115:7 | call to scanf | Unchecked return value for call to 'scanf'. | +| test.cpp:120:3:120:7 | call to scanf | Unchecked return value for call to 'scanf'. |