1--TEST-- 2Bug #81249: Intermittent property assignment failure with JIT enabled 3--EXTENSIONS-- 4opcache 5--INI-- 6opcache.enable=1 7opcache.enable_cli=1 8opcache.jit_buffer_size=1M 9opcache.jit=tracing 10--SKIPIF-- 11<?php if (PHP_INT_SIZE != 8) die("skip: 64-bit only"); ?> 12--FILE-- 13<?php 14 15declare(strict_types=1); 16 17final class EucJpDecoder 18{ 19 private const JIS0212_INDEX = [108 => 728]; 20 private const JIS0208_INDEX = []; 21 22 private const CONTINUE = -1; 23 private const FINISHED = -2; 24 private const ERROR = -3; 25 26 /** 27 * @var int 28 */ 29 private $lead; 30 31 /** 32 * @var bool 33 */ 34 private $isJis0212; 35 36 public function __construct() 37 { 38 $this->lead = 0x00; 39 $this->isJis0212 = false; 40 } 41 42 public function handle(array &$ioQueue, string $byte): int 43 { 44 if ($byte === '') { 45 if ($this->lead !== 0x00) { 46 $this->lead = 0x00; 47 48 return self::ERROR; 49 } 50 51 return self::FINISHED; 52 } 53 54 $byte = ord($byte); 55 56 if ($this->lead === 0x8E && ($byte >= 0xA1 && $byte <= 0xDF)) { 57 $this->lead = 0x00; 58 59 return 0xFF61 - 0xA1 + $byte; 60 } 61 62 if ($this->lead === 0x8F && ($byte >= 0xA1 && $byte <= 0xFE)) { 63 $this->isJis0212 = true; 64 $this->lead = $byte; 65 66 return self::CONTINUE; 67 } 68 69 if ($this->lead !== 0x00) { 70 $lead = $this->lead; 71 $this->lead = 0x00; 72 $codePoint = null; 73 74 if (($lead >= 0xA1 && $lead <= 0xFE) && ($byte >= 0xA1 && $byte <= 0xFE)) { 75 $index = self::JIS0208_INDEX; 76 77 if ($this->isJis0212) { 78 $index = self::JIS0212_INDEX; 79 } 80 81 $codePoint = $index[($lead - 0xA1) * 94 + $byte - 0xA1] ?? null; 82 } 83 84 $this->isJis0212 = false; 85 86 if ($codePoint !== null) { 87 return $codePoint; 88 } 89 90 if ($byte <= 0x7F) { 91 array_unshift($ioQueue, chr($byte)); 92 } 93 94 return self::ERROR; 95 } 96 97 if ($byte <= 0x7F) { 98 return $byte; 99 } 100 101 if ($byte === 0x8E || $byte === 0x8F || ($byte >= 0xA1 && $byte <= 0xFE)) { 102 $this->lead = $byte; 103 104 return self::CONTINUE; 105 } 106 107 return self::ERROR; 108 } 109} 110 111for ($i = 0; $i < 2000; ++$i) { 112 $decoder = new EucJpDecoder(); 113 114 $bytes = ["\x8F", "\xA2", "\xAF", '']; 115 $out = null; 116 117 foreach ($bytes as $byte) { 118 $result = $decoder->handle($bytes, $byte); 119 120 if ($result >= 0) { 121 $out = $result; 122 } 123 } 124 125 // $bytes array should be decoded to U+2D8, decimal 728 126 assert($out === 728); 127} 128?> 129OK 130--EXPECT-- 131OK 132