Skip to content

Commit eb23dbe

Browse files
committed
fix regex issues for repeated varnames and empty brackets. fix issue with zero or negative line numbers.
1 parent f941ec9 commit eb23dbe

1 file changed

Lines changed: 47 additions & 23 deletions

File tree

cli/cppcheckexecutor.cpp

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -143,35 +143,57 @@ namespace {
143143

144144
// Variable name patterns - replace specific variable names with generic terms
145145
// But be careful not to replace legitimate words like "pointer" in "C-style pointer casting"
146-
result = std::regex_replace(result, std::regex(R"('arr\[\d+\]')"), "'array'");
147-
result = std::regex_replace(result, std::regex(R"('varname')"), "'variable'");
148146

149-
// Replace quoted variable names but preserve legitimate words
150-
// Only replace single-quoted variable names that are clearly identifiers
147+
// Handle common variable/function patterns by removing quoted names entirely
148+
result = std::regex_replace(result, std::regex(R"(Variable '[^']*' is)"), "Variable is");
149+
result = std::regex_replace(result, std::regex(R"(variable '[^']*' is)"), "variable is");
150+
result = std::regex_replace(result, std::regex(R"(Variable '[^']*' )"), "Variable ");
151+
result = std::regex_replace(result, std::regex(R"(variable '[^']*' )"), "variable ");
152+
result = std::regex_replace(result, std::regex(R"(Function '[^']*' )"), "Function ");
153+
result = std::regex_replace(result, std::regex(R"(function '[^']*' )"), "function ");
154+
result = std::regex_replace(result, std::regex(R"(Parameter '[^']*' )"), "Parameter ");
155+
result = std::regex_replace(result, std::regex(R"(parameter '[^']*' )"), "parameter ");
156+
157+
// Handle "of 'varname'" -> "of variable"
158+
result = std::regex_replace(result, std::regex(R"( of '[^']*')"), " of variable");
159+
160+
// Handle trailing quoted variable names at end of sentences
161+
result = std::regex_replace(result, std::regex(R"(: '[^']*'$)"), "");
162+
result = std::regex_replace(result, std::regex(R"(: '[^']*'\.)"), ".");
163+
164+
// Handle array patterns like 'arr[16]' -> 'array'
165+
result = std::regex_replace(result, std::regex(R"('[a-zA-Z_][a-zA-Z0-9_]*\[\d+\]')"), "'array'");
166+
167+
// Handle expression patterns for overflow messages
168+
if (ruleId == "integerOverflow" || ruleId == "integerOverflowCond")
169+
{
170+
// Replace "for expression 'expr'" with "for expression"
171+
result = std::regex_replace(result, std::regex(R"(for expression '[^']*')"), "for expression");
172+
}
173+
174+
// Replace remaining single-quoted identifiers with generic terms
175+
// Only replace if they look like variable names (start with letter/underscore)
151176
result = std::regex_replace(result, std::regex(R"('\b[a-zA-Z_][a-zA-Z0-9_]*\b')"), "'variable'");
152177

153-
// Replace specific patterns like "Variable 'varname' is..."
154-
result = std::regex_replace(result, std::regex(R"(Variable '[^']*')"), "Variable 'variable'");
155-
result = std::regex_replace(result, std::regex(R"(variable '[^']*')"), "variable 'variable'");
178+
// Clean up redundant 'variable' references
179+
// Replace patterns where we now have redundant "Variable 'variable'"
180+
result = std::regex_replace(result, std::regex(R"(Variable 'variable')"), "Variable");
181+
result = std::regex_replace(result, std::regex(R"(variable 'variable')"), "variable");
182+
result = std::regex_replace(result, std::regex(R"(Function 'variable')"), "Function");
183+
result = std::regex_replace(result, std::regex(R"(function 'variable')"), "function");
184+
result = std::regex_replace(result, std::regex(R"(Parameter 'variable')"), "Parameter");
185+
result = std::regex_replace(result, std::regex(R"(parameter 'variable')"), "parameter");
186+
result = std::regex_replace(
187+
result, std::regex(R"(Memory pointed to by 'variable')"), "Memory pointed to by variable");
188+
189+
// Handle include file patterns with empty angle brackets
190+
result = std::regex_replace(result, std::regex(R"(Include file: <> )"), "Include file: ");
156191

157192
// Number patterns - replace specific numbers with generic terms
158193
result = std::regex_replace(result, std::regex(R"( \d+ )"), " N ");
159194
result = std::regex_replace(result, std::regex(R"( at index \d+)"), " at index N");
160195

161-
// Function name patterns
162-
result = std::regex_replace(result, std::regex(R"(function '[^']*')"), "function");
163-
result = std::regex_replace(result, std::regex(R"(Function '[^']*')"), "Function");
164-
165-
// Clean up empty quotes and redundant spaces
166-
// Handle cases where parameter/variable names were empty or completely removed
167-
result = std::regex_replace(result, std::regex(R"(parameter ''\s)"), "parameter ");
168-
result = std::regex_replace(result, std::regex(R"(Parameter ''\s)"), "Parameter ");
169-
result = std::regex_replace(result, std::regex(R"(variable ''\s)"), "variable ");
170-
result = std::regex_replace(result, std::regex(R"(Variable ''\s)"), "Variable ");
171-
result = std::regex_replace(result, std::regex(R"(function ''\s)"), "function ");
172-
result = std::regex_replace(result, std::regex(R"(Function ''\s)"), "Function ");
173-
174-
// Handle standalone empty quotes
196+
// Clean up any remaining empty quotes and redundant spaces
175197
result = std::regex_replace(result, std::regex(R"(\s''\s)"), " ");
176198
result = std::regex_replace(result, std::regex(R"(^''\s)"), "");
177199
result = std::regex_replace(result, std::regex(R"(\s''$)"), "");
@@ -349,9 +371,11 @@ namespace {
349371
artifactLocation["uri"] = picojson::value(location.getfile(false));
350372
physicalLocation["artifactLocation"] = picojson::value(artifactLocation);
351373
picojson::object region;
352-
region["startLine"] = picojson::value(static_cast<int64_t>(location.line));
353-
region["startColumn"] = picojson::value(static_cast<int64_t>(location.column));
374+
// Ensure line numbers are always positive (SARIF requires positive line numbers)
375+
const int64_t lineNumber = (location.line > 0) ? location.line : 1;
376+
region["startLine"] = picojson::value(lineNumber);
354377
region["endLine"] = region["startLine"];
378+
region["startColumn"] = picojson::value(static_cast<int64_t>(location.column));
355379
region["endColumn"] = region["startColumn"];
356380
physicalLocation["region"] = picojson::value(region);
357381
picojson::object loc;

0 commit comments

Comments
 (0)