@@ -10,6 +10,8 @@ import semmle.code.cpp.models.interfaces.SideEffect
1010
1111/**
1212 * The standard function `strcat` and its wide, sized, and Microsoft variants.
13+ *
14+ * Does not include `strlcat`, which is covered by `StrlcatFunction`
1315 */
1416class StrcatFunction extends TaintFunction , DataFlowFunction , ArrayFunction , SideEffectFunction {
1517 StrcatFunction ( ) {
@@ -25,8 +27,7 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid
2527 "_mbsncat" , // _mbsncat(dst, src, max_amount)
2628 "_mbsncat_l" , // _mbsncat_l(dst, src, max_amount, locale)
2729 "_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)
3031 ] )
3132 }
3233
@@ -52,7 +53,7 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid
5253
5354 override predicate hasTaintFlow ( FunctionInput input , FunctionOutput output ) {
5455 (
55- this .getName ( ) = [ "strncat" , "strlcat" , " wcsncat", "_mbsncat" , "_mbsncat_l" ] and
56+ this .getName ( ) = [ "strncat" , "wcsncat" , "_mbsncat" , "_mbsncat_l" ] and
5657 input .isParameter ( 2 )
5758 or
5859 this .getName ( ) = [ "_mbsncat_l" , "_mbsnbcat_l" ] and
@@ -91,3 +92,69 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid
9192 buffer = true
9293 }
9394}
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