@@ -10,6 +10,8 @@ import semmle.code.cpp.models.interfaces.SideEffect
10
10
11
11
/**
12
12
* The standard function `strcat` and its wide, sized, and Microsoft variants.
13
+ *
14
+ * Does not include `strlcat`, which is covered by `StrlcatFunction`
13
15
*/
14
16
class StrcatFunction extends TaintFunction , DataFlowFunction , ArrayFunction , SideEffectFunction {
15
17
StrcatFunction ( ) {
@@ -25,8 +27,7 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid
25
27
"_mbsncat" , // _mbsncat(dst, src, max_amount)
26
28
"_mbsncat_l" , // _mbsncat_l(dst, src, max_amount, locale)
27
29
"_mbsnbcat" , // _mbsnbcat(dest, src, count)
28
- "_mbsnbcat_l" , // _mbsnbcat_l(dest, src, count, locale)
29
- "strlcat" // strlcat(dst, src, dst_size)
30
+ "_mbsnbcat_l" // _mbsnbcat_l(dest, src, count, locale)
30
31
] )
31
32
}
32
33
@@ -52,7 +53,7 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid
52
53
53
54
override predicate hasTaintFlow ( FunctionInput input , FunctionOutput output ) {
54
55
(
55
- this .getName ( ) = [ "strncat" , "strlcat" , " wcsncat", "_mbsncat" , "_mbsncat_l" ] and
56
+ this .getName ( ) = [ "strncat" , "wcsncat" , "_mbsncat" , "_mbsncat_l" ] and
56
57
input .isParameter ( 2 )
57
58
or
58
59
this .getName ( ) = [ "_mbsncat_l" , "_mbsnbcat_l" ] and
@@ -91,3 +92,69 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid
91
92
buffer = true
92
93
}
93
94
}
95
+
96
+ /**
97
+ * The `strlcat` function.
98
+ */
99
+ class StrlcatFunction extends TaintFunction , DataFlowFunction , ArrayFunction , SideEffectFunction {
100
+ StrlcatFunction ( ) {
101
+ this .hasGlobalName ( "strlcat" ) // strlcat(dst, src, dst_size)
102
+ }
103
+
104
+ /**
105
+ * Gets the index of the parameter that is the size of the copy (in characters).
106
+ */
107
+ int getParamSize ( ) { exists ( this .getParameter ( 2 ) ) and result = 2 }
108
+
109
+ /**
110
+ * Gets the index of the parameter that is the source of the copy.
111
+ */
112
+ int getParamSrc ( ) { result = 1 }
113
+
114
+ /**
115
+ * Gets the index of the parameter that is the destination to be appended to.
116
+ */
117
+ int getParamDest ( ) { result = 0 }
118
+
119
+ override predicate hasDataFlow ( FunctionInput input , FunctionOutput output ) {
120
+ input .isParameter ( 0 ) and
121
+ output .isReturnValue ( )
122
+ }
123
+
124
+ override predicate hasTaintFlow ( FunctionInput input , FunctionOutput output ) {
125
+ (
126
+ input .isParameter ( 2 )
127
+ or
128
+ input .isParameterDeref ( 0 )
129
+ or
130
+ input .isParameterDeref ( 1 )
131
+ ) and
132
+ ( output .isParameterDeref ( 0 ) or output .isReturnValueDeref ( ) )
133
+ }
134
+
135
+ override predicate hasArrayInput ( int param ) {
136
+ param = 0 or
137
+ param = 1
138
+ }
139
+
140
+ override predicate hasArrayOutput ( int param ) { param = 0 }
141
+
142
+ override predicate hasArrayWithNullTerminator ( int param ) { param = 1 }
143
+
144
+ override predicate hasArrayWithUnknownSize ( int param ) { param = 0 }
145
+
146
+ override predicate hasOnlySpecificReadSideEffects ( ) { any ( ) }
147
+
148
+ override predicate hasOnlySpecificWriteSideEffects ( ) { any ( ) }
149
+
150
+ override predicate hasSpecificWriteSideEffect ( ParameterIndex i , boolean buffer , boolean mustWrite ) {
151
+ i = 0 and
152
+ buffer = true and
153
+ mustWrite = false
154
+ }
155
+
156
+ override predicate hasSpecificReadSideEffect ( ParameterIndex i , boolean buffer ) {
157
+ ( i = 0 or i = 1 ) and
158
+ buffer = true
159
+ }
160
+ }
0 commit comments