Bad Null Guard

ID

php.bad_null_guard

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Php

Tags

null-safety, reliability

Description

Reports an inverted null guard: a condition whose left operand tests a variable for null and whose right operand dereferences that same variable in the branch where it is known to be null. The dereference is reached precisely when the variable holds null, so the call fails at runtime.

Rationale

A correct guard short-circuits the dereference away from the null case: $x !== null && $x→m() calls the method only when $x is non-null. Flipping the test — $x == null && $x→m() — keeps the same code shape but inverts the meaning: the && reaches $x→m() only when $x == null is true, i.e. exactly when $x is null. The same trap appears as is_null($x) && $x→m(), !isset($x) && $x→m(), and the OR dual $x !== null || $x→m() (the || falls through to the dereference only when $x is null). All four dereference null whenever the branch runs.

<?php
function process($user)
{
    if ($user == null && $user->save()) {   // FLAW — $user->save() runs only when $user is null
        return;
    }

    if ($user !== null && $user->save()) {   // OK — dereference reached only when non-null
        return;
    }
}

Remediation

Invert the null test so the dereference is reached only when the variable is non-null: replace ==/=== with !== (and || with &&), or is_null($x) / !isset($x) with isset($x). If the test direction is correct, the dereference belongs in the other branch.