[pitboss/grind] deferred session-0001 (20260521T143544Z-f898)

This commit is contained in:
pitboss 2026-05-21 10:42:31 -05:00
parent 1e122b615e
commit be4021d8c0
2 changed files with 41 additions and 11 deletions

View file

@ -68,21 +68,29 @@ pub fn source_imports_micronaut(bytes: &[u8]) -> bool {
}
/// True when `bytes` carries any of the well-known Java Servlet API
/// import stanzas or a class extending `HttpServlet`. The bare
/// `HttpServletRequest` / `HttpServletResponse` stub-class names also
/// fire so the Phase 14 default-package fixture path lights up the
/// adapter without a Jakarta servlet jar.
/// import stanzas or a class extending `HttpServlet`. Files that name
/// the bare `HttpServletRequest` / `HttpServletResponse` types as stub
/// classes only mention one of the two; the Phase 14 default-package
/// fixture path uses both in the same file, so requiring both type
/// tokens together keeps the fixture path lit while rejecting
/// single-token stub helper files.
pub fn source_imports_servlet(bytes: &[u8]) -> bool {
contains_any(
let has_canonical = contains_any(
bytes,
&[
b"javax.servlet",
b"jakarta.servlet",
b"HttpServletRequest",
b"HttpServletResponse",
b"extends HttpServlet",
],
)
);
if has_canonical {
return true;
}
contains(bytes, b"HttpServletRequest") && contains(bytes, b"HttpServletResponse")
}
fn contains(haystack: &[u8], needle: &[u8]) -> bool {
haystack.windows(needle.len()).any(|w| w == needle)
}
fn contains_any(haystack: &[u8], needles: &[&[u8]]) -> bool {
@ -379,6 +387,29 @@ mod tests {
assert_eq!(method.kind(), "method_declaration");
}
#[test]
fn source_imports_servlet_rejects_lone_stub_files() {
let req_stub: &[u8] = b"public class HttpServletRequest {\n private String body;\n public String getBody() { return body; }\n}\n";
let resp_stub: &[u8] = b"public class HttpServletResponse {\n private int status;\n public int getStatus() { return status; }\n}\n";
assert!(!source_imports_servlet(req_stub));
assert!(!source_imports_servlet(resp_stub));
}
#[test]
fn source_imports_servlet_accepts_canonical_imports() {
let canonical: &[u8] =
b"import jakarta.servlet.http.HttpServletRequest;\npublic class V {}\n";
let extends: &[u8] = b"public class V extends HttpServlet {}\n";
assert!(source_imports_servlet(canonical));
assert!(source_imports_servlet(extends));
}
#[test]
fn source_imports_servlet_accepts_default_package_fixture() {
let vuln: &[u8] = b"public class V {\n public void doGet(HttpServletRequest req, HttpServletResponse resp) {}\n}\n";
assert!(source_imports_servlet(vuln));
}
#[test]
fn extracts_brace_placeholders() {
assert_eq!(extract_path_placeholders("/users/{id}"), vec!["id"]);

View file

@ -232,9 +232,8 @@ pub fn bind_rust_path_params(formals: &[String], path: &str) -> Vec<ParamBinding
} else {
let positional_slot = non_implicit_seen;
non_implicit_seen += 1;
if placeholders.iter().any(|p| p == name) {
ParamSource::PathSegment(name.clone())
} else if positional_slot < typed_anon_count {
let is_named_match = placeholders.iter().any(|p| p == name);
if is_named_match || positional_slot < typed_anon_count {
ParamSource::PathSegment(name.clone())
} else {
ParamSource::QueryParam(name.clone())