Skip to content

Commit 14b770d

Browse files
committed
Fix literal compaction collision between string and double
For the sake of simplicity I'm using a separate hashtable, rather than trying to do hash perturabation on the double strings.
1 parent cc3af6f commit 14b770d

File tree

2 files changed

+8
-3
lines changed

2 files changed

+8
-3
lines changed

ext/opcache/Optimizer/compact_literals.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
125125
int l_false = -1;
126126
int l_true = -1;
127127
int l_empty_arr = -1;
128-
HashTable hash;
128+
HashTable hash, double_hash;
129129
zend_string *key = NULL;
130130
void *checkpoint = zend_arena_checkpoint(ctx->arena);
131131
int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot;
@@ -329,6 +329,8 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
329329
/* Merge equal constants */
330330
j = 0;
331331
zend_hash_init(&hash, op_array->last_literal, NULL, NULL, 0);
332+
/* Use separate hashtable for doubles stored as string keys, to avoid collisions. */
333+
zend_hash_init(&double_hash, 0, NULL, NULL, 0);
332334
map = (int*)zend_arena_alloc(&ctx->arena, op_array->last_literal * sizeof(int));
333335
memset(map, 0, op_array->last_literal * sizeof(int));
334336
for (i = 0; i < op_array->last_literal; i++) {
@@ -411,12 +413,12 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
411413
}
412414
break;
413415
case IS_DOUBLE:
414-
if ((pos = zend_hash_str_find(&hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double))) != NULL) {
416+
if ((pos = zend_hash_str_find(&double_hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double))) != NULL) {
415417
map[i] = Z_LVAL_P(pos);
416418
} else {
417419
map[i] = j;
418420
ZVAL_LONG(&zv, j);
419-
zend_hash_str_add(&hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double), &zv);
421+
zend_hash_str_add(&double_hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double), &zv);
420422
if (i != j) {
421423
op_array->literals[j] = op_array->literals[i];
422424
info[j] = info[i];
@@ -494,7 +496,10 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
494496
break;
495497
}
496498
}
499+
500+
/* Only clean "hash", as it will be reused in the loop below. */
497501
zend_hash_clean(&hash);
502+
zend_hash_destroy(&double_hash);
498503
op_array->last_literal = j;
499504

500505
const_slot = zend_arena_alloc(&ctx->arena, j * 6 * sizeof(int));
252 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)