precondition inference

**Precondition inference** is the process of **automatically determining the required conditions that must be true before a function executes correctly** — discovering input constraints, state requirements, and assumptions that functions depend on, without requiring manual specification writing. **What Is a Precondition?** - **Precondition**: A condition that must hold when a function is called for it to behave correctly. - **Examples**: - `array != null` — array must not be null - `index >= 0 && index < array.length` — index must be valid - `amount > 0` — amount must be positive - `file.isOpen()` — file must be open before reading **Why Infer Preconditions?** - **Documentation**: Automatically document function requirements. - **Bug Prevention**: Callers can check preconditions before calling — prevent crashes and errors. - **Verification**: Preconditions are essential for formal verification. - **Test Generation**: Generate valid test inputs that satisfy preconditions. - **API Understanding**: Help developers understand how to correctly use functions. **How Precondition Inference Works** - **Static Analysis**: Analyze code to identify conditions that must hold. - Look for assertions, exceptions, null checks, bounds checks. - Trace backward from error conditions to find required preconditions. - **Dynamic Analysis**: Observe executions to learn preconditions. - Run function with various inputs, observe which succeed and which fail. - Infer preconditions that distinguish successful from failing executions. - **Symbolic Execution**: Explore paths symbolically to derive preconditions. - Compute path conditions for successful execution. - Negate conditions leading to errors to get preconditions. - **Machine Learning**: Learn preconditions from examples. - Train models on (input, success/failure) pairs. - Extract decision boundaries as preconditions. **Example: Precondition Inference** ```python def divide(a, b): return a / b # Inferred precondition: b != 0 # (Otherwise ZeroDivisionError) def get_element(arr, index): return arr[index] # Inferred preconditions: # - arr != null # - 0 <= index < len(arr) # (Otherwise IndexError) def withdraw(account, amount): if amount <= 0: raise ValueError("Amount must be positive") if account.balance < amount: raise InsufficientFundsError() account.balance -= amount # Inferred preconditions: # - amount > 0 # - account.balance >= amount ``` **Static Precondition Inference** - **Approach**: Analyze code to find conditions that prevent errors. ```python def process_user(user): # Code checks user.age if user.age < 18: return "Minor" else: return "Adult" # Inferred precondition: user != null AND user.age is defined # (Otherwise AttributeError) ``` - **Techniques**: - **Null Pointer Analysis**: Identify where null checks are needed. - **Bounds Analysis**: Determine valid ranges for array indices and numeric values. - **Exception Analysis**: Trace back from exception throws to find preventing conditions. **Dynamic Precondition Inference** - **Approach**: Run function with many inputs, observe successes and failures. ```python # Function: def sqrt(x): return x ** 0.5 # Test inputs: sqrt(4) → 2.0 (success) sqrt(0) → 0.0 (success) sqrt(-1) → complex number or error (failure) # Inferred precondition: x >= 0 ``` - **Daikon-Style**: Collect traces of successful executions, find properties that always hold for inputs. **Symbolic Execution for Preconditions** - **Approach**: Symbolically execute function, collect path conditions. ```python def abs_value(x): if x < 0: return -x else: return x # Symbolic execution: # Path 1: x < 0 → return -x (requires x < 0) # Path 2: x >= 0 → return x (requires x >= 0) # Combined precondition: true (no restriction, works for all x) def safe_divide(a, b): if b == 0: raise ValueError() return a / b # Symbolic execution: # Path 1: b == 0 → exception # Path 2: b != 0 → return a/b (success) # Precondition for success: b != 0 ``` **LLM-Based Precondition Inference** - **Code Analysis**: LLMs analyze function code to identify implicit preconditions. - **Natural Language**: LLMs express preconditions in human-readable form. - **Documentation Mining**: LLMs extract preconditions from comments and documentation. **Example: LLM Inferring Preconditions** ```python def binary_search(arr, target): left, right = 0, len(arr) - 1 while left <= right: mid = (left + right) // 2 if arr[mid] == target: return mid elif arr[mid] < target: left = mid + 1 else: right = mid - 1 return -1 # LLM-inferred preconditions: """ Preconditions: - arr is not null/None - arr is sorted in ascending order - target is comparable with elements of arr Without these preconditions: - If arr is None: AttributeError - If arr is unsorted: incorrect result (not an error, but wrong answer) - If target is incomparable: TypeError """ ``` **Applications** - **API Documentation**: Automatically document function requirements. - **Defensive Programming**: Insert precondition checks at function entry. ```python def withdraw(account, amount): assert amount > 0, "Amount must be positive" assert account.balance >= amount, "Insufficient funds" # ... rest of function ``` - **Contract-Based Programming**: Generate contracts for design-by-contract systems. - **Test Input Generation**: Generate test inputs that satisfy preconditions. - **Static Analysis**: Use preconditions to improve precision of static analyzers. **Challenges** - **Completeness**: May not discover all preconditions, especially complex ones. - **Precision**: May infer preconditions that are too strong (overly restrictive) or too weak (insufficient). - **Implicit Preconditions**: Some preconditions are implicit in the domain — hard to infer from code alone. - **Validation**: Determining whether inferred preconditions are correct requires human judgment. **Evaluation** - **Soundness**: Are inferred preconditions actually required? - **Completeness**: Are all necessary preconditions discovered? - **Usefulness**: Do inferred preconditions help developers? Precondition inference is a **valuable program analysis technique** — it automatically discovers function requirements, improving documentation, enabling verification, and helping developers use APIs correctly.

Go deeper with CFSGPT

Get AI-powered deep-dives, save terms, and run advanced simulations — free account.

Create Free Account