diff --git a/crates/ruff/src/checkers/ast/mod.rs b/crates/ruff/src/checkers/ast/mod.rs index 33a16e339c..78fb6b8c3a 100644 --- a/crates/ruff/src/checkers/ast/mod.rs +++ b/crates/ruff/src/checkers/ast/mod.rs @@ -2623,7 +2623,7 @@ where } } if self.enabled(Rule::NoExplicitStacklevel) { - flake8_bugbear::rules::no_explicit_stacklevel(self, func, args, keywords); + flake8_bugbear::rules::no_explicit_stacklevel(self, func, keywords); } if self.enabled(Rule::UnnecessaryDictKwargs) { flake8_pie::rules::unnecessary_dict_kwargs(self, expr, keywords); @@ -2647,7 +2647,7 @@ where flake8_bandit::rules::snmp_weak_cryptography(self, func, args, keywords); } if self.enabled(Rule::Jinja2AutoescapeFalse) { - flake8_bandit::rules::jinja2_autoescape_false(self, func, args, keywords); + flake8_bandit::rules::jinja2_autoescape_false(self, func, keywords); } if self.enabled(Rule::HardcodedPasswordFuncArg) { flake8_bandit::rules::hardcoded_password_func_arg(self, keywords); @@ -2661,15 +2661,13 @@ where ); } if self.enabled(Rule::RequestWithoutTimeout) { - flake8_bandit::rules::request_without_timeout(self, func, args, keywords); + flake8_bandit::rules::request_without_timeout(self, func, keywords); } if self.enabled(Rule::ParamikoCall) { flake8_bandit::rules::paramiko_call(self, func); } if self.enabled(Rule::LoggingConfigInsecureListen) { - flake8_bandit::rules::logging_config_insecure_listen( - self, func, args, keywords, - ); + flake8_bandit::rules::logging_config_insecure_listen(self, func, keywords); } if self.any_enabled(&[ Rule::SubprocessWithoutShellEqualsTrue, diff --git a/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs b/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs index bf368e89e7..7173e5579d 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs @@ -2,7 +2,6 @@ use rustpython_parser::ast::{self, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::SimpleCallArgs; use crate::checkers::ast::Checker; @@ -30,12 +29,7 @@ impl Violation for Jinja2AutoescapeFalse { } /// S701 -pub(crate) fn jinja2_autoescape_false( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { +pub(crate) fn jinja2_autoescape_false(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) { if checker .semantic() .resolve_call_path(func) @@ -43,10 +37,13 @@ pub(crate) fn jinja2_autoescape_false( matches!(call_path.as_slice(), ["jinja2", "Environment"]) }) { - let call_args = SimpleCallArgs::new(args, keywords); - - if let Some(autoescape_arg) = call_args.keyword_argument("autoescape") { - match autoescape_arg { + if let Some(keyword) = keywords.iter().find(|keyword| { + keyword + .arg + .as_ref() + .map_or(false, |arg| arg.as_str() == "autoescape") + }) { + match &keyword.value { Expr::Constant(ast::ExprConstant { value: Constant::Bool(true), .. @@ -56,14 +53,14 @@ pub(crate) fn jinja2_autoescape_false( if id != "select_autoescape" { checker.diagnostics.push(Diagnostic::new( Jinja2AutoescapeFalse { value: true }, - autoescape_arg.range(), + keyword.range(), )); } } } _ => checker.diagnostics.push(Diagnostic::new( Jinja2AutoescapeFalse { value: true }, - autoescape_arg.range(), + keyword.range(), )), } } else { diff --git a/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs b/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs index 0953a96113..58554c2608 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs @@ -2,7 +2,6 @@ use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::SimpleCallArgs; use crate::checkers::ast::Checker; @@ -20,7 +19,6 @@ impl Violation for LoggingConfigInsecureListen { pub(crate) fn logging_config_insecure_listen( checker: &mut Checker, func: &Expr, - args: &[Expr], keywords: &[Keyword], ) { if checker @@ -30,12 +28,17 @@ pub(crate) fn logging_config_insecure_listen( matches!(call_path.as_slice(), ["logging", "config", "listen"]) }) { - let call_args = SimpleCallArgs::new(args, keywords); - - if call_args.keyword_argument("verify").is_none() { - checker - .diagnostics - .push(Diagnostic::new(LoggingConfigInsecureListen, func.range())); + if keywords.iter().any(|keyword| { + keyword + .arg + .as_ref() + .map_or(false, |arg| arg.as_str() == "verify") + }) { + return; } + + checker + .diagnostics + .push(Diagnostic::new(LoggingConfigInsecureListen, func.range())); } } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs b/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs index aea68dfef8..a85afaa7af 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs @@ -63,18 +63,18 @@ pub(crate) fn request_with_no_cert_validation( _ => None, }) { - if let Some(arg) = keywords.iter().find(|keyword| { + if let Some(keyword) = keywords.iter().find(|keyword| { keyword .arg .as_ref() .map_or(false, |arg| arg.as_str() == "verify") }) { - if is_const_false(&arg.value) { + if is_const_false(&keyword.value) { checker.diagnostics.push(Diagnostic::new( RequestWithNoCertValidation { string: target.to_string(), }, - arg.range(), + keyword.range(), )); } } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs b/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs index e62e92687c..6e80e08deb 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs @@ -2,7 +2,7 @@ use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{is_const_none, SimpleCallArgs}; +use ruff_python_ast::helpers::is_const_none; use crate::checkers::ast::Checker; @@ -49,12 +49,7 @@ impl Violation for RequestWithoutTimeout { } /// S113 -pub(crate) fn request_without_timeout( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { +pub(crate) fn request_without_timeout(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) { if checker .semantic() .resolve_call_path(func) @@ -68,12 +63,16 @@ pub(crate) fn request_without_timeout( ) }) { - let call_args = SimpleCallArgs::new(args, keywords); - if let Some(timeout) = call_args.keyword_argument("timeout") { - if is_const_none(timeout) { + if let Some(keyword) = keywords.iter().find(|keyword| { + keyword + .arg + .as_ref() + .map_or(false, |arg| arg.as_str() == "timeout") + }) { + if is_const_none(&keyword.value) { checker.diagnostics.push(Diagnostic::new( RequestWithoutTimeout { implicit: false }, - timeout.range(), + keyword.range(), )); } } else { diff --git a/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs b/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs index b4c6434d72..f0bf18827b 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs @@ -50,7 +50,7 @@ pub(crate) fn snmp_insecure_version(checker: &mut Checker, func: &Expr, keywords matches!(call_path.as_slice(), ["pysnmp", "hlapi", "CommunityData"]) }) { - if let Some(arg) = keywords.iter().find(|keyword| { + if let Some(keyword) = keywords.iter().find(|keyword| { keyword .arg .as_ref() @@ -59,12 +59,12 @@ pub(crate) fn snmp_insecure_version(checker: &mut Checker, func: &Expr, keywords if let Expr::Constant(ast::ExprConstant { value: Constant::Int(value), .. - }) = &arg.value + }) = &keyword.value { if value.is_zero() || value.is_one() { checker .diagnostics - .push(Diagnostic::new(SnmpInsecureVersion, arg.range())); + .push(Diagnostic::new(SnmpInsecureVersion, keyword.range())); } } } diff --git a/crates/ruff/src/rules/flake8_bandit/snapshots/ruff__rules__flake8_bandit__tests__S113_S113.py.snap b/crates/ruff/src/rules/flake8_bandit/snapshots/ruff__rules__flake8_bandit__tests__S113_S113.py.snap index ee0325a6d3..a1d0b8924e 100644 --- a/crates/ruff/src/rules/flake8_bandit/snapshots/ruff__rules__flake8_bandit__tests__S113_S113.py.snap +++ b/crates/ruff/src/rules/flake8_bandit/snapshots/ruff__rules__flake8_bandit__tests__S113_S113.py.snap @@ -11,11 +11,11 @@ S113.py:3:1: S113 Probable use of requests call without timeout 5 | requests.get('https://gmail.com', timeout=5) | -S113.py:4:43: S113 Probable use of requests call with timeout set to `None` +S113.py:4:35: S113 Probable use of requests call with timeout set to `None` | 3 | requests.get('https://gmail.com') 4 | requests.get('https://gmail.com', timeout=None) - | ^^^^ S113 + | ^^^^^^^^^^^^ S113 5 | requests.get('https://gmail.com', timeout=5) 6 | requests.post('https://gmail.com') | @@ -30,12 +30,12 @@ S113.py:6:1: S113 Probable use of requests call without timeout 8 | requests.post('https://gmail.com', timeout=5) | -S113.py:7:44: S113 Probable use of requests call with timeout set to `None` +S113.py:7:36: S113 Probable use of requests call with timeout set to `None` | 5 | requests.get('https://gmail.com', timeout=5) 6 | requests.post('https://gmail.com') 7 | requests.post('https://gmail.com', timeout=None) - | ^^^^ S113 + | ^^^^^^^^^^^^ S113 8 | requests.post('https://gmail.com', timeout=5) 9 | requests.put('https://gmail.com') | @@ -50,12 +50,12 @@ S113.py:9:1: S113 Probable use of requests call without timeout 11 | requests.put('https://gmail.com', timeout=5) | -S113.py:10:43: S113 Probable use of requests call with timeout set to `None` +S113.py:10:35: S113 Probable use of requests call with timeout set to `None` | 8 | requests.post('https://gmail.com', timeout=5) 9 | requests.put('https://gmail.com') 10 | requests.put('https://gmail.com', timeout=None) - | ^^^^ S113 + | ^^^^^^^^^^^^ S113 11 | requests.put('https://gmail.com', timeout=5) 12 | requests.delete('https://gmail.com') | @@ -70,12 +70,12 @@ S113.py:12:1: S113 Probable use of requests call without timeout 14 | requests.delete('https://gmail.com', timeout=5) | -S113.py:13:46: S113 Probable use of requests call with timeout set to `None` +S113.py:13:38: S113 Probable use of requests call with timeout set to `None` | 11 | requests.put('https://gmail.com', timeout=5) 12 | requests.delete('https://gmail.com') 13 | requests.delete('https://gmail.com', timeout=None) - | ^^^^ S113 + | ^^^^^^^^^^^^ S113 14 | requests.delete('https://gmail.com', timeout=5) 15 | requests.patch('https://gmail.com') | @@ -90,12 +90,12 @@ S113.py:15:1: S113 Probable use of requests call without timeout 17 | requests.patch('https://gmail.com', timeout=5) | -S113.py:16:45: S113 Probable use of requests call with timeout set to `None` +S113.py:16:37: S113 Probable use of requests call with timeout set to `None` | 14 | requests.delete('https://gmail.com', timeout=5) 15 | requests.patch('https://gmail.com') 16 | requests.patch('https://gmail.com', timeout=None) - | ^^^^ S113 + | ^^^^^^^^^^^^ S113 17 | requests.patch('https://gmail.com', timeout=5) 18 | requests.options('https://gmail.com') | @@ -110,12 +110,12 @@ S113.py:18:1: S113 Probable use of requests call without timeout 20 | requests.options('https://gmail.com', timeout=5) | -S113.py:19:47: S113 Probable use of requests call with timeout set to `None` +S113.py:19:39: S113 Probable use of requests call with timeout set to `None` | 17 | requests.patch('https://gmail.com', timeout=5) 18 | requests.options('https://gmail.com') 19 | requests.options('https://gmail.com', timeout=None) - | ^^^^ S113 + | ^^^^^^^^^^^^ S113 20 | requests.options('https://gmail.com', timeout=5) 21 | requests.head('https://gmail.com') | @@ -130,12 +130,12 @@ S113.py:21:1: S113 Probable use of requests call without timeout 23 | requests.head('https://gmail.com', timeout=5) | -S113.py:22:44: S113 Probable use of requests call with timeout set to `None` +S113.py:22:36: S113 Probable use of requests call with timeout set to `None` | 20 | requests.options('https://gmail.com', timeout=5) 21 | requests.head('https://gmail.com') 22 | requests.head('https://gmail.com', timeout=None) - | ^^^^ S113 + | ^^^^^^^^^^^^ S113 23 | requests.head('https://gmail.com', timeout=5) | diff --git a/crates/ruff/src/rules/flake8_bandit/snapshots/ruff__rules__flake8_bandit__tests__S701_S701.py.snap b/crates/ruff/src/rules/flake8_bandit/snapshots/ruff__rules__flake8_bandit__tests__S701_S701.py.snap index 715361b52c..c8927f68d0 100644 --- a/crates/ruff/src/rules/flake8_bandit/snapshots/ruff__rules__flake8_bandit__tests__S701_S701.py.snap +++ b/crates/ruff/src/rules/flake8_bandit/snapshots/ruff__rules__flake8_bandit__tests__S701_S701.py.snap @@ -1,32 +1,32 @@ --- source: crates/ruff/src/rules/flake8_bandit/mod.rs --- -S701.py:9:68: S701 Using jinja2 templates with `autoescape=False` is dangerous and can lead to XSS. Ensure `autoescape=True` or use the `select_autoescape` function. +S701.py:9:57: S701 Using jinja2 templates with `autoescape=False` is dangerous and can lead to XSS. Ensure `autoescape=True` or use the `select_autoescape` function. | 7 | templateEnv = jinja2.Environment(autoescape=True, 8 | loader=templateLoader ) 9 | Environment(loader=templateLoader, load=templateLoader, autoescape=something) # S701 - | ^^^^^^^^^ S701 + | ^^^^^^^^^^^^^^^^^^^^ S701 10 | templateEnv = jinja2.Environment(autoescape=False, loader=templateLoader ) # S701 11 | Environment(loader=templateLoader, | -S701.py:10:45: S701 Using jinja2 templates with `autoescape=False` is dangerous and can lead to XSS. Ensure `autoescape=True` or use the `select_autoescape` function. +S701.py:10:34: S701 Using jinja2 templates with `autoescape=False` is dangerous and can lead to XSS. Ensure `autoescape=True` or use the `select_autoescape` function. | 8 | loader=templateLoader ) 9 | Environment(loader=templateLoader, load=templateLoader, autoescape=something) # S701 10 | templateEnv = jinja2.Environment(autoescape=False, loader=templateLoader ) # S701 - | ^^^^^ S701 + | ^^^^^^^^^^^^^^^^ S701 11 | Environment(loader=templateLoader, 12 | load=templateLoader, | -S701.py:13:24: S701 Using jinja2 templates with `autoescape=False` is dangerous and can lead to XSS. Ensure `autoescape=True` or use the `select_autoescape` function. +S701.py:13:13: S701 Using jinja2 templates with `autoescape=False` is dangerous and can lead to XSS. Ensure `autoescape=True` or use the `select_autoescape` function. | 11 | Environment(loader=templateLoader, 12 | load=templateLoader, 13 | autoescape=False) # S701 - | ^^^^^ S701 + | ^^^^^^^^^^^^^^^^ S701 14 | 15 | Environment(loader=templateLoader, # S701 | @@ -40,12 +40,12 @@ S701.py:15:1: S701 By default, jinja2 sets `autoescape` to `False`. Consider usi 16 | load=templateLoader) | -S701.py:29:47: S701 Using jinja2 templates with `autoescape=False` is dangerous and can lead to XSS. Ensure `autoescape=True` or use the `select_autoescape` function. +S701.py:29:36: S701 Using jinja2 templates with `autoescape=False` is dangerous and can lead to XSS. Ensure `autoescape=True` or use the `select_autoescape` function. | 27 | def fake_func(): 28 | return 'foobar' 29 | Environment(loader=templateLoader, autoescape=fake_func()) # S701 - | ^^^^^^^^^^^ S701 + | ^^^^^^^^^^^^^^^^^^^^^^ S701 | diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs b/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs index 4d034dce4a..e3f2fcd658 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs @@ -2,7 +2,6 @@ use rustpython_parser::ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::SimpleCallArgs; use crate::checkers::ast::Checker; @@ -38,12 +37,7 @@ impl Violation for NoExplicitStacklevel { } /// B028 -pub(crate) fn no_explicit_stacklevel( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { +pub(crate) fn no_explicit_stacklevel(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) { if !checker .semantic() .resolve_call_path(func) @@ -54,10 +48,12 @@ pub(crate) fn no_explicit_stacklevel( return; } - if SimpleCallArgs::new(args, keywords) - .keyword_argument("stacklevel") - .is_some() - { + if keywords.iter().any(|keyword| { + keyword + .arg + .as_ref() + .map_or(false, |arg| arg.as_str() == "stacklevel") + }) { return; }