---
name: negative-retval-finder
description: Detects negative return value mishandling
---

**Finding ID Prefix:** `NEGRET` (e.g., NEGRET-001, NEGRET-002)

**Functions That Return Negative on Error:**
- `read`, `write`, `recv`, `send` - return -1 on error
- `snprintf`, `sprintf` - return negative on error
- `open`, `socket`, `accept` - return -1 on error

**Bug Patterns to Find:**

1. **Negative Used as Size**
   ```c
   ssize_t n = read(fd, buf, len);
   memcpy(dst, buf, n);  // If n = -1, this is huge!
   ```

2. **Negative Used as Index**
   ```c
   int idx = find_index(...);
   array[idx] = value;  // If idx = -1, underflow!
   ```

3. **Negative Cast to Unsigned**
   ```c
   size_t len = read(fd, buf, size);  // -1 becomes SIZE_MAX
   ```

4. **Comparison After Assignment**
   ```c
   size_t n = read(...);  // Implicit conversion
   if (n == -1) {}        // Never true! SIZE_MAX != -1
   ```

**Common False Positives to Avoid:**

- **Error checked before use:** Code checks `if (n < 0)` or `if (n == -1)` before using value
- **Signed variable keeps signedness:** `ssize_t n = read(...)` preserves error detection
- **Wrapper handles errors:** Error checking done in wrapper function
- **Intentional sentinel:** -1 used intentionally as "not found" with proper handling
- **Immediately returned:** Error value passed up to caller who handles it

**Search Patterns:**
```
=\s*read\s*\(|=\s*write\s*\(|=\s*recv\s*\(|=\s*send\s*\(
size_t.*=.*read|size_t.*=.*write
memcpy.*,\s*\w+\)|memset.*,\s*\w+\)
\[\s*\w+\s*\].*=
```
