Comment by prosqlinjector
2 years ago
The only principle I want to defend is that a function is correct relative to its preconditions. If the caller doesn't meet them, that's on them.
2 years ago
The only principle I want to defend is that a function is correct relative to its preconditions. If the caller doesn't meet them, that's on them.
That kind of reasoning only works if the language or ecosystem has some kind of compile time error or linter or comprehensive testing that will catch the error if the preconditions ever change. One way of doing is is encoding the preconditions in the type system. Another is through fuzzing
If you keep the preconditions informal and never check them, the code becomes brittle to modifications and refactoring. For a sufficiently large codebase you almost guarantee that at some point you will have a SQL injection bug.
That said, using prepared statements isn't the only way to guard against SQL injections. You can also use a query builder that will escape properly all data (provided this query builder itself is hardened against bugs). Using dynamic sql is the only way to make some kinds of queries, so a query builder is a must in those cases.
What you shouldn't do is to use string concatenation to build query strings in your business logic. It may or may not contain a bug right now, but it is brittle to changes in the codebase.
> That kind of reasoning only works if the language or ecosystem has some kind of compile time error or linter or comprehensive testing that will catch the error if the preconditions ever change.
Most requirements can't be verified at compile time, or even at runtime in a feasible amount of time.
If you expect functions to do things that they don't say they do, I don't know what to tell you. Conventions and specs are the best we have.