mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-09 19:45:13 +02:00
* refactor: Update comments for clarity and add expectations.json files for performance metrics * feat: Implement FP guard for JS/TS local-collection receivers to suppress missing ownership checks * feat: Enhance Rust parameter handling to classify local collections and prevent false ownership checks * refactor: Simplify code formatting for better readability in multiple files * refactor: Improve UTF-8 sequence length handling and enhance clarity in loop iteration * feat: Update Java and Python patterns to include new security rules * refactor: Improve comment clarity and consistency across multiple Rust files * refactor: Simplify code formatting for improved readability in integration tests and module files * refactor: Improve comment formatting and enhance clarity in assertions across multiple files
805 lines
23 KiB
Rust
805 lines
23 KiB
Rust
use crate::labels::Cap;
|
|
use crate::symbol::Lang;
|
|
|
|
/// A guard rule: functions that must dominate sinks to ensure safety.
|
|
pub struct GuardRule {
|
|
pub matchers: &'static [&'static str],
|
|
pub applies_to_sink_caps: Cap,
|
|
}
|
|
|
|
/// An auth rule: functions that perform authentication/authorization checks.
|
|
pub struct AuthRule {
|
|
pub matchers: &'static [&'static str],
|
|
}
|
|
|
|
/// An entry point rule: functions that serve as external-facing entry points.
|
|
pub struct EntryPointRule {
|
|
pub matchers: &'static [&'static str],
|
|
}
|
|
|
|
/// A resource acquire/release pair.
|
|
pub struct ResourcePair {
|
|
pub acquire: &'static [&'static str],
|
|
pub release: &'static [&'static str],
|
|
/// Patterns that look like acquire calls (e.g. `freopen` ends with `fopen`)
|
|
/// but should NOT be treated as acquisitions.
|
|
pub exclude_acquire: &'static [&'static str],
|
|
pub resource_name: &'static str,
|
|
/// Callee patterns that read/write/operate on this specific resource type,
|
|
/// triggering use-after-close if the handle is closed. Checked before the
|
|
/// global `RESOURCE_USE_PATTERNS` fallback.
|
|
pub use_patterns: &'static [&'static str],
|
|
}
|
|
|
|
// ── Guard rules ─────────────────────────────────────────────────────────
|
|
|
|
static COMMON_GUARDS: &[GuardRule] = &[
|
|
GuardRule {
|
|
matchers: &["validate", "sanitize"],
|
|
applies_to_sink_caps: Cap::all(),
|
|
},
|
|
GuardRule {
|
|
matchers: &["check_", "verify_", "assert_"],
|
|
applies_to_sink_caps: Cap::all(),
|
|
},
|
|
GuardRule {
|
|
matchers: &["shell_escape", "quote", "escape_shell"],
|
|
applies_to_sink_caps: Cap::SHELL_ESCAPE,
|
|
},
|
|
GuardRule {
|
|
matchers: &["html_escape", "encode_safe", "escape_html", "sanitize_html"],
|
|
applies_to_sink_caps: Cap::HTML_ESCAPE,
|
|
},
|
|
GuardRule {
|
|
matchers: &["url_encode", "encode_uri", "urlencode"],
|
|
applies_to_sink_caps: Cap::URL_ENCODE,
|
|
},
|
|
GuardRule {
|
|
matchers: &[
|
|
"which",
|
|
"resolve_binary",
|
|
"find_program",
|
|
"lookup_path",
|
|
"shutil.which",
|
|
],
|
|
applies_to_sink_caps: Cap::SHELL_ESCAPE,
|
|
},
|
|
];
|
|
|
|
pub fn guard_rules(_lang: Lang) -> &'static [GuardRule] {
|
|
// All languages share the common set for now; per-language
|
|
// overrides can be added via match arms when needed.
|
|
COMMON_GUARDS
|
|
}
|
|
|
|
// ── Auth rules ──────────────────────────────────────────────────────────
|
|
|
|
static COMMON_AUTH: &[AuthRule] = &[AuthRule {
|
|
matchers: &[
|
|
"is_authenticated",
|
|
"require_auth",
|
|
"check_permission",
|
|
"is_admin",
|
|
"authorize",
|
|
"authenticate",
|
|
"require_login",
|
|
"check_auth",
|
|
"verify_token",
|
|
"validate_token",
|
|
// Additional patterns
|
|
"ensureAuthenticated",
|
|
"ensureAuth",
|
|
"requireAuth",
|
|
"hasPermission",
|
|
"requireRole",
|
|
],
|
|
}];
|
|
|
|
static GO_AUTH: &[AuthRule] = &[AuthRule {
|
|
matchers: &[
|
|
"is_authenticated",
|
|
"require_auth",
|
|
"check_permission",
|
|
"is_admin",
|
|
"authorize",
|
|
"authenticate",
|
|
"require_login",
|
|
"check_auth",
|
|
"verify_token",
|
|
"validate_token",
|
|
"middleware.auth",
|
|
"auth.required",
|
|
// Additional patterns
|
|
"ensureAuthenticated",
|
|
"ensureAuth",
|
|
"requireAuth",
|
|
"hasPermission",
|
|
"requireRole",
|
|
],
|
|
}];
|
|
|
|
static JAVA_AUTH: &[AuthRule] = &[AuthRule {
|
|
matchers: &[
|
|
"is_authenticated",
|
|
"require_auth",
|
|
"check_permission",
|
|
"is_admin",
|
|
"authorize",
|
|
"authenticate",
|
|
"require_login",
|
|
"check_auth",
|
|
"verify_token",
|
|
"validate_token",
|
|
"isAuthenticated",
|
|
"checkPermission",
|
|
"hasAuthority",
|
|
"hasRole",
|
|
// Additional patterns
|
|
"ensureAuthenticated",
|
|
"ensureAuth",
|
|
"requireAuth",
|
|
"hasPermission",
|
|
"requireRole",
|
|
// Spring Security / JAX-RS annotation names (used by decorator
|
|
// detection, see `extract_auth_decorators` in src/cfg.rs).
|
|
"PreAuthorize",
|
|
"PostAuthorize",
|
|
"Secured",
|
|
"RolesAllowed",
|
|
"DenyAll",
|
|
"Authenticated",
|
|
],
|
|
}];
|
|
|
|
static JS_AUTH: &[AuthRule] = &[AuthRule {
|
|
matchers: &[
|
|
"is_authenticated",
|
|
"require_auth",
|
|
"check_permission",
|
|
"is_admin",
|
|
"authorize",
|
|
"authenticate",
|
|
"require_login",
|
|
"check_auth",
|
|
"verify_token",
|
|
"validate_token",
|
|
// JS/TS middleware & JWT
|
|
"ensureAuthenticated",
|
|
"ensureAuth",
|
|
"requireAuth",
|
|
"hasPermission",
|
|
"requireRole",
|
|
"checkRole",
|
|
"passport.authenticate",
|
|
"jwt.verify",
|
|
// NestJS-style decorators and guard class names (seeded by decorator
|
|
// arg extraction in `extract_auth_decorators`). `UseGuards` alone is
|
|
// too generic, we still match on guard *argument* identifiers here.
|
|
"Authenticated",
|
|
"AuthGuard",
|
|
"JwtAuthGuard",
|
|
"JwtGuard",
|
|
"RolesGuard",
|
|
"SessionGuard",
|
|
"PassportAuthGuard",
|
|
],
|
|
}];
|
|
|
|
static PYTHON_AUTH: &[AuthRule] = &[AuthRule {
|
|
matchers: &[
|
|
"is_authenticated",
|
|
"require_auth",
|
|
"check_permission",
|
|
"is_admin",
|
|
"authorize",
|
|
"authenticate",
|
|
"require_login",
|
|
"check_auth",
|
|
"verify_token",
|
|
"validate_token",
|
|
// Python-specific
|
|
"ensureAuthenticated",
|
|
"ensureAuth",
|
|
"requireAuth",
|
|
"hasPermission",
|
|
"requireRole",
|
|
"login_required",
|
|
"permission_required",
|
|
"has_permission",
|
|
"check_permissions",
|
|
// Common decorator names used by Flask-Login / Django / custom views
|
|
// (consumed by `extract_auth_decorators` on function_definition nodes).
|
|
"admin_required",
|
|
"staff_member_required",
|
|
"user_passes_test",
|
|
],
|
|
}];
|
|
|
|
static RUBY_AUTH: &[AuthRule] = &[AuthRule {
|
|
matchers: &[
|
|
"is_authenticated",
|
|
"require_auth",
|
|
"check_permission",
|
|
"is_admin",
|
|
"authorize",
|
|
"authenticate",
|
|
"require_login",
|
|
"check_auth",
|
|
"verify_token",
|
|
"validate_token",
|
|
// Devise / Rails controller-filter idioms (consumed by `before_action`
|
|
// decorator extraction).
|
|
"authenticate_user",
|
|
"authenticate_admin",
|
|
"require_user",
|
|
"require_admin",
|
|
"current_user",
|
|
],
|
|
}];
|
|
|
|
static PHP_AUTH: &[AuthRule] = &[AuthRule {
|
|
matchers: &[
|
|
"is_authenticated",
|
|
"require_auth",
|
|
"check_permission",
|
|
"is_admin",
|
|
"authorize",
|
|
"authenticate",
|
|
"require_login",
|
|
"check_auth",
|
|
"verify_token",
|
|
"validate_token",
|
|
// Symfony Security attributes (`#[IsGranted(..)]`, `#[Security(..)]`)
|
|
// and common guard idioms.
|
|
"IsGranted",
|
|
"Security",
|
|
],
|
|
}];
|
|
|
|
static CPP_AUTH: &[AuthRule] = &[AuthRule {
|
|
matchers: &[
|
|
"is_authenticated",
|
|
"require_auth",
|
|
"check_permission",
|
|
"is_admin",
|
|
"authorize",
|
|
"authenticate",
|
|
"require_login",
|
|
"check_auth",
|
|
"verify_token",
|
|
"validate_token",
|
|
// Custom C++ attributes, framework-defined, bare-name match.
|
|
"authenticated",
|
|
"require_auth",
|
|
"admin_only",
|
|
],
|
|
}];
|
|
|
|
static RUST_AUTH: &[AuthRule] = &[AuthRule {
|
|
matchers: &[
|
|
"is_authenticated",
|
|
"require_auth",
|
|
"check_permission",
|
|
"is_admin",
|
|
"authorize",
|
|
"authenticate",
|
|
"require_login",
|
|
"check_auth",
|
|
"verify_token",
|
|
"validate_token",
|
|
// Custom proc-macro attributes, framework-defined, bare-name match.
|
|
"authenticated",
|
|
"require_auth",
|
|
"admin_only",
|
|
],
|
|
}];
|
|
|
|
pub fn auth_rules(lang: Lang) -> &'static [AuthRule] {
|
|
match lang {
|
|
Lang::Go => GO_AUTH,
|
|
Lang::Java => JAVA_AUTH,
|
|
Lang::JavaScript | Lang::TypeScript => JS_AUTH,
|
|
Lang::Python => PYTHON_AUTH,
|
|
Lang::Ruby => RUBY_AUTH,
|
|
Lang::Php => PHP_AUTH,
|
|
Lang::Cpp => CPP_AUTH,
|
|
Lang::Rust => RUST_AUTH,
|
|
_ => COMMON_AUTH,
|
|
}
|
|
}
|
|
|
|
// ── Entry point rules ───────────────────────────────────────────────────
|
|
|
|
static COMMON_ENTRY_POINTS: &[EntryPointRule] = &[EntryPointRule {
|
|
matchers: &[
|
|
"main",
|
|
"handle_*",
|
|
"route_*",
|
|
"api_*",
|
|
"serve_*",
|
|
"process_*",
|
|
],
|
|
}];
|
|
|
|
static GO_ENTRY_POINTS: &[EntryPointRule] = &[EntryPointRule {
|
|
matchers: &[
|
|
"main",
|
|
"handle_*",
|
|
"handler_*",
|
|
"route_*",
|
|
"api_*",
|
|
"serve_*",
|
|
"process_*",
|
|
"ServeHTTP",
|
|
],
|
|
}];
|
|
|
|
static PYTHON_ENTRY_POINTS: &[EntryPointRule] = &[EntryPointRule {
|
|
matchers: &[
|
|
"main",
|
|
"handle_*",
|
|
"route_*",
|
|
"api_*",
|
|
"serve_*",
|
|
"process_*",
|
|
"view_*",
|
|
],
|
|
}];
|
|
|
|
pub fn entry_point_rules(lang: Lang) -> &'static [EntryPointRule] {
|
|
match lang {
|
|
Lang::Go => GO_ENTRY_POINTS,
|
|
Lang::Python => PYTHON_ENTRY_POINTS,
|
|
_ => COMMON_ENTRY_POINTS,
|
|
}
|
|
}
|
|
|
|
// ── Resource pairs ──────────────────────────────────────────────────────
|
|
|
|
static C_RESOURCES: &[ResourcePair] = &[
|
|
ResourcePair {
|
|
acquire: &["malloc", "calloc", "realloc"],
|
|
release: &["free"],
|
|
exclude_acquire: &[],
|
|
resource_name: "memory",
|
|
use_patterns: &[],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["fopen", "fdopen", "curlx_fopen", "curlx_fdopen"],
|
|
release: &["fclose", "curlx_fclose"],
|
|
exclude_acquire: &["freopen", "curlx_freopen"],
|
|
resource_name: "file handle",
|
|
use_patterns: &[],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["open"],
|
|
release: &["close"],
|
|
exclude_acquire: &["freopen", "curlx_freopen"],
|
|
resource_name: "file descriptor",
|
|
use_patterns: &[],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["pthread_mutex_lock"],
|
|
release: &["pthread_mutex_unlock"],
|
|
exclude_acquire: &[],
|
|
resource_name: "mutex",
|
|
use_patterns: &[],
|
|
},
|
|
];
|
|
|
|
static CPP_RESOURCES: &[ResourcePair] = &[
|
|
// Inherited from C
|
|
ResourcePair {
|
|
acquire: &["malloc", "calloc", "realloc"],
|
|
release: &["free"],
|
|
exclude_acquire: &[],
|
|
resource_name: "memory",
|
|
use_patterns: &[],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["fopen", "fdopen", "curlx_fopen", "curlx_fdopen"],
|
|
release: &["fclose", "curlx_fclose"],
|
|
exclude_acquire: &["freopen", "curlx_freopen"],
|
|
resource_name: "file handle",
|
|
use_patterns: &[],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["open"],
|
|
release: &["close"],
|
|
exclude_acquire: &["freopen", "curlx_freopen"],
|
|
resource_name: "file descriptor",
|
|
use_patterns: &[],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["pthread_mutex_lock"],
|
|
release: &["pthread_mutex_unlock"],
|
|
exclude_acquire: &[],
|
|
resource_name: "mutex",
|
|
use_patterns: &[],
|
|
},
|
|
// C++ new/delete (callee normalized to "new"/"delete" in cfg.rs)
|
|
ResourcePair {
|
|
acquire: &["new"],
|
|
release: &["delete"],
|
|
exclude_acquire: &[],
|
|
resource_name: "heap object",
|
|
use_patterns: &[],
|
|
},
|
|
];
|
|
|
|
static GO_RESOURCES: &[ResourcePair] = &[
|
|
ResourcePair {
|
|
acquire: &["os.Open", "os.Create", "os.OpenFile"],
|
|
release: &[".Close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "file handle",
|
|
use_patterns: &[],
|
|
},
|
|
ResourcePair {
|
|
acquire: &[".Lock"],
|
|
release: &[".Unlock"],
|
|
exclude_acquire: &[],
|
|
resource_name: "mutex",
|
|
use_patterns: &[],
|
|
},
|
|
// Additional patterns
|
|
ResourcePair {
|
|
acquire: &["sql.Open"],
|
|
release: &[".Close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "db connection",
|
|
use_patterns: &[".Query", ".Exec", ".Prepare", ".Begin"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["net.Listen"],
|
|
release: &[".Close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "listener",
|
|
use_patterns: &[".Accept", ".Addr"],
|
|
},
|
|
];
|
|
|
|
static RUST_RESOURCES: &[ResourcePair] = &[
|
|
// Rust uses RAII, but unsafe alloc/dealloc is a pattern
|
|
ResourcePair {
|
|
acquire: &["alloc"],
|
|
release: &["dealloc"],
|
|
exclude_acquire: &[],
|
|
resource_name: "raw memory",
|
|
use_patterns: &[],
|
|
},
|
|
];
|
|
|
|
static JAVA_RESOURCES: &[ResourcePair] = &[
|
|
ResourcePair {
|
|
acquire: &[
|
|
"FileInputStream",
|
|
"FileOutputStream",
|
|
"BufferedReader",
|
|
"openConnection",
|
|
],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "stream/connection",
|
|
use_patterns: &[".read", ".write", ".flush", ".available"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["DriverManager.getConnection", "getConnection"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "db connection",
|
|
use_patterns: &[
|
|
".executeQuery",
|
|
".executeUpdate",
|
|
".createStatement",
|
|
".prepareStatement",
|
|
],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["Socket"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "socket",
|
|
use_patterns: &[".getInputStream", ".getOutputStream", ".connect"],
|
|
},
|
|
// Additional patterns
|
|
ResourcePair {
|
|
acquire: &["prepareStatement"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "prepared statement",
|
|
use_patterns: &[".executeQuery", ".executeUpdate", ".setString", ".setInt"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["executeQuery"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "result set",
|
|
use_patterns: &[".next", ".getString", ".getInt", ".getBoolean"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["ServerSocket"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "server socket",
|
|
use_patterns: &[".accept", ".bind"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["DatagramSocket"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "datagram socket",
|
|
use_patterns: &[".send", ".receive"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["RandomAccessFile"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "random access file",
|
|
use_patterns: &[".read", ".write", ".seek", ".length"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["Channel.open", "FileChannel.open", "SocketChannel.open"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "NIO channel",
|
|
use_patterns: &[".read", ".write", ".position"],
|
|
},
|
|
];
|
|
|
|
static PYTHON_RESOURCES: &[ResourcePair] = &[
|
|
ResourcePair {
|
|
acquire: &["open"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "file handle",
|
|
use_patterns: &[],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["socket.socket", "socket"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "socket",
|
|
use_patterns: &[],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["connect", "cursor"],
|
|
release: &[".close"],
|
|
exclude_acquire: &["signal.connect", "event.connect", ".register"],
|
|
resource_name: "db connection",
|
|
use_patterns: &[],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["threading.Lock", "threading.RLock"],
|
|
release: &[".release"],
|
|
exclude_acquire: &[],
|
|
resource_name: "mutex",
|
|
use_patterns: &[],
|
|
},
|
|
// Additional patterns
|
|
ResourcePair {
|
|
acquire: &["urllib.request.urlopen", "urlopen"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "url handle",
|
|
use_patterns: &[".read", ".readline", ".readlines"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &[
|
|
"http.client.HTTPConnection",
|
|
"HTTPConnection",
|
|
"HTTPSConnection",
|
|
],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "http connection",
|
|
use_patterns: &[".request", ".getresponse"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["sqlite3.connect"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "sqlite connection",
|
|
use_patterns: &[".execute", ".cursor", ".commit"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["tempfile.NamedTemporaryFile", "NamedTemporaryFile"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "temp file",
|
|
use_patterns: &[".write", ".read", ".seek"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["zipfile.ZipFile", "ZipFile"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "zip file",
|
|
use_patterns: &[".read", ".write", ".extractall", ".namelist"],
|
|
},
|
|
];
|
|
|
|
static RUBY_RESOURCES: &[ResourcePair] = &[
|
|
ResourcePair {
|
|
acquire: &["File.open", "File.new", "open"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "file handle",
|
|
use_patterns: &[
|
|
".read",
|
|
".write",
|
|
".gets",
|
|
".puts",
|
|
".each_line",
|
|
".readline",
|
|
".readlines",
|
|
".sysread",
|
|
".syswrite",
|
|
],
|
|
},
|
|
ResourcePair {
|
|
acquire: &[
|
|
"TCPSocket.new",
|
|
"UDPSocket.new",
|
|
"TCPServer.new",
|
|
"UNIXSocket.new",
|
|
],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "socket",
|
|
use_patterns: &[".read", ".write", ".send", ".recv", ".gets", ".puts"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &[".lock"],
|
|
release: &[".unlock"],
|
|
exclude_acquire: &[],
|
|
resource_name: "mutex",
|
|
use_patterns: &[],
|
|
},
|
|
ResourcePair {
|
|
acquire: &[
|
|
"PG.connect",
|
|
"PG::Connection.new",
|
|
"Sequel.connect",
|
|
"Mysql2::Client.new",
|
|
"SQLite3::Database.new",
|
|
],
|
|
release: &[".close", ".disconnect"],
|
|
exclude_acquire: &[],
|
|
resource_name: "db connection",
|
|
use_patterns: &[".exec", ".query", ".exec_params", ".prepare", ".execute"],
|
|
},
|
|
// Additional patterns
|
|
ResourcePair {
|
|
acquire: &["Net::HTTP.start"],
|
|
release: &[".finish"],
|
|
exclude_acquire: &[],
|
|
resource_name: "http connection",
|
|
use_patterns: &[".get", ".post", ".request"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["Tempfile.new", "Tempfile.open"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "temp file",
|
|
use_patterns: &[".write", ".read", ".path"],
|
|
},
|
|
];
|
|
|
|
static PHP_RESOURCES: &[ResourcePair] = &[
|
|
ResourcePair {
|
|
acquire: &["fopen"],
|
|
release: &["fclose"],
|
|
exclude_acquire: &["freopen"],
|
|
resource_name: "file handle",
|
|
use_patterns: &[],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["mysqli_connect", "mysqli"],
|
|
release: &["mysqli_close", ".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "db connection",
|
|
use_patterns: &["mysqli_query", "mysqli_fetch_array", ".query", ".fetch"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["curl_init"],
|
|
release: &["curl_close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "curl handle",
|
|
use_patterns: &["curl_exec", "curl_getinfo", "curl_setopt"],
|
|
},
|
|
// Additional patterns
|
|
ResourcePair {
|
|
acquire: &["pg_connect"],
|
|
release: &["pg_close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "pg connection",
|
|
use_patterns: &["pg_query", "pg_fetch_array", "pg_fetch_row"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["fsockopen", "pfsockopen"],
|
|
release: &["fclose"],
|
|
exclude_acquire: &[],
|
|
resource_name: "socket",
|
|
use_patterns: &["fwrite", "fread", "fgets"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["stream_socket_client"],
|
|
release: &["fclose"],
|
|
exclude_acquire: &[],
|
|
resource_name: "stream socket",
|
|
use_patterns: &["fwrite", "fread", "stream_get_contents"],
|
|
},
|
|
];
|
|
|
|
static JS_RESOURCES: &[ResourcePair] = &[
|
|
ResourcePair {
|
|
acquire: &["fs.open", "fs.openSync"],
|
|
release: &["fs.close", "fs.closeSync"],
|
|
exclude_acquire: &[],
|
|
resource_name: "file descriptor",
|
|
use_patterns: &[
|
|
"fs.readSync",
|
|
"fs.writeSync",
|
|
"fs.fstatSync",
|
|
"fs.ftruncateSync",
|
|
"fs.fsyncSync",
|
|
],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["createReadStream", "createWriteStream"],
|
|
release: &[".close", ".destroy"],
|
|
exclude_acquire: &[],
|
|
resource_name: "stream",
|
|
use_patterns: &[".pipe", ".resume", ".write", ".read", ".push"],
|
|
},
|
|
// Additional patterns
|
|
ResourcePair {
|
|
acquire: &["net.createConnection", "net.connect"],
|
|
release: &[".end", ".destroy"],
|
|
exclude_acquire: &[],
|
|
resource_name: "net socket",
|
|
use_patterns: &[".write", ".read", ".pipe"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["http.request", "https.request"],
|
|
release: &[".end", ".destroy"],
|
|
exclude_acquire: &[],
|
|
resource_name: "http request",
|
|
use_patterns: &[".write"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["WebSocket"],
|
|
release: &[".close"],
|
|
exclude_acquire: &[],
|
|
resource_name: "websocket",
|
|
use_patterns: &[".send"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["mysql.createConnection", "mysql.createPool"],
|
|
release: &[".end", ".destroy"],
|
|
exclude_acquire: &[],
|
|
resource_name: "mysql connection",
|
|
use_patterns: &[".query", ".execute"],
|
|
},
|
|
ResourcePair {
|
|
acquire: &["pg.Pool", "pg.Client"],
|
|
release: &[".end", ".release"],
|
|
exclude_acquire: &[],
|
|
resource_name: "pg connection",
|
|
use_patterns: &[".query"],
|
|
},
|
|
];
|
|
|
|
pub fn resource_pairs(lang: Lang) -> &'static [ResourcePair] {
|
|
match lang {
|
|
Lang::C => C_RESOURCES,
|
|
Lang::Cpp => CPP_RESOURCES,
|
|
Lang::Go => GO_RESOURCES,
|
|
Lang::Rust => RUST_RESOURCES,
|
|
Lang::Java => JAVA_RESOURCES,
|
|
Lang::Python => PYTHON_RESOURCES,
|
|
Lang::Ruby => RUBY_RESOURCES,
|
|
Lang::Php => PHP_RESOURCES,
|
|
Lang::JavaScript | Lang::TypeScript => JS_RESOURCES,
|
|
}
|
|
}
|