bug81249.phpt 2.7 KB

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