---
title: "strpos() Syndrom: When 0 And false Are Not The Same"
url: https://www.exakat.io/strpos-syndrom-when-0-and-false-are-not-the-same/
date: 2026-05-06
modified: 2026-05-06
author: "dams"
description: "strpos() Syndrom: When 0 And false Are Not The Same In PHP, several functions can return 0 or false or even null, and all these values may be confused for..."
categories:
  - "Code auditing"
tags:
  - "audit"
  - "bugs"
image: https://www.exakat.io/wp-content/uploads/2026/05/turtle.320.jpg
word_count: 614
---

# strpos() Syndrom: When 0 And false Are Not The Same

# strpos() Syndrom: When 0 And false Are Not The Same

In PHP, several functions can return **`0`** or **`false`** or even **null**, and all these values may be confused for different things.

The most popular function with this syndrom is `strpos()`, hence the name of this classic PHP bug. `strpos()` returns the position where the string was found. In the case of `b` below, it returns `1`. And `1` is truthy.

When `strpos()` does not find the requested string, as it is the case for `d`, then it returns `false`.

The problem arise when `strpos()` finds the requested string on the first position of the haystack. Then, the returned position is 0, which is falsy. At this point, `string not found` and `string found at position 0` are confused, and it leads to a bug.

In this case, an error is converted to a `false` value, while a valid return value may also be confused with `false`, such as 0, `''` (empty string), `false`, `[]` (empty array) or `null`. Nowadays, PHP tends to throw exceptions to avoid confusing one for the other, such as with `json_decode()`, though some previous behaviors are still in place.

There are some notable PHP functions which produce this behavior:

### String Functions

- **`strpos()`** – Returns the position (0 or higher) or `false` if not found.
- **`stripos()`** – Case-insensitive version of `strpos()`.
- **`strrpos()`** – Returns the position of the last occurrence or `false`.
- **`strripos()`** – Case-insensitive version of `strrpos()`.
- **`strstr()`** – Returns the substring or `false` if not found.
- **`stristr()`** – Case-insensitive version of `strstr()`.
- **`strpbrk()`** – Returns the substring or `false` if not found.

---

### Array Functions

- **`array_search()`** – Returns the key (which can be `0`) or `false` if not found.

---

### Other Functions

- **`preg_match()`** – Returns `1` for a match, `0` for no match, or `false` on error.
- **`preg_match_all()`** – Returns the number of matches (which can be `0`) or `false` on error.
- **`json_decode()`** – May return valid decoded `false`, 0 or `null` values.

## Best Practices

### Strict comparison

One solution to protect one's code against this problem is to always use a strict comparison, with the `===` or `!==` operators. )** when checking the return value of these functions to avoid confusion between `0` and `false`.

Example: ```

```

### Use safe functions

Another solution is to use dedicated functions, such as `str_contains()`, `str_start_with()`or `str_end_with()`, instead of `strpos()`.

There isn't always a straightforward replacement for the orginal function, such as for `json_decode()`, or `preg_match()`. In that case, you should create it yourself, with the added context.

Example: ```

```

### Use static analysis

Static analysis tools, like [Exakat](https://www.exakat.io/), are able to detect this error and focus attention on them before the code goes to production.

## Explicit comparison

The `strpos()` syndrom is not limited to that function: it comes also with `array_search()`, and others. It usually takes a few hours of head scratching to find the error and make the code work again.

This is a [PHP classic bug](https://php-dictionary.readthedocs.io/en/latest/thesaurus.html#classic-bug) that should be known to every developer that work with the platform.

 