Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with cfqueryparam on more than a single line #621

Merged
merged 12 commits into from
Aug 10, 2024
82 changes: 70 additions & 12 deletions src/main/java/com/cflint/plugins/core/QueryParamChecker.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.StringReader;
import java.io.BufferedReader;

import com.cflint.BugList;
import com.cflint.CF;
Expand Down Expand Up @@ -36,18 +38,33 @@ public void element(final Element element, final Context context, final BugList
if (
element.getName().equalsIgnoreCase(CF.CFQUERY) && !CF.QUERY.equalsIgnoreCase(element.getAttributeValue(CF.DBTYPE))) {
String content = element.getContent().toString();
final String allowVariableExpression = context.getConfiguration().getParameter(this,"allowVariableExpression");
Pattern allowVariableExpressionPattern = null;
if ( !"".equals(allowVariableExpression) ) {
allowVariableExpressionPattern = Pattern.compile(allowVariableExpression,Pattern.DOTALL);
}
final String allowLineExpression = context.getConfiguration().getParameter(this,"allowLineExpression");
//Todo : cfparser/Jericho does not support parsing out the cfqueryparam very well.
// the following code will not work when there is a > sign in the expression
content = content.replaceAll("<[cC][fF][qQ][uU][eE][rR][yY][pP][aA][rR][aA][mM][^>]*>", "");
if (content.indexOf('#') >= 0) {
final List<Integer> ignoreLines = determineIgnoreLines(element);
final List<Integer> ignoreLines = determineIgnoreLines(content, context.startLine());
final Matcher matcher = Pattern.compile("#(?:##)?([^#]+)(?:##)?#($|[^#])",Pattern.DOTALL).matcher(content);
while (matcher.find()) {
if (matcher.groupCount() >= 1) {
int currentline = context.startLine() + countNewLinesUpTo(content, matcher.start());
String linecontent = content.split("\\R")[currentline-context.startLine()];
int currentOffset = element.getStartTag().getEnd() + 1 + matcher.start();
final String variableName = matcher.group(1);
if (!ignoreLines.contains(currentline)) {
String variableName = matcher.group(1);
Pattern allowLineExpressionPattern = null;
if ( !"".equals(allowLineExpression) ) {
//System.out.println(allowLineExpression.replaceAll("\\$\\{variable\\}","\\\\Q" + Matcher.quoteReplacement(variableName) + "\\\\E"));
allowLineExpressionPattern = Pattern.compile(allowLineExpression.replaceAll("\\$\\{variable\\}","\\\\Q" + Matcher.quoteReplacement(variableName) + "\\\\E"),Pattern.DOTALL);
}
if ( !ignoreLines.contains(currentline)
&& (allowVariableExpressionPattern == null || !allowVariableExpressionPattern.matcher(variableName).find())
&& (allowLineExpressionPattern == null || !allowLineExpressionPattern.matcher(linecontent).find())) {
//System.out.println("linecontent:" + linecontent);
context.addMessage("CFQUERYPARAM_REQ", variableName, currentline, currentOffset);
}
}
Expand All @@ -63,18 +80,59 @@ public void element(final Element element, final Context context, final BugList
* @param element the element object
* @return the line numbers of any @@CFLintIgnore annotations.
*/
private List<Integer> determineIgnoreLines(final Element element) {
private List<Integer> determineIgnoreLines(final String textContent, final int start ) {

final List<Integer> ignoreLines = new ArrayList<>();
for (Element comment : element.getChildElements()) {
if ("!---".equals(comment.getName()) && comment.toString().contains("@CFLintIgnore") && comment.toString().contains("CFQUERYPARAM_REQ")) {
int ignoreLine = comment.getSource().getRow(comment.getEnd());
ignoreLines.add(ignoreLine);
ignoreLines.add(ignoreLine + 1);
ignoreLines.add(comment.getSource().getRow(comment.getBegin()));
} else {
ignoreLines.addAll(determineIgnoreLines(comment));
int currentline = start;
String line = null;
List<Integer> tmpIgnoreLines = new ArrayList<>();
int match = 0;

BufferedReader bufReader = new BufferedReader(new StringReader(textContent));

try {
while( (line=bufReader.readLine()) != null )
{
if ( line.contains("!---") ) {
if (!tmpIgnoreLines.contains(currentline)) {
tmpIgnoreLines.add(currentline);
}
match = 1;
}

if ( line.contains("@CFLintIgnore") && match > 0 ) {
if (!tmpIgnoreLines.contains(currentline)) {
tmpIgnoreLines.add(currentline);
}
match = 2;
}

if ( line.contains("CFQUERYPARAM_REQ") && match > 1 ) {
if (!tmpIgnoreLines.contains(currentline)) {
tmpIgnoreLines.add(currentline);
}
match = 3;
}

if ( line.contains("--->") && match > 2 ) {
if (!tmpIgnoreLines.contains(currentline)) {
tmpIgnoreLines.add(currentline);
}
if (!tmpIgnoreLines.contains(currentline+1)) {
tmpIgnoreLines.add(currentline+1);
}
ignoreLines.addAll(tmpIgnoreLines);
tmpIgnoreLines.clear();
match = 0;
}

currentline++;

}
} catch(Exception e) {
e.printStackTrace();
}

return ignoreLines;
}

Expand Down
11 changes: 10 additions & 1 deletion src/main/resources/cflint.definition.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,16 @@
"severity": "WARNING"
}
],
"parameter": []
"parameter": [
{
"name": "allowVariableExpression",
"value": ""
},
{
"name": "allowLineExpression",
"value": ""
}
]
},
{
"name": "TypedQueryNew",
Expand Down
3 changes: 3 additions & 0 deletions src/test/java/com/cflint/TestCFBugs_QueryParams.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ public void testCFScript_QueryParams_ignore_offset() throws CFLintScanException
" ON C.aID = A.aID\n" +
" AND C.bar = #magicVal# <!--- \n" +
" @CFLintIgnore CFQUERYPARAM_REQ --->\n" +
" <!--- @CFLintIgnore CFQUERYPARAM_REQ --->\n" +
" #delim# C.bar = <cfqueryparam\n " +
" value='#magicVal#' /> \n" +
" WHERE \n" +
" <!---\n" +
" @CFLintIgnore CFQUERYPARAM_REQ\n" +
Expand Down
Loading