(
&self,
query: &sqlparser::ast::Query,
analysis: &mut SqlAnalysisResult,
depth: usize,
original_query: &str
)
| 160 | } |
| 161 | |
| 162 | fn analyze_query_statement( |
| 163 | &self, |
| 164 | query: &sqlparser::ast::Query, |
| 165 | analysis: &mut SqlAnalysisResult, |
| 166 | depth: usize, |
| 167 | original_query: &str |
| 168 | ) -> Result<(), PgSqliteError> { |
| 169 | if let sqlparser::ast::SetExpr::Select(select) = &*query.body { |
| 170 | // Analyze SELECT items |
| 171 | for item in &select.projection { |
| 172 | self.analyze_select_item(item, analysis, depth, original_query)?; |
| 173 | } |
| 174 | |
| 175 | // Analyze FROM clause |
| 176 | for table in &select.from { |
| 177 | self.analyze_table_factor(&table.relation, analysis, depth, original_query)?; |
| 178 | |
| 179 | for join in &table.joins { |
| 180 | self.analyze_join(join, analysis, depth, original_query)?; |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | // Analyze WHERE clause |
| 185 | if let Some(ref where_clause) = select.selection { |
| 186 | self.analyze_expression(where_clause, analysis, depth, original_query)?; |
| 187 | } |
| 188 | } else if let sqlparser::ast::SetExpr::SetOperation { op: _, left, right, .. } = &*query.body { |
| 189 | analysis.union_count += 1; |
| 190 | |
| 191 | // Check for suspicious UNION patterns with sensitive data |
| 192 | let query_str = original_query.to_uppercase(); |
| 193 | if (query_str.contains("UNION") && query_str.contains("PASSWORD")) || |
| 194 | (query_str.contains("UNION") && query_str.contains("ADMIN")) { |
| 195 | events::sql_injection_attempt(None, None, original_query, "suspicious union with sensitive data"); |
| 196 | return Err(PgSqliteError::InvalidParameter( |
| 197 | "Suspicious UNION with sensitive data access".to_string() |
| 198 | )); |
| 199 | } |
| 200 | |
| 201 | // Recursively analyze the left and right parts |
| 202 | let left_query = sqlparser::ast::Query { |
| 203 | body: left.clone(), |
| 204 | order_by: None, |
| 205 | limit_clause: None, |
| 206 | settings: None, |
| 207 | fetch: None, |
| 208 | locks: vec![], |
| 209 | for_clause: None, |
| 210 | with: None, |
| 211 | format_clause: None, |
| 212 | pipe_operators: vec![], |
| 213 | }; |
| 214 | |
| 215 | let right_query = sqlparser::ast::Query { |
| 216 | body: right.clone(), |
| 217 | order_by: None, |
| 218 | limit_clause: None, |
| 219 | settings: None, |
no test coverage detected