Skip to content

Language: negative bit shift ArithmeticError bypasses try/catch (Zend/zend_operators.c) #21912

Closed

Description

@PurHur

Category

bug · php-src-strict · language / operators / exceptions

Problem

Zend throws a catchable ArithmeticError: Bit shift by negative number for << / >> with a negative shift count. php-compiler raises the same ArithmeticError from lib/VM/Variable.php but it escapes user try/catch and becomes an uncaught fatal (engine abort), so scripts cannot handle the error.

Repro Zend 8.2+ VM (2026-07-21)
try { 1 << -1; } catch (ArithmeticError $e) { echo "caught"; } prints caught PHP Fatal error: Uncaught ArithmeticError: Bit shift by negative number in Variable.php
same for 1 >> -1 caught uncaught fatal

php-src reference

  • php/php-src Zend/zend_operators.c — shift_left_function / shift_right_function negative-count zend_throw_exception / ArithmeticError
  • Exception dispatch must go through the VM user-exception path (same as division-by-zero / modulo-by-zero, which are catchable today)

PHP implementation target

  • lib/VM/Variable.php (_bitwiseOp / bitwiseOp) — throw via VM exception mechanism so try/catch works; do not throw a raw PHP exception that bypasses the interpreter frame
  • Mirror in JIT/AOT lowering for OpCode shift ops
  • No new C in runtime/

Repro

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
cat > /tmp/shl.php <<'"'"'PHP'"'"'
<?php
try {
  $x = 1 << -1;
  echo "result=$x\n";
} catch (ArithmeticError $e) {
  echo "caught ArithmeticError: ", $e->getMessage(), "\n";
}
echo "after\n";
PHP
php /tmp/shl.php
php bin/vm.php /tmp/shl.php
'

Done when

  • 1 << -1 and 1 >> -1 are catchable as ArithmeticError with Zend message (VM + JIT)
  • Script continues after catch (after prints)
  • Compliance .phpt under test/compliance/cases/language/
  • php-src-strict; no php-compiler-strict shortcut

Activity

  1. added
    bugSomething isn't working
    area:vmVirtual machine
    implementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claim
    on Jul 21, 2026
  2. PurHur commented on Jul 21, 2026

    @PurHur
    OwnerAuthor

    claim: Lane A implementer — starting this run

    Gate snapshot (pre-work):

  3. PurHur commented on Jul 21, 2026

    @PurHur
    OwnerAuthor

    Merged via #21917

    Verification

    • VM + JIT: 1 << -1 / 1 >> -1 catchable as ArithmeticError: Bit shift by negative number; script continues (after prints)
    • ./script/phpunit.sh --filter 'JitOperandHelpersRuntimeShrinkTest|negative_bit_shift' → OK 18/18
    • Existing shift compliance (shift_bool|shift_float|assignop_shift) → OK 15/15

    Gate snapshot (this run, before claim)

    • bootstrap-inventory --check: OK 6326/6326
    • release-readiness --json: user_release_ready=yes (inventory, spine-coverage, root-readme-sync, north-star5-fast, vm-driver-probe all ok)
  4. PurHur commented on Jul 22, 2026

    @PurHur
    OwnerAuthor

    cleanup: deleted stale remote branch agent/issue-21912-negative-bit-shift-catchable (work landed via squash merge in #21917; tip was not an ancestor of master but issue is closed and there is no open PR — leftover post-merge agent branch).

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 machinebugSomething isn't workingimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-2:languagePhase 2 – language features

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions