Skip to content

Regression: filter_var() inline options array — filter operand not int (ext/filter/filter.c) #12007

Closed

Description

@PurHur

Category

stdlib · php-src-strict

Problem

filter_var() with three arguments where the third is an inline array literal mis-binds call operands on the VM: argument #2 ($filter) is not an integer at runtime, so the builtin throws LogicException: filter must be an integer instead of validating.

Two-argument calls with FILTER_* constants work; assigning the options array to a variable first also works. The bug is specific to compiled call sites that pass a literal ['options' => …] or ['flags' => …] as the third parameter.

Examples that fail on VM but succeed on Zend:

  • filter_var('abc', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^a/']]) → should return 'abc'
  • filter_var('x', FILTER_VALIDATE_INT, ['flags' => FILTER_NULL_ON_FAILURE]) → should return null

Distinct from #9588 (named filter: rejected) and #4403 (full filter matrix); this is VM call-frame / operand lowering for inline array actuals.

php-src reference

PHP implementation today

  • ext/filter/filter_var.php — reads $frame->calledArgs[1] as filter id
  • Likely compiler/VM builtin dispatch bug when optional third arg is compile-time array literal

Repro

test/repro/maintainer_gap_filter_validate_regexp_options.php
test/repro/maintainer_gap_filter_var_int_null_on_failure.php

./script/docker-exec.sh -- php bin/vm.php test/repro/maintainer_gap_filter_validate_regexp_options.php
./script/docker-exec.sh -- php test/repro/maintainer_gap_filter_validate_regexp_options.php
Runtime Output
Zend ok
VM LogicException: filter_var() filter must be an integer…

Implementation hints (PHP-in-PHP)

  • Fix VM builtin argument lowering / calledArgs indexing for optional array parameters
  • Keep ext/filter/VmFilter.php semantics; no new C runtime
  • Add compliance guard; JIT/AOT if same mis-bind appears there

Done when

  • Both repro scripts print ok on VM
  • filter_var() with inline options works for REGEXP + FILTER_NULL_ON_FAILURE flags
  • No regression on 2-arg filter_var() paths

Refs #1492, #4403, #9588, #9032.

Activity

  1. added
    enhancementNew feature or request
    phase-4:stdlibPhase 4 – stdlib for web apps
    area:vmVirtual machine
    implementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claim
    on Jun 26, 2026
  2. PurHur commented on Jun 26, 2026

    @PurHur
    OwnerAuthor

    claim: PHP Compiler STD Lib — batch (issues #12007, #12008, #12009)

  3. PurHur commented on Jun 26, 2026

    @PurHur
    OwnerAuthor

    Merged via #12014.

    Root cause: matchInlineCallArgProducer mapped producers by index when ConstFetch + nested Array_ chain matched arg count; inner array was sent as $filter.

    Fix: splitLeadingConstFetchWithNestedArrayLiteralChain() maps leading constant to filter arg and outer array to options.

    Verification (VM):

    • test/repro/maintainer_gap_filter_validate_regexp_options.php → ok
    • test/repro/maintainer_gap_filter_var_int_null_on_failure.php → ok
    • test/compliance/cases/stdlib/filter_validate_regexp.phpt → pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:vmVirtual machineenhancementNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-4:stdlibPhase 4 – stdlib for web appsstdlib

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions