fix(security): Resolve SonarQube security hotspots
SonarQube Analysis / sonarqube (pull_request) Successful in 3m9s
SonarQube Analysis / sonarqube (pull_request) Successful in 3m9s
Introduce a default regex match timeout across the library to prevent potential ReDoS attacks (SonarQube rule S6444). Implement `[OnDeserialized]` methods to re-establish object invariants and validate state after deserialization, addressing SonarQube rule S5766.
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Strata.SqlTools.SqlBreakdown.Classes;
|
||||
using Strata.SqlTools.SqlBreakdown.Enums.SQL;
|
||||
using Strata.SqlTools.SqlBreakdown.Utilities;
|
||||
|
||||
namespace Strata.SqlTools.Statements.SqlServer;
|
||||
|
||||
@@ -35,7 +36,7 @@ public class StatementParser
|
||||
// Remove SQL comments before processing
|
||||
sql = RemoveSqlComments(sql);
|
||||
// Replace multiple whitespace/newlines with single space
|
||||
sql = Regex.Replace(sql, @"\s+", " ");
|
||||
sql = Regex.Replace(sql, @"\s+", " ", RegexOptions.None, RegexDefaults.MatchTimeout);
|
||||
return sql.Trim();
|
||||
}
|
||||
|
||||
@@ -47,7 +48,7 @@ public class StatementParser
|
||||
public virtual string NormalizeSqlPreservingComments(string sql)
|
||||
{
|
||||
// Replace multiple spaces/tabs with single space, but preserve newlines for comment handling
|
||||
sql = Regex.Replace(sql, @"[ \t]+", " ");
|
||||
sql = Regex.Replace(sql, @"[ \t]+", " ", RegexOptions.None, RegexDefaults.MatchTimeout);
|
||||
// Remove leading/trailing whitespace from each line
|
||||
var lines = sql.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
|
||||
sql = string.Join("\n", lines.Select(line => line.Trim()));
|
||||
@@ -238,7 +239,7 @@ public class StatementParser
|
||||
|
||||
// Simple extraction: look for statements before the main SELECT
|
||||
var selectIndex = Regex.Match(
|
||||
sql, @"\bSELECT\b", RegexOptions.IgnoreCase).Index;
|
||||
sql, @"\bSELECT\b", RegexOptions.IgnoreCase, RegexDefaults.MatchTimeout).Index;
|
||||
|
||||
if (selectIndex > 0)
|
||||
{
|
||||
@@ -275,7 +276,7 @@ public class StatementParser
|
||||
// Look for DROP TABLE or other cleanup statements after the main query
|
||||
var finishPattern = GetFinishClausePattern();
|
||||
var match = Regex.Match(
|
||||
sql, finishPattern, RegexOptions.IgnoreCase);
|
||||
sql, finishPattern, RegexOptions.IgnoreCase, RegexDefaults.MatchTimeout);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
@@ -302,7 +303,7 @@ public class StatementParser
|
||||
|
||||
// Check if SQL starts with WITH
|
||||
var withMatch = Regex.Match(
|
||||
sql, @"^\s*WITH\b", RegexOptions.IgnoreCase);
|
||||
sql, @"^\s*WITH\b", RegexOptions.IgnoreCase, RegexDefaults.MatchTimeout);
|
||||
|
||||
if (!withMatch.Success)
|
||||
{
|
||||
@@ -330,7 +331,7 @@ public class StatementParser
|
||||
// Check if we're at a SELECT keyword at top level
|
||||
var selectMatch = Regex.Match(
|
||||
sql.Substring(i), @"^\s*SELECT\b",
|
||||
RegexOptions.IgnoreCase);
|
||||
RegexOptions.IgnoreCase, RegexDefaults.MatchTimeout);
|
||||
|
||||
if (selectMatch.Success && IsTopLevelKeyword(sql, i + selectMatch.Index))
|
||||
{
|
||||
@@ -398,7 +399,7 @@ public class StatementParser
|
||||
}
|
||||
|
||||
if (!Regex.IsMatch(sqlTrimmed, @"^\s*(WITH|SELECT)\b",
|
||||
RegexOptions.IgnoreCase))
|
||||
RegexOptions.IgnoreCase, RegexDefaults.MatchTimeout))
|
||||
{
|
||||
errorMessage = "SQL statement must start with WITH or SELECT.";
|
||||
clauses = null;
|
||||
@@ -830,7 +831,7 @@ public class StatementParser
|
||||
/// <param name="paramPattern">The regex pattern to match parameter names.</param>
|
||||
protected virtual void ExtractParameters(Dictionary<string, object> parameters, string sql, string paramPattern)
|
||||
{
|
||||
var matches = Regex.Matches(sql, paramPattern);
|
||||
var matches = Regex.Matches(sql, paramPattern, RegexOptions.None, RegexDefaults.MatchTimeout);
|
||||
|
||||
var paramNames = matches.Cast<Match>()
|
||||
.Select(match => match.Value)
|
||||
|
||||
Reference in New Issue
Block a user