FREE LESSON · Security & cryptography · 4 OF 6

Injection, memory safety, and data boundaries

Injection, memory safety, and data boundaries: Keep untrusted bytes from becoming instructions or addresses.

Prerequisites: Functions, memory layout, and SQL.

Learning objectives

  • Explain parameter binding.
  • Recognize context-specific injection.
  • Separate memory safety from logical correctness.

The parser decides what bytes mean

Injection occurs when data is incorporated into a language in a way that lets it change the program's structure. Building SQL by concatenating user input into a quoted expression can let that input terminate a value and introduce new syntax. Parameterized queries send the statement structure and values through separate interfaces, so a value is treated as a value.

For example, the intended query is SELECT * FROM notes WHERE owner_id = ? AND title = ?. Bind the authenticated owner and supplied title as parameters. Do not concatenate a title into the SQL string. Parameters generally represent values, not arbitrary table names or ordering keywords; dynamic structural choices need a small explicit allowlist or another safe construction supported by the library.

A boundary is specific to its language

HTML, shell commands, SQL, regular expressions, and filesystem paths have different interpretation rules. Escaping for one context does not make data safe in another. Prefer APIs that avoid invoking a parser at all: pass an argument array to a process API instead of constructing a shell command when shell syntax is unnecessary.

Path handling has its own authority question. Joining a user-supplied filename onto a directory does not necessarily keep access inside that directory. Canonicalization, traversal components, symbolic links, and race conditions can matter. A secure design uses an appropriate filesystem API and constrains which resources can be reached, rather than assuming a string prefix check proves containment.

Memory safety protects another boundary

In a language with unchecked memory operations, writing beyond an array can overwrite neighboring data or control information. Reading freed storage can use an object after its lifetime has ended. Bounds checks, ownership systems, and managed runtimes prevent important classes of these failures, though unsafe interfaces and native extensions can reintroduce them.

Memory safety does not prove authorization, correct cryptography, or correct business logic. A perfectly memory-safe program can return another user's notes. Likewise, parameterized SQL does not fix an application that binds the wrong owner ID.

Test the invariant at the boundary

Use a controlled local test environment. Supply strings containing quotes, separators, Unicode, empty values, and long inputs. Verify that they remain data and that authorization still holds. For parsers, fuzzing can discover unexpected crashes and malformed-input paths; it complements specification-based tests. Fix the structural cause, then retain a regression test. Blacklisting a few suspicious characters usually leaves the underlying interpreter boundary unchanged.

Practice problem

Design a note search using an owner ID, search text, and sort direction. Which inputs can be bound as SQL values, and how should sort direction be handled? Explain why the owner ID should not be trusted from the request body.

Worked solution

Bind the owner ID and search text through the database API’s value parameters. Select sort direction from an explicit mapping such as ascending→ASC and descending→DESC; reject unsupported choices rather than concatenating arbitrary syntax. Derive the owner ID from the verified account context, because a client can change a body field to another user’s ID. The query must still enforce visibility rules for shared notes if those exist. Test quotes and SQL-looking text as ordinary search input, and test that changing an owner field cannot expose another account’s data.

Check your understanding

What is the main benefit of SQL parameter binding?

  • It separates value data from SQL statement structure.
  • It automatically authorizes every row.
  • It encrypts the database.
  • It makes all queries fast.
Explanation

Binding prevents values from being parsed as additional SQL syntax.

Which bug can remain in a memory-safe program?

  • Every out-of-bounds native write.
  • Returning a private object to the wrong user.
  • All use-after-free errors in checked code.
  • Uninitialized pointer arithmetic by definition.
Explanation

Authorization is a logical policy that memory safety does not establish.

Primary reading

Open the study and save your work →