Skip to content

Commit 7f766cb

Browse files
author
Nikita Kraiouchkine
committed
Fix strncat/wcscat param definition and add rules
1 parent 2696ef9 commit 7f766cb

10 files changed

+77
-9
lines changed

c/cert/src/rules/ARR38-C/LibraryFunctionArgumentOutOfBounds.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/**
22
* @id c/cert/library-function-argument-out-of-bounds
33
* @name ARR38-C: Guarantee that library functions do not form invalid pointers
4-
* @description
4+
* @description Passing out-of-bounds pointers or erroneous size arguments to standard library
5+
* functions can result in out-of-bounds accesses and other undefined behavior.
56
* @kind problem
67
* @precision high
78
* @problem.severity error

c/cert/test/rules/ARR38-C/LibraryFunctionArgumentOutOfBounds.expected

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,9 @@
1515
| test.c:153:5:153:10 | call to strcat | The $@ passed to strcat might not be null-terminated. | test.c:153:12:153:15 | buf1 | argument | test.c:153:12:153:15 | buf1 | |
1616
| test.c:158:5:158:10 | call to strcat | The size of the $@ passed to strcat is 6 bytes, but the size of the $@ is only 5 bytes. | test.c:158:24:158:30 | 12345 | read buffer | test.c:158:12:158:19 | call to get_ca_5 | write buffer |
1717
| test.c:160:5:160:10 | call to strcat | The size of the $@ passed to strcat is 5 bytes, but the size of the $@ is only 4 bytes. | test.c:160:28:160:33 | 1234 | read buffer | test.c:160:12:160:25 | ... + ... | write buffer |
18-
| test.c:183:5:183:11 | call to wcsncat | The size of the $@ passed to wcsncat is 5 bytes, but the $@ is 20 bytes. | test.c:183:13:183:20 | call to get_ca_5 | write buffer | test.c:183:35:183:35 | 5 | size argument |
1918
| test.c:183:5:183:11 | call to wcsncat | The size of the $@ passed to wcsncat is 24 bytes, but the size of the $@ is only 5 bytes. | test.c:183:25:183:32 | 12345 | read buffer | test.c:183:13:183:20 | call to get_ca_5 | write buffer |
20-
| test.c:184:5:184:11 | call to wcsncat | The size of the $@ passed to wcsncat is 5 bytes, but the $@ is 16 bytes. | test.c:184:13:184:20 | call to get_ca_5 | write buffer | test.c:184:34:184:34 | 4 | size argument |
2119
| test.c:184:5:184:11 | call to wcsncat | The size of the $@ passed to wcsncat is 20 bytes, but the size of the $@ is only 5 bytes. | test.c:184:25:184:31 | 1234 | read buffer | test.c:184:13:184:20 | call to get_ca_5 | write buffer |
22-
| test.c:185:5:185:11 | call to wcsncat | The size of the $@ passed to wcsncat is 1 bytes, but the $@ is 16 bytes. | test.c:185:13:185:26 | ... + ... | write buffer | test.c:185:38:185:38 | 4 | size argument |
2320
| test.c:185:5:185:11 | call to wcsncat | The size of the $@ passed to wcsncat is 20 bytes, but the size of the $@ is only 1 bytes. | test.c:185:29:185:35 | 1234 | read buffer | test.c:185:13:185:26 | ... + ... | write buffer |
24-
| test.c:186:5:186:11 | call to wcsncat | The size of the $@ passed to wcsncat is 5 bytes, but the $@ is 8 bytes. | test.c:186:13:186:20 | call to get_ca_5 | write buffer | test.c:186:32:186:32 | 2 | size argument |
2521
| test.c:186:5:186:11 | call to wcsncat | The size of the $@ passed to wcsncat is 12 bytes, but the size of the $@ is only 5 bytes. | test.c:186:25:186:29 | 12 | read buffer | test.c:186:13:186:20 | call to get_ca_5 | write buffer |
2622
| test.c:191:5:191:10 | call to strcmp | The $@ passed to strcmp might not be null-terminated. | test.c:191:22:191:28 | ca5_bad | argument | test.c:191:22:191:28 | ca5_bad | |
2723
| test.c:193:5:193:10 | call to strcmp | The $@ passed to strcmp might not be null-terminated. | test.c:193:12:193:18 | ca5_bad | argument | test.c:193:12:193:18 | ca5_bad | |

c/common/src/codingstandards/c/OutOfBounds.qll

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import semmle.code.cpp.security.BufferWrite
1818

1919
module OOB {
2020
bindingset[name, result]
21-
private string getNameOrInternalName(string name) {
21+
string getNameOrInternalName(string name) {
2222
result = name or
2323
result.regexpMatch("__.*_+" + name + "_.*")
2424
}
@@ -162,8 +162,8 @@ module OOB {
162162
name = ["strncat", "wcsncat"] and
163163
dst = 0 and
164164
src = 1 and
165-
src_sz = -1 and
166-
dst_sz = 2
165+
src_sz = 2 and
166+
dst_sz = -1
167167
or
168168
name = ["snprintf", "vsnprintf", "swprintf", "vswprintf"] and
169169
dst = 0 and
@@ -362,6 +362,11 @@ module OOB {
362362
*/
363363
class StrncatLibraryFunction extends StringConcatenationFunctionLibraryFunction {
364364
StrncatLibraryFunction() { this.getName() = getNameOrInternalName(["strncat", "wcsncat"]) }
365+
366+
override predicate getALengthParameterIndex(int i) {
367+
// `strncat` and `wcsncat` exclude the size of a null terminator
368+
i = 2
369+
}
365370
}
366371

367372
/**
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* @id c/misra/string-function-pointer-argument-out-of-bounds
3+
* @name RULE-21-17: Use of the string handling functions from <string.h> shall not result in accesses beyond the bounds
4+
* @description Use of string manipulation functions from <string.h> with improper buffer sizes can
5+
* result in out-of-bounds buffer accesses.
6+
* @kind problem
7+
* @precision high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-21-17
10+
* correctness
11+
* security
12+
* external/misra/obligation/mandatory
13+
*/
14+
15+
import cpp
16+
import codingstandards.c.misra
17+
import codingstandards.c.OutOfBounds
18+
19+
class RULE_21_17_Subset_FC = OOB::SimpleStringLibraryFunctionCall;
20+
21+
from
22+
RULE_21_17_Subset_FC fc, string message, Expr bufferArg, string bufferArgStr,
23+
Expr sizeOrOtherBufferArg, string otherStr
24+
where
25+
not isExcluded(fc, OutOfBoundsPackage::stringFunctionPointerArgumentOutOfBoundsQuery()) and
26+
OOB::problems(fc, message, bufferArg, bufferArgStr, sizeOrOtherBufferArg, otherStr)
27+
select fc, message, bufferArg, bufferArgStr, sizeOrOtherBufferArg, otherStr
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* @id c/misra/string-library-size-argument-out-of-bounds
3+
* @name RULE-21-18: The size_t argument passed to any function in <string.h> shall have an appropriate value
4+
* @description Passing a size_t argument that is non-positive or greater than the size of the
5+
* smallest buffer argument to any function in <string.h> may result in out-of-bounds
6+
* buffer accesses.
7+
* @kind problem
8+
* @precision high
9+
* @problem.severity error
10+
* @tags external/misra/id/rule-21-18
11+
* correctness
12+
* security
13+
* external/misra/obligation/mandatory
14+
*/
15+
16+
import cpp
17+
import codingstandards.c.misra
18+
import codingstandards.c.OutOfBounds
19+
20+
class RULE_21_18_Subset_FC extends OOB::BufferAccessLibraryFunctionCall {
21+
RULE_21_18_Subset_FC() {
22+
this.getTarget().getName() =
23+
OOB::getNameOrInternalName([
24+
"mem" + ["chr", "cmp", "cpy", "move", "set"], "str" + ["ncat", "ncmp", "ncpy", "xfrm"]
25+
])
26+
}
27+
}
28+
29+
from
30+
RULE_21_18_Subset_FC fc, string message, Expr bufferArg, string bufferArgStr,
31+
Expr sizeOrOtherBufferArg, string otherStr
32+
where
33+
not isExcluded(fc, OutOfBoundsPackage::stringLibrarySizeArgumentOutOfBoundsQuery()) and
34+
OOB::problems(fc, message, bufferArg, bufferArgStr, sizeOrOtherBufferArg, otherStr)
35+
select fc, message, bufferArg, bufferArgStr, sizeOrOtherBufferArg, otherStr
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
No expected results have yet been specified
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-21-17/StringFunctionPointerArgumentOutOfBounds.ql
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
No expected results have yet been specified
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-21-18/StringLibrarySizeArgumentOutOfBounds.ql

rule_packages/c/OutOfBounds.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
},
2727
"queries": [
2828
{
29-
"description": "",
29+
"description": "Passing out-of-bounds pointers or erroneous size arguments to standard library functions can result in out-of-bounds accesses and other undefined behavior.",
3030
"kind": "problem",
3131
"name": "Guarantee that library functions do not form invalid pointers",
3232
"precision": "high",

0 commit comments

Comments
 (0)