Skip to content

In 8.4 array internal pointer gets "lost" with certain sequence of assign/unset operations. Works in 8.2 and 8.3 #19280

Closed

Description

@mikethea1

Description

The following code:

<?php
$o = (object)['a' => []];
$key = key($o->a); $o->a[0] = (object)['id' => 0]; if ($key && !key($o->a)) { echo "Key became null after assigning 0\n"; }
$key = key($o->a); $o->a[1] = (object)['id' => 1]; if ($key && !key($o->a)) { echo "Key became null after assigning 1\n"; }
$key = key($o->a); $o->a[2] = (object)['id' => 2]; if ($key && !key($o->a)) { echo "Key became null after assigning 2\n"; }
$key = key($o->a); $o->a[3] = (object)['id' => 3]; if ($key && !key($o->a)) { echo "Key became null after assigning 3\n"; }
$key = key($o->a); $o->a[4] = (object)['id' => 4]; if ($key && !key($o->a)) { echo "Key became null after assigning 4\n"; }
$key = key($o->a); $o->a[5] = (object)['id' => 5]; if ($key && !key($o->a)) { echo "Key became null after assigning 5\n"; }
$key = key($o->a); $o->a[6] = (object)['id' => 6]; if ($key && !key($o->a)) { echo "Key became null after assigning 6\n"; }
$key = key($o->a); $o->a[7] = (object)['id' => 7]; if ($key && !key($o->a)) { echo "Key became null after assigning 7\n"; }
$key = key($o->a); $o->a[8] = (object)['id' => 8]; if ($key && !key($o->a)) { echo "Key became null after assigning 8\n"; }
$key = key($o->a); $o->a[9] = (object)['id' => 9]; if ($key && !key($o->a)) { echo "Key became null after assigning 9\n"; }
$c = current($o->a); next($o->a);
unset($o->a[0]);
$key = key($o->a); $o->a[10] = (object)['id' => 10]; if ($key && !key($o->a)) { echo "Key became null after assigning 10\n"; }
$c = current($o->a); next($o->a);
unset($o->a[7]);
$key = key($o->a); $o->a[11] = (object)['id' => 11]; if ($key && !key($o->a)) { echo "Key became null after assigning 11\n"; }
unset($o->a[2]);
$key = key($o->a); $o->a[12] = (object)['id' => 12]; if ($key && !key($o->a)) { echo "Key became null after assigning 12\n"; }
unset($o->a[3]);
$key = key($o->a); $o->a[13] = (object)['id' => 13]; if ($key && !key($o->a)) { echo "Key became null after assigning 13\n"; }
unset($o->a[8]);
$key = key($o->a); $o->a[14] = (object)['id' => 14]; if ($key && !key($o->a)) { echo "Key became null after assigning 14\n"; }
unset($o->a[6]);
$key = key($o->a); $o->a[15] = (object)['id' => 15]; if ($key && !key($o->a)) { echo "Key became null after assigning 15\n"; }
unset($o->a[1]);
$key = key($o->a); $o->a[16] = (object)['id' => 16]; if ($key && !key($o->a)) { echo "Key became null after assigning 16\n"; }
$c = current($o->a); next($o->a);
unset($o->a[9]);
$key = key($o->a); $o->a[17] = (object)['id' => 17]; if ($key && !key($o->a)) { echo "Key became null after assigning 17\n"; }
unset($o->a[5]);
$key = key($o->a); $o->a[18] = (object)['id' => 18]; if ($key && !key($o->a)) { echo "Key became null after assigning 18\n"; }
unset($o->a[4]);
$key = key($o->a); $o->a[19] = (object)['id' => 19]; if ($key && !key($o->a)) { echo "Key became null after assigning 19\n"; }
$c = current($o->a); next($o->a);
unset($o->a[10]);
$key = key($o->a); $o->a[20] = (object)['id' => 20]; if ($key && !key($o->a)) { echo "Key became null after assigning 20\n"; }
$c = current($o->a); next($o->a);
unset($o->a[12]);
$key = key($o->a); $o->a[21] = (object)['id' => 21]; if ($key && !key($o->a)) { echo "Key became null after assigning 21\n"; }
unset($o->a[11]);
$key = key($o->a); $o->a[22] = (object)['id' => 22]; if ($key && !key($o->a)) { echo "Key became null after assigning 22\n"; }
$c = current($o->a); next($o->a);
unset($o->a[15]);
$key = key($o->a); $o->a[23] = (object)['id' => 23]; if ($key && !key($o->a)) { echo "Key became null after assigning 23\n"; }
unset($o->a[18]);
$key = key($o->a); $o->a[24] = (object)['id' => 24]; if ($key && !key($o->a)) { echo "Key became null after assigning 24\n"; }
unset($o->a[13]);
$key = key($o->a); $o->a[25] = (object)['id' => 25]; if ($key && !key($o->a)) { echo "Key became null after assigning 25\n"; }
$c = current($o->a); next($o->a);
unset($o->a[14]);
$key = key($o->a); $o->a[26] = (object)['id' => 26]; if ($key && !key($o->a)) { echo "Key became null after assigning 26\n"; }
unset($o->a[17]);
$key = key($o->a); $o->a[27] = (object)['id' => 27]; if ($key && !key($o->a)) { echo "Key became null after assigning 27\n"; }
$c = current($o->a); next($o->a);
unset($o->a[19]);
$key = key($o->a); $o->a[28] = (object)['id' => 28]; if ($key && !key($o->a)) { echo "Key became null after assigning 28\n"; }
unset($o->a[20]);
$key = key($o->a); $o->a[29] = (object)['id' => 29]; if ($key && !key($o->a)) { echo "Key became null after assigning 29\n"; }
unset($o->a[24]);
$key = key($o->a); $o->a[30] = (object)['id' => 30]; if ($key && !key($o->a)) { echo "Key became null after assigning 30\n"; }
unset($o->a[16]);
$key = key($o->a); $o->a[31] = (object)['id' => 31]; if ($key && !key($o->a)) { echo "Key became null after assigning 31\n"; }
$c = current($o->a); next($o->a);
unset($o->a[26]);
$key = key($o->a); $o->a[32] = (object)['id' => 32]; if ($key && !key($o->a)) { echo "Key became null after assigning 32\n"; }
unset($o->a[27]);
$key = key($o->a); $o->a[33] = (object)['id' => 33]; if ($key && !key($o->a)) { echo "Key became null after assigning 33\n"; }
unset($o->a[22]);
$key = key($o->a); $o->a[34] = (object)['id' => 34]; if ($key && !key($o->a)) { echo "Key became null after assigning 34\n"; }
unset($o->a[23]);
$key = key($o->a); $o->a[35] = (object)['id' => 35]; if ($key && !key($o->a)) { echo "Key became null after assigning 35\n"; }
unset($o->a[21]);
$key = key($o->a); $o->a[36] = (object)['id' => 36]; if ($key && !key($o->a)) { echo "Key became null after assigning 36\n"; }
unset($o->a[25]);
$key = key($o->a); $o->a[37] = (object)['id' => 37]; if ($key && !key($o->a)) { echo "Key became null after assigning 37\n"; }
$c = current($o->a); next($o->a);
unset($o->a[28]);
$key = key($o->a); $o->a[38] = (object)['id' => 38]; if ($key && !key($o->a)) { echo "Key became null after assigning 38\n"; }
$c = current($o->a); next($o->a);
unset($o->a[30]);
$key = key($o->a); $o->a[39] = (object)['id' => 39]; if ($key && !key($o->a)) { echo "Key became null after assigning 39\n"; }
unset($o->a[29]);
$key = key($o->a); $o->a[40] = (object)['id' => 40]; if ($key && !key($o->a)) { echo "Key became null after assigning 40\n"; }
$c = current($o->a); next($o->a);
unset($o->a[33]);
$key = key($o->a); $o->a[41] = (object)['id' => 41]; if ($key && !key($o->a)) { echo "Key became null after assigning 41\n"; }
unset($o->a[31]);
$key = key($o->a); $o->a[42] = (object)['id' => 42]; if ($key && !key($o->a)) { echo "Key became null after assigning 42\n"; }
unset($o->a[34]);
$key = key($o->a); $o->a[43] = (object)['id' => 43]; if ($key && !key($o->a)) { echo "Key became null after assigning 43\n"; }
$c = current($o->a); next($o->a);
unset($o->a[37]);
$key = key($o->a); $o->a[44] = (object)['id' => 44]; if ($key && !key($o->a)) { echo "Key became null after assigning 44\n"; }
unset($o->a[32]);
$key = key($o->a); $o->a[45] = (object)['id' => 45]; if ($key && !key($o->a)) { echo "Key became null after assigning 45\n"; }
unset($o->a[36]);
$key = key($o->a); $o->a[46] = (object)['id' => 46]; if ($key && !key($o->a)) { echo "Key became null after assigning 46\n"; }
$c = current($o->a); next($o->a);
unset($o->a[35]);
$key = key($o->a); $o->a[47] = (object)['id' => 47]; if ($key && !key($o->a)) { echo "Key became null after assigning 47\n"; }
unset($o->a[38]);
$key = key($o->a); $o->a[48] = (object)['id' => 48]; if ($key && !key($o->a)) { echo "Key became null after assigning 48\n"; }
$c = current($o->a); next($o->a);
unset($o->a[39]);
$key = key($o->a); $o->a[49] = (object)['id' => 49]; if ($key && !key($o->a)) { echo "Key became null after assigning 49\n"; }
$c = current($o->a); next($o->a);
unset($o->a[41]);
$key = key($o->a); $o->a[50] = (object)['id' => 50]; if ($key && !key($o->a)) { echo "Key became null after assigning 50\n"; }
unset($o->a[40]);
$key = key($o->a); $o->a[51] = (object)['id' => 51]; if ($key && !key($o->a)) { echo "Key became null after assigning 51\n"; }
unset($o->a[43]);
$key = key($o->a); $o->a[52] = (object)['id' => 52]; if ($key && !key($o->a)) { echo "Key became null after assigning 52\n"; }
$c = current($o->a); next($o->a);
unset($o->a[42]);
$key = key($o->a); $o->a[53] = (object)['id' => 53]; if ($key && !key($o->a)) { echo "Key became null after assigning 53\n"; }
$c = current($o->a); next($o->a);
unset($o->a[44]);
$key = key($o->a); $o->a[54] = (object)['id' => 54]; if ($key && !key($o->a)) { echo "Key became null after assigning 54\n"; }
$c = current($o->a); next($o->a);
unset($o->a[46]);
$key = key($o->a); $o->a[55] = (object)['id' => 55]; if ($key && !key($o->a)) { echo "Key became null after assigning 55\n"; }
unset($o->a[45]);
$key = key($o->a); $o->a[56] = (object)['id' => 56]; if ($key && !key($o->a)) { echo "Key became null after assigning 56\n"; }
unset($o->a[48]);
$key = key($o->a); $o->a[57] = (object)['id' => 57]; if ($key && !key($o->a)) { echo "Key became null after assigning 57\n"; }
$c = current($o->a); next($o->a);
unset($o->a[47]);
$key = key($o->a); $o->a[58] = (object)['id' => 58]; if ($key && !key($o->a)) { echo "Key became null after assigning 58\n"; }
$c = current($o->a); next($o->a);
unset($o->a[49]);
$key = key($o->a); $o->a[59] = (object)['id' => 59]; if ($key && !key($o->a)) { echo "Key became null after assigning 59\n"; }
$c = current($o->a); next($o->a);
unset($o->a[54]);
$key = key($o->a); $o->a[60] = (object)['id' => 60]; if ($key && !key($o->a)) { echo "Key became null after assigning 60\n"; }
unset($o->a[51]);
$key = key($o->a); $o->a[61] = (object)['id' => 61]; if ($key && !key($o->a)) { echo "Key became null after assigning 61\n"; }
unset($o->a[50]);
$key = key($o->a); $o->a[62] = (object)['id' => 62]; if ($key && !key($o->a)) { echo "Key became null after assigning 62\n"; }
$c = current($o->a); next($o->a);
unset($o->a[53]);
$key = key($o->a); $o->a[63] = (object)['id' => 63]; if ($key && !key($o->a)) { echo "Key became null after assigning 63\n"; }
unset($o->a[52]);
$key = key($o->a); $o->a[64] = (object)['id' => 64]; if ($key && !key($o->a)) { echo "Key became null after assigning 64\n"; }
$c = current($o->a); next($o->a);
unset($o->a[57]);
$key = key($o->a); $o->a[65] = (object)['id' => 65]; if ($key && !key($o->a)) { echo "Key became null after assigning 65\n"; }
unset($o->a[59]);
$key = key($o->a); $o->a[66] = (object)['id' => 66]; if ($key && !key($o->a)) { echo "Key became null after assigning 66\n"; }
unset($o->a[56]);
$key = key($o->a); $o->a[67] = (object)['id' => 67]; if ($key && !key($o->a)) { echo "Key became null after assigning 67\n"; }
unset($o->a[55]);
$key = key($o->a); $o->a[68] = (object)['id' => 68]; if ($key && !key($o->a)) { echo "Key became null after assigning 68\n"; }
unset($o->a[58]);
$key = key($o->a); $o->a[69] = (object)['id' => 69]; if ($key && !key($o->a)) { echo "Key became null after assigning 69\n"; }
$c = current($o->a); next($o->a);
unset($o->a[61]);
$key = key($o->a); $o->a[70] = (object)['id' => 70]; if ($key && !key($o->a)) { echo "Key became null after assigning 70\n"; }
unset($o->a[63]);
$key = key($o->a); $o->a[71] = (object)['id' => 71]; if ($key && !key($o->a)) { echo "Key became null after assigning 71\n"; }
unset($o->a[60]);
$key = key($o->a); $o->a[72] = (object)['id' => 72]; if ($key && !key($o->a)) { echo "Key became null after assigning 72\n"; }
$c = current($o->a); next($o->a);
unset($o->a[66]);
$key = key($o->a); $o->a[73] = (object)['id' => 73]; if ($key && !key($o->a)) { echo "Key became null after assigning 73\n"; }
unset($o->a[67]);
$key = key($o->a); $o->a[74] = (object)['id' => 74]; if ($key && !key($o->a)) { echo "Key became null after assigning 74\n"; }
unset($o->a[69]);
$key = key($o->a); $o->a[75] = (object)['id' => 75]; if ($key && !key($o->a)) { echo "Key became null after assigning 75\n"; }
unset($o->a[65]);
$key = key($o->a); $o->a[76] = (object)['id' => 76]; if ($key && !key($o->a)) { echo "Key became null after assigning 76\n"; }
unset($o->a[72]);
$key = key($o->a); $o->a[77] = (object)['id' => 77]; if ($key && !key($o->a)) { echo "Key became null after assigning 77\n"; }
unset($o->a[68]);
$key = key($o->a); $o->a[78] = (object)['id' => 78]; if ($key && !key($o->a)) { echo "Key became null after assigning 78\n"; }
unset($o->a[71]);
$key = key($o->a); $o->a[79] = (object)['id' => 79]; if ($key && !key($o->a)) { echo "Key became null after assigning 79\n"; }
unset($o->a[73]);
$key = key($o->a); $o->a[80] = (object)['id' => 80]; if ($key && !key($o->a)) { echo "Key became null after assigning 80\n"; }
unset($o->a[62]);
$key = key($o->a); $o->a[81] = (object)['id' => 81]; if ($key && !key($o->a)) { echo "Key became null after assigning 81\n"; }
unset($o->a[64]);
$key = key($o->a); $o->a[82] = (object)['id' => 82]; if ($key && !key($o->a)) { echo "Key became null after assigning 82\n"; }
$c = current($o->a); next($o->a);
unset($o->a[70]);
$key = key($o->a); $o->a[83] = (object)['id' => 83]; if ($key && !key($o->a)) { echo "Key became null after assigning 83\n"; }
$c = current($o->a); next($o->a);
unset($o->a[78]);
$key = key($o->a); $o->a[84] = (object)['id' => 84]; if ($key && !key($o->a)) { echo "Key became null after assigning 84\n"; }
unset($o->a[75]);
$key = key($o->a); $o->a[85] = (object)['id' => 85]; if ($key && !key($o->a)) { echo "Key became null after assigning 85\n"; }
unset($o->a[74]);
$key = key($o->a); $o->a[86] = (object)['id' => 86]; if ($key && !key($o->a)) { echo "Key became null after assigning 86\n"; }
$c = current($o->a); next($o->a);
unset($o->a[76]);
$key = key($o->a); $o->a[87] = (object)['id' => 87]; if ($key && !key($o->a)) { echo "Key became null after assigning 87\n"; }
$c = current($o->a); next($o->a);
unset($o->a[79]);
$key = key($o->a); $o->a[88] = (object)['id' => 88]; if ($key && !key($o->a)) { echo "Key became null after assigning 88\n"; }
unset($o->a[82]);
$key = key($o->a); $o->a[89] = (object)['id' => 89]; if ($key && !key($o->a)) { echo "Key became null after assigning 89\n"; }
unset($o->a[81]);
$key = key($o->a); $o->a[90] = (object)['id' => 90]; if ($key && !key($o->a)) { echo "Key became null after assigning 90\n"; }
unset($o->a[77]);
$key = key($o->a); $o->a[91] = (object)['id' => 91]; if ($key && !key($o->a)) { echo "Key became null after assigning 91\n"; }
$c = current($o->a); next($o->a);
unset($o->a[80]);
$key = key($o->a); $o->a[92] = (object)['id' => 92]; if ($key && !key($o->a)) { echo "Key became null after assigning 92\n"; }
$c = current($o->a); next($o->a);
unset($o->a[85]);
$key = key($o->a); $o->a[93] = (object)['id' => 93]; if ($key && !key($o->a)) { echo "Key became null after assigning 93\n"; }
unset($o->a[83]);
$key = key($o->a); $o->a[94] = (object)['id' => 94]; if ($key && !key($o->a)) { echo "Key became null after assigning 94\n"; }
$c = current($o->a); next($o->a);
unset($o->a[84]);
$key = key($o->a); $o->a[95] = (object)['id' => 95]; if ($key && !key($o->a)) { echo "Key became null after assigning 95\n"; }
$c = current($o->a); next($o->a);
unset($o->a[87]);
$key = key($o->a); $o->a[96] = (object)['id' => 96]; if ($key && !key($o->a)) { echo "Key became null after assigning 96\n"; }
unset($o->a[86]);
$key = key($o->a); $o->a[97] = (object)['id' => 97]; if ($key && !key($o->a)) { echo "Key became null after assigning 97\n"; }
$c = current($o->a); next($o->a);
unset($o->a[88]);
$key = key($o->a); $o->a[98] = (object)['id' => 98]; if ($key && !key($o->a)) { echo "Key became null after assigning 98\n"; }
$c = current($o->a); next($o->a);
unset($o->a[89]);
$key = key($o->a); $o->a[99] = (object)['id' => 99]; if ($key && !key($o->a)) { echo "Key became null after assigning 99\n"; }
$c = current($o->a); next($o->a);
unset($o->a[90]);
$key = key($o->a); $o->a[100] = (object)['id' => 100]; if ($key && !key($o->a)) { echo "Key became null after assigning 100\n"; }
$c = current($o->a); next($o->a);
unset($o->a[91]);
$key = key($o->a); $o->a[101] = (object)['id' => 101]; if ($key && !key($o->a)) { echo "Key became null after assigning 101\n"; }
$c = current($o->a); next($o->a);
unset($o->a[92]);
$key = key($o->a); $o->a[102] = (object)['id' => 102]; if ($key && !key($o->a)) { echo "Key became null after assigning 102\n"; }
$c = current($o->a); next($o->a);
unset($o->a[94]);
$key = key($o->a); $o->a[103] = (object)['id' => 103]; if ($key && !key($o->a)) { echo "Key became null after assigning 103\n"; }
unset($o->a[95]);
$key = key($o->a); $o->a[104] = (object)['id' => 104]; if ($key && !key($o->a)) { echo "Key became null after assigning 104\n"; }
unset($o->a[93]);
$key = key($o->a); $o->a[105] = (object)['id' => 105]; if ($key && !key($o->a)) { echo "Key became null after assigning 105\n"; }
$c = current($o->a); next($o->a);
unset($o->a[98]);
$key = key($o->a); $o->a[106] = (object)['id' => 106]; if ($key && !key($o->a)) { echo "Key became null after assigning 106\n"; }
unset($o->a[96]);
$key = key($o->a); $o->a[107] = (object)['id' => 107]; if ($key && !key($o->a)) { echo "Key became null after assigning 107\n"; }
$c = current($o->a); next($o->a);
unset($o->a[100]);
$key = key($o->a); $o->a[108] = (object)['id' => 108]; if ($key && !key($o->a)) { echo "Key became null after assigning 108\n"; }
unset($o->a[99]);
$key = key($o->a); $o->a[109] = (object)['id' => 109]; if ($key && !key($o->a)) { echo "Key became null after assigning 109\n"; }
unset($o->a[101]);
$key = key($o->a); $o->a[110] = (object)['id' => 110]; if ($key && !key($o->a)) { echo "Key became null after assigning 110\n"; }
unset($o->a[97]);
$key = key($o->a); $o->a[111] = (object)['id' => 111]; if ($key && !key($o->a)) { echo "Key became null after assigning 111\n"; }
unset($o->a[102]);
$key = key($o->a); $o->a[112] = (object)['id' => 112]; if ($key && !key($o->a)) { echo "Key became null after assigning 112\n"; }
unset($o->a[103]);
$key = key($o->a); $o->a[113] = (object)['id' => 113]; if ($key && !key($o->a)) { echo "Key became null after assigning 113\n"; }
$c = current($o->a); next($o->a);
unset($o->a[104]);
$key = key($o->a); $o->a[114] = (object)['id' => 114]; if ($key && !key($o->a)) { echo "Key became null after assigning 114\n"; }
$c = current($o->a); next($o->a);
unset($o->a[105]);
$key = key($o->a); $o->a[115] = (object)['id' => 115]; if ($key && !key($o->a)) { echo "Key became null after assigning 115\n"; }
$c = current($o->a); next($o->a);
unset($o->a[107]);
$key = key($o->a); $o->a[116] = (object)['id' => 116]; if ($key && !key($o->a)) { echo "Key became null after assigning 116\n"; }
unset($o->a[106]);
$key = key($o->a); $o->a[117] = (object)['id' => 117]; if ($key && !key($o->a)) { echo "Key became null after assigning 117\n"; }
$c = current($o->a); next($o->a);
unset($o->a[108]);
$key = key($o->a); $o->a[118] = (object)['id' => 118]; if ($key && !key($o->a)) { echo "Key became null after assigning 118\n"; }
$c = current($o->a); next($o->a);
unset($o->a[109]);
$key = key($o->a); $o->a[119] = (object)['id' => 119]; if ($key && !key($o->a)) { echo "Key became null after assigning 119\n"; }
$c = current($o->a); next($o->a);
unset($o->a[110]);
$key = key($o->a); $o->a[120] = (object)['id' => 120]; if ($key && !key($o->a)) { echo "Key became null after assigning 120\n"; }
$c = current($o->a); next($o->a);
unset($o->a[113]);
$key = key($o->a); $o->a[121] = (object)['id' => 121]; if ($key && !key($o->a)) { echo "Key became null after assigning 121\n"; }
unset($o->a[111]);
$key = key($o->a); $o->a[122] = (object)['id' => 122]; if ($key && !key($o->a)) { echo "Key became null after assigning 122\n"; }
$c = current($o->a); next($o->a);
unset($o->a[112]);
$key = key($o->a); $o->a[123] = (object)['id' => 123]; if ($key && !key($o->a)) { echo "Key became null after assigning 123\n"; }
$c = current($o->a); next($o->a);
unset($o->a[115]);
$key = key($o->a); $o->a[124] = (object)['id' => 124]; if ($key && !key($o->a)) { echo "Key became null after assigning 124\n"; }
unset($o->a[114]);
$key = key($o->a); $o->a[125] = (object)['id' => 125]; if ($key && !key($o->a)) { echo "Key became null after assigning 125\n"; }
unset($o->a[116]);
$key = key($o->a); $o->a[126] = (object)['id' => 126]; if ($key && !key($o->a)) { echo "Key became null after assigning 126\n"; }
unset($o->a[117]);
$key = key($o->a); $o->a[127] = (object)['id' => 127]; if ($key && !key($o->a)) { echo "Key became null after assigning 127\n"; }
$c = current($o->a); next($o->a);
unset($o->a[118]);
$key = key($o->a); $o->a[128] = (object)['id' => 128]; if ($key && !key($o->a)) { echo "Key became null after assigning 128\n"; }
$c = current($o->a); next($o->a);
unset($o->a[119]);
$key = key($o->a); $o->a[129] = (object)['id' => 129]; if ($key && !key($o->a)) { echo "Key became null after assigning 129\n"; }
$c = current($o->a); next($o->a);
unset($o->a[121]);
$key = key($o->a); $o->a[130] = (object)['id' => 130]; if ($key && !key($o->a)) { echo "Key became null after assigning 130\n"; }
unset($o->a[122]);
$key = key($o->a); $o->a[131] = (object)['id' => 131]; if ($key && !key($o->a)) { echo "Key became null after assigning 131\n"; }
unset($o->a[123]);
$key = key($o->a); $o->a[132] = (object)['id' => 132]; if ($key && !key($o->a)) { echo "Key became null after assigning 132\n"; }
unset($o->a[124]);
$key = key($o->a); $o->a[133] = (object)['id' => 133]; if ($key && !key($o->a)) { echo "Key became null after assigning 133\n"; }
unset($o->a[120]);
$key = key($o->a); $o->a[134] = (object)['id' => 134]; if ($key && !key($o->a)) { echo "Key became null after assigning 134\n"; }
unset($o->a[127]);
$key = key($o->a); $o->a[135] = (object)['id' => 135]; if ($key && !key($o->a)) { echo "Key became null after assigning 135\n"; }
$c = current($o->a); next($o->a);
unset($o->a[125]);
$key = key($o->a); $o->a[136] = (object)['id' => 136]; if ($key && !key($o->a)) { echo "Key became null after assigning 136\n"; }
$c = current($o->a); next($o->a);
unset($o->a[130]);
$key = key($o->a); $o->a[137] = (object)['id' => 137]; if ($key && !key($o->a)) { echo "Key became null after assigning 137\n"; }
unset($o->a[128]);
$key = key($o->a); $o->a[138] = (object)['id' => 138]; if ($key && !key($o->a)) { echo "Key became null after assigning 138\n"; }
unset($o->a[131]);
$key = key($o->a); $o->a[139] = (object)['id' => 139]; if ($key && !key($o->a)) { echo "Key became null after assigning 139\n"; }
unset($o->a[132]);
$key = key($o->a); $o->a[140] = (object)['id' => 140]; if ($key && !key($o->a)) { echo "Key became null after assigning 140\n"; }
unset($o->a[129]);
$key = key($o->a); $o->a[141] = (object)['id' => 141]; if ($key && !key($o->a)) { echo "Key became null after assigning 141\n"; }
unset($o->a[135]);
$key = key($o->a); $o->a[142] = (object)['id' => 142]; if ($key && !key($o->a)) { echo "Key became null after assigning 142\n"; }
unset($o->a[134]);
$key = key($o->a); $o->a[143] = (object)['id' => 143]; if ($key && !key($o->a)) { echo "Key became null after assigning 143\n"; }
unset($o->a[133]);
$key = key($o->a); $o->a[144] = (object)['id' => 144]; if ($key && !key($o->a)) { echo "Key became null after assigning 144\n"; }
unset($o->a[136]);
$key = key($o->a); $o->a[145] = (object)['id' => 145]; if ($key && !key($o->a)) { echo "Key became null after assigning 145\n"; }
unset($o->a[138]);
$key = key($o->a); $o->a[146] = (object)['id' => 146]; if ($key && !key($o->a)) { echo "Key became null after assigning 146\n"; }
unset($o->a[137]);
$key = key($o->a); $o->a[147] = (object)['id' => 147]; if ($key && !key($o->a)) { echo "Key became null after assigning 147\n"; }
unset($o->a[126]);
$key = key($o->a); $o->a[148] = (object)['id' => 148]; if ($key && !key($o->a)) { echo "Key became null after assigning 148\n"; }
unset($o->a[140]);
$key = key($o->a); $o->a[149] = (object)['id' => 149]; if ($key && !key($o->a)) { echo "Key became null after assigning 149\n"; }
$key = key($o->a); $o->a[0] = (object)['id' => 0]; if ($key && !key($o->a)) { echo "Key became null after assigning 0\n"; }
unset($o->a[0]);
$key = key($o->a); $o->a[0] = (object)['id' => 0]; if ($key && !key($o->a)) { echo "Key became null after assigning 0\n"; }
unset($o->a[0]);
echo 'DONE';

Resulted in this output:

Key became null after assigning 142
DONE

But I expected this output instead:

DONE

Note that 8.2.29 and 8.3.23 give the expected output, but 8.4.x gives the new output.

I'm not a PHP expert so apologies if there is something I'm missing, but I wouldn't have thought that assigning a value to an array slot should have this impact.

PHP Version

8.4.10

Operating System

Windows 11 and also PHP sandbox (https://onlinephp.io/)

Activity

  1. ndossche commented on Jul 28, 2025

    @ndossche
    Member

    Bisected to d653646

  2. ndossche commented on Jul 28, 2025

    @ndossche
    Member

    Restoring this loop would work: d653646#diff-b7e8bf4a312e668b8e9e5ef32e20919c951647cafaa2abeedc47d3742d289b49L1461-L1477
    What's missing right now is the handling of buckets being removed "to the left (inclusive)" of the iterator position (in that case we have to shift forwards), ditto for packed arrays likely. I don't immediately understand why this loop was removed. cc @iluuu1994

  3. self-assigned this
    on Jul 28, 2025
  4. iluuu1994 commented on Jul 28, 2025

    @iluuu1994
    Member

    This can be triggered through various paths. Restoring these lines fixes 2/3. It happens because the rehashing paths don't account for nInternalPointer pointing to IS_UNDEF elements (and for one it seems not to fix `nInternalPointer at all). I suspect it might be better for performance to check this during rehashing, since it should happen less frequently than removing elements. But I'll have a closer look tomorrow.

    Details

    <?php
    
    function rehash_packed() {
        $a = range(0, 63);
        for ($i = 0; $i <= 47; $i++) {
            next($a);
        }
        for ($i = 16; $i < 63; $i++) {
            unset($a[$i]);
        }
        var_dump(key($a));
        $a[64] = 64;
        var_dump(key($a));
    }
    
    function rehash_string() {
        $a = [];
        for ($i = 0; $i < 64; $i++) {
            $a[md5($i)] = $i;
        }
        for ($i = 0; $i <= 47; $i++) {
            next($a);
        }
        for ($i = 16; $i < 63; $i++) {
            unset($a[md5($i)]);
        }
        var_dump(key($a));
        $a[md5(64)] = 64;
        var_dump(key($a));
    }
    
    function rehash_int() {
        $a = [];
        for ($i = 63; $i >= 0; $i--) {
            $a[$i] = $i;
        }
        for ($i = 0; $i <= 47; $i++) {
            next($a);
        }
        for ($i = 48; $i >= 1; $i--) {
            unset($a[$i]);
        }
        var_dump(key($a));
        $a[64] = 64;
        var_dump(key($a));
    }
    
    rehash_packed();
    rehash_string();
    rehash_int();

  5. mikethea1 commented on Jul 29, 2025

    @mikethea1
    Author

    Not helpful for debugging/fixing, but for anyone curious as to the impact of this, EachPromise.php in Guzzle has a pending array whose access pattern can and does trigger the bug.

  6. mikethea1 commented on Aug 1, 2025

    @mikethea1
    Author

    Thanks @iluuu1994 ! Any sense of when this will be available in a patch?

  7. iluuu1994 commented on Aug 1, 2025

    @iluuu1994
    Member

    @mikethea1 It should land in PHP 8.4.12 in approx. 4 weeks.

  8. mikethea1 commented on Aug 1, 2025

    @mikethea1
    Author

    Great. Really appreciate the rapid engagement and resolution @iluuu1994 and @nielsdos

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions