`DB/PreparedSQL` and `DB/PreparedSQLPlaceholders`: how should namespaced function calls be handled?
The WordPress.DB.PreparedSQL and WordPress.DB.PreparedSQLPlaceholders sniffs check for specific functions to determine if certain code patterns are safe. I have a question about how these sniffs should handle namespace-prefixed calls like MyNamespace\absint() or \MyNamespace\absint().
WordPress.DB.PreparedSQL looks for:
- SQL escaping functions:
absint(),esc_sql(),floatval(),intval(),like_escape(). - SQL auto-escaped functions:
count(). - Formatting functions:
sprintf(),vsprintf(),wp_sprintf(),implode(),join(),array_fill(),antispambot(),ent2ncr(),nl2br().
WordPress.DB.PreparedSQLPlaceholders checks for:
-
sprintf(),implode(), andarray_fill()to detect specific variable placeholder patterns.
Currently, both sniffs don't properly differentiate between global and namespaced function calls:
-
When
WordPress.DB.PreparedSQLsees code likeMyNamespace\absint($foo), it generates an error forMyNamespacebut then incorrectly treatsabsint()as if it were a global function call and doesn't check its parameters. -
WordPress.DB.PreparedSQLPlaceholdersdoesn't differentiate at all - it accepts bothsprintf()andMyNamespace\sprintf()as valid for the dynamic placeholder generation pattern.
Question for discussion
Should these sniffs treat namespace-prefixed function calls that mirror the name of global functions they check as different functions and treat them accordingly?
I'm inclined to think that they should, but given the discussion in #2619, I'm not sure. In that issue, it was decided that WordPress.DB.DirectDatabaseQuery should treat namespaced functions like MyNamespace\wp_cache_get() as valid custom cache implementations (effectively treating it the same way as wp_cache_get()). However, security sniffs like WordPress.Security.NonceVerification and WordPress.Security.ValidatedSanitizedInput use stricter global-function-only matching. I'm curious which approach makes more sense for these two DB sniffs.
Should these sniffs treat namespace-prefixed function calls that mirror the name of global functions they check as different functions and treat them accordingly?
In my opinion: yes.
Reason for this opinion to be different from my opinion regarding the DirectDatabaseQuery sniff:
- The chances of methods/namespaced functions with a name like
wp_cache_get()to do something different than getting the cach from WP are very very slim, while with much more generic names likejoin(), a method or namespaced function with that name could well be doing something domain specific and not mirror the PHP native functionality we allow for. - The
DirectDatabaseQuerysniff is not a security sniff, while thePreparedSQL*sniffs are security related sniffs, so should be less tolerant.