@@ -82,7 +82,7 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
82
82
Finder->addMatcher (
83
83
cxxConstructExpr (
84
84
hasDeclaration (cxxMethodDecl (hasName (" basic_string" ))),
85
- hasArgument (0 , hasType (qualType (isInteger ()))),
85
+ argumentCountIs ( 2 ), hasArgument (0 , hasType (qualType (isInteger ()))),
86
86
hasArgument (1 , hasType (qualType (isInteger ()))),
87
87
anyOf (
88
88
// Detect the expression: string('x', 40);
@@ -102,7 +102,7 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
102
102
cxxConstructExpr (
103
103
hasDeclaration (cxxConstructorDecl (ofClass (
104
104
cxxRecordDecl (hasAnyName (removeNamespaces (StringNames)))))),
105
- hasArgument (0 , hasType (CharPtrType)),
105
+ argumentCountIs ( 2 ), hasArgument (0 , hasType (CharPtrType)),
106
106
hasArgument (1 , hasType (isInteger ())),
107
107
anyOf (
108
108
// Detect the expression: string("...", 0);
@@ -114,7 +114,34 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
114
114
// Detect the expression: string("lit", 5)
115
115
allOf (hasArgument (0 , ConstStrLiteral.bind (" literal-with-length" )),
116
116
hasArgument (1 , ignoringParenImpCasts (
117
- integerLiteral ().bind (" int" ))))))
117
+ integerLiteral ().bind (" length" ))))))
118
+ .bind (" constructor" ),
119
+ this );
120
+
121
+ // Check the literal string constructor with char pointer, start position and
122
+ // length parameters. [i.e. string (const char* s, size_t pos, size_t count);]
123
+ Finder->addMatcher (
124
+ cxxConstructExpr (
125
+ hasDeclaration (cxxConstructorDecl (ofClass (
126
+ cxxRecordDecl (hasAnyName (removeNamespaces (StringNames)))))),
127
+ argumentCountIs (3 ), hasArgument (0 , hasType (CharPtrType)),
128
+ hasArgument (1 , hasType (qualType (isInteger ()))),
129
+ hasArgument (2 , hasType (qualType (isInteger ()))),
130
+ anyOf (
131
+ // Detect the expression: string("...", 1, 0);
132
+ hasArgument (2 , ZeroExpr.bind (" empty-string" )),
133
+ // Detect the expression: string("...", -4, 1);
134
+ hasArgument (1 , NegativeExpr.bind (" negative-pos" )),
135
+ // Detect the expression: string("...", 0, -4);
136
+ hasArgument (2 , NegativeExpr.bind (" negative-length" )),
137
+ // Detect the expression: string("lit", 0, 0x1234567);
138
+ hasArgument (2 , LargeLengthExpr.bind (" large-length" )),
139
+ // Detect the expression: string("lit", 1, 5)
140
+ allOf (hasArgument (0 , ConstStrLiteral.bind (" literal-with-length" )),
141
+ hasArgument (
142
+ 1 , ignoringParenImpCasts (integerLiteral ().bind (" pos" ))),
143
+ hasArgument (2 , ignoringParenImpCasts (
144
+ integerLiteral ().bind (" length" ))))))
118
145
.bind (" constructor" ),
119
146
this );
120
147
@@ -155,14 +182,27 @@ void StringConstructorCheck::check(const MatchFinder::MatchResult &Result) {
155
182
diag (Loc, " constructor creating an empty string" );
156
183
} else if (Result.Nodes .getNodeAs <Expr>(" negative-length" )) {
157
184
diag (Loc, " negative value used as length parameter" );
185
+ } else if (Result.Nodes .getNodeAs <Expr>(" negative-pos" )) {
186
+ diag (Loc, " negative value used as position of the "
187
+ " first character parameter" );
158
188
} else if (Result.Nodes .getNodeAs <Expr>(" large-length" )) {
159
189
if (WarnOnLargeLength)
160
190
diag (Loc, " suspicious large length parameter" );
161
191
} else if (Result.Nodes .getNodeAs <Expr>(" literal-with-length" )) {
162
192
const auto *Str = Result.Nodes .getNodeAs <StringLiteral>(" str" );
163
- const auto *Lit = Result.Nodes .getNodeAs <IntegerLiteral>(" int " );
164
- if (Lit ->getValue ().ugt (Str->getLength ())) {
193
+ const auto *Length = Result.Nodes .getNodeAs <IntegerLiteral>(" length " );
194
+ if (Length ->getValue ().ugt (Str->getLength ())) {
165
195
diag (Loc, " length is bigger than string literal size" );
196
+ return ;
197
+ }
198
+ if (const auto *Pos = Result.Nodes .getNodeAs <IntegerLiteral>(" pos" )) {
199
+ if (Pos->getValue ().uge (Str->getLength ())) {
200
+ diag (Loc, " position of the first character parameter is bigger than "
201
+ " string literal character range" );
202
+ } else if (Length->getValue ().ugt (
203
+ (Str->getLength () - Pos->getValue ()).getZExtValue ())) {
204
+ diag (Loc, " length is bigger than remaining string literal size" );
205
+ }
166
206
}
167
207
} else if (const auto *Ptr = Result.Nodes .getNodeAs <Expr>(" from-ptr" )) {
168
208
Expr::EvalResult ConstPtr;
0 commit comments