@@ -82,7 +82,7 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
8282 Finder->addMatcher (
8383 cxxConstructExpr (
8484 hasDeclaration (cxxMethodDecl (hasName (" basic_string" ))),
85- hasArgument (0 , hasType (qualType (isInteger ()))),
85+ argumentCountIs ( 2 ), hasArgument (0 , hasType (qualType (isInteger ()))),
8686 hasArgument (1 , hasType (qualType (isInteger ()))),
8787 anyOf (
8888 // Detect the expression: string('x', 40);
@@ -102,7 +102,7 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
102102 cxxConstructExpr (
103103 hasDeclaration (cxxConstructorDecl (ofClass (
104104 cxxRecordDecl (hasAnyName (removeNamespaces (StringNames)))))),
105- hasArgument (0 , hasType (CharPtrType)),
105+ argumentCountIs ( 2 ), hasArgument (0 , hasType (CharPtrType)),
106106 hasArgument (1 , hasType (isInteger ())),
107107 anyOf (
108108 // Detect the expression: string("...", 0);
@@ -114,7 +114,34 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
114114 // Detect the expression: string("lit", 5)
115115 allOf (hasArgument (0 , ConstStrLiteral.bind (" literal-with-length" )),
116116 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" ))))))
118145 .bind (" constructor" ),
119146 this );
120147
@@ -155,14 +182,27 @@ void StringConstructorCheck::check(const MatchFinder::MatchResult &Result) {
155182 diag (Loc, " constructor creating an empty string" );
156183 } else if (Result.Nodes .getNodeAs <Expr>(" negative-length" )) {
157184 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" );
158188 } else if (Result.Nodes .getNodeAs <Expr>(" large-length" )) {
159189 if (WarnOnLargeLength)
160190 diag (Loc, " suspicious large length parameter" );
161191 } else if (Result.Nodes .getNodeAs <Expr>(" literal-with-length" )) {
162192 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 ())) {
165195 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+ }
166206 }
167207 } else if (const auto *Ptr = Result.Nodes .getNodeAs <Expr>(" from-ptr" )) {
168208 Expr::EvalResult ConstPtr;
0 commit comments