Skip to content

Commit 8685a7f

Browse files
authored
Remove custom alloca() (#8513)
* Use arena in DCE instead of multiple alloca() This requires passing the optimizer context * Use our do_alloca() instead of alloca() * Use emalloc in DEBUG builds instead of stack allocations for do_alloca() This helps detecting that we correctly free do_alloca()
1 parent 3445557 commit 8685a7f

File tree

8 files changed

+80
-536
lines changed

8 files changed

+80
-536
lines changed

Zend/Optimizer/dce.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ static inline bool may_throw_dce_exception(const zend_op *opline) {
523523
return opline->opcode == ZEND_ADD_ARRAY_ELEMENT && opline->op2_type == IS_UNUSED;
524524
}
525525

526-
int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, bool reorder_dtor_effects) {
526+
int dce_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *optimizer_ctx, zend_ssa *ssa, bool reorder_dtor_effects) {
527527
int i;
528528
zend_ssa_phi *phi;
529529
int removed_ops = 0;
@@ -536,20 +536,17 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, bool reorder_d
536536
ctx.op_array = op_array;
537537
ctx.reorder_dtor_effects = reorder_dtor_effects;
538538

539+
void *checkpoint = zend_arena_checkpoint(optimizer_ctx->arena);
539540
/* We have no dedicated phi vector, so we use the whole ssa var vector instead */
540541
ctx.instr_worklist_len = zend_bitset_len(op_array->last);
541-
ctx.instr_worklist = alloca(sizeof(zend_ulong) * ctx.instr_worklist_len);
542-
memset(ctx.instr_worklist, 0, sizeof(zend_ulong) * ctx.instr_worklist_len);
542+
ctx.instr_worklist = zend_arena_calloc(&optimizer_ctx->arena, ctx.instr_worklist_len, sizeof(zend_ulong));
543543
ctx.phi_worklist_len = zend_bitset_len(ssa->vars_count);
544-
ctx.phi_worklist = alloca(sizeof(zend_ulong) * ctx.phi_worklist_len);
545-
memset(ctx.phi_worklist, 0, sizeof(zend_ulong) * ctx.phi_worklist_len);
546-
ctx.phi_worklist_no_val = alloca(sizeof(zend_ulong) * ctx.phi_worklist_len);
547-
memset(ctx.phi_worklist_no_val, 0, sizeof(zend_ulong) * ctx.phi_worklist_len);
544+
ctx.phi_worklist = zend_arena_calloc(&optimizer_ctx->arena, ctx.phi_worklist_len, sizeof(zend_ulong));
545+
ctx.phi_worklist_no_val = zend_arena_calloc(&optimizer_ctx->arena, ctx.phi_worklist_len, sizeof(zend_ulong));
548546

549547
/* Optimistically assume all instructions and phis to be dead */
550-
ctx.instr_dead = alloca(sizeof(zend_ulong) * ctx.instr_worklist_len);
551-
memset(ctx.instr_dead, 0, sizeof(zend_ulong) * ctx.instr_worklist_len);
552-
ctx.phi_dead = alloca(sizeof(zend_ulong) * ctx.phi_worklist_len);
548+
ctx.instr_dead = zend_arena_calloc(&optimizer_ctx->arena, ctx.instr_worklist_len, sizeof(zend_ulong));
549+
ctx.phi_dead = zend_arena_alloc(&optimizer_ctx->arena, ctx.phi_worklist_len * sizeof(zend_ulong));
553550
memset(ctx.phi_dead, 0xff, sizeof(zend_ulong) * ctx.phi_worklist_len);
554551

555552
/* Mark non-CV phis as live. Even if the result is unused, we generally cannot remove one
@@ -664,5 +661,7 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, bool reorder_d
664661
}
665662
} FOREACH_PHI_END();
666663

664+
zend_arena_release(&optimizer_ctx->arena, checkpoint);
665+
667666
return removed_ops;
668667
}

Zend/Optimizer/dfa_pass.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
10761076
}
10771077

10781078
if (ZEND_OPTIMIZER_PASS_14 & ctx->optimization_level) {
1079-
if (dce_optimize_op_array(op_array, ssa, 0)) {
1079+
if (dce_optimize_op_array(op_array, ctx, ssa, 0)) {
10801080
remove_nops = 1;
10811081
}
10821082
if (zend_dfa_optimize_jmps(op_array, ssa)) {

Zend/Optimizer/zend_optimizer_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ uint32_t zend_optimizer_classify_function(zend_string *name, uint32_t num_args);
121121
void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, zend_op *opline);
122122
void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_t *shiftlist);
123123
int sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa, zend_call_info **call_map);
124-
int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, bool reorder_dtor_effects);
124+
int dce_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *optimizer_ctx, zend_ssa *ssa, bool reorder_dtor_effects);
125125
zend_result zend_ssa_escape_analysis(const zend_script *script, zend_op_array *op_array, zend_ssa *ssa);
126126

127127
typedef void (*zend_op_array_func_t)(zend_op_array *, void *context);

Zend/zend_portability.h

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,6 @@
6363

6464
#include <limits.h>
6565

66-
#if HAVE_ALLOCA_H && !defined(_ALLOCA_H)
67-
# include <alloca.h>
68-
#endif
69-
7066
#if defined(ZEND_WIN32) && !defined(__clang__)
7167
#include <intrin.h>
7268
#endif
@@ -181,6 +177,9 @@
181177
# define ZEND_EXTENSIONS_SUPPORT 0
182178
#endif
183179

180+
#if defined(HAVE_ALLOCA_H) && !defined(_ALLOCA_H)
181+
# include <alloca.h>
182+
#endif
184183
/* AIX requires this to be the first thing in the file. */
185184
#ifndef __GNUC__
186185
# ifndef HAVE_ALLOCA_H
@@ -194,6 +193,25 @@ char *alloca();
194193
# endif
195194
#endif
196195

196+
#if !ZEND_DEBUG && (defined(HAVE_ALLOCA) || (defined (__GNUC__) && __GNUC__ >= 2)) && !(defined(ZTS) && defined(HPUX)) && !defined(DARWIN)
197+
# define ZEND_ALLOCA_MAX_SIZE (32 * 1024)
198+
# define ALLOCA_FLAG(name) \
199+
bool name;
200+
# define SET_ALLOCA_FLAG(name) \
201+
name = true
202+
# define do_alloca_ex(size, limit, use_heap) \
203+
((use_heap = (UNEXPECTED((size) > (limit)))) ? emalloc(size) : alloca(size))
204+
# define do_alloca(size, use_heap) \
205+
do_alloca_ex(size, ZEND_ALLOCA_MAX_SIZE, use_heap)
206+
# define free_alloca(p, use_heap) \
207+
do { if (UNEXPECTED(use_heap)) efree(p); } while (0)
208+
#else
209+
# define ALLOCA_FLAG(name)
210+
# define SET_ALLOCA_FLAG(name)
211+
# define do_alloca(p, use_heap) emalloc(p)
212+
# define free_alloca(p, use_heap) efree(p)
213+
#endif
214+
197215
#if ZEND_GCC_VERSION >= 2096 || __has_attribute(__malloc__)
198216
# define ZEND_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
199217
#else
@@ -345,25 +363,6 @@ char *alloca();
345363
# define XtOffsetOf(s_type, field) offsetof(s_type, field)
346364
#endif
347365

348-
#if (defined(HAVE_ALLOCA) || (defined (__GNUC__) && __GNUC__ >= 2)) && !(defined(ZTS) && defined(HPUX)) && !defined(DARWIN)
349-
# define ZEND_ALLOCA_MAX_SIZE (32 * 1024)
350-
# define ALLOCA_FLAG(name) \
351-
bool name;
352-
# define SET_ALLOCA_FLAG(name) \
353-
name = 1
354-
# define do_alloca_ex(size, limit, use_heap) \
355-
((use_heap = (UNEXPECTED((size) > (limit)))) ? emalloc(size) : alloca(size))
356-
# define do_alloca(size, use_heap) \
357-
do_alloca_ex(size, ZEND_ALLOCA_MAX_SIZE, use_heap)
358-
# define free_alloca(p, use_heap) \
359-
do { if (UNEXPECTED(use_heap)) efree(p); } while (0)
360-
#else
361-
# define ALLOCA_FLAG(name)
362-
# define SET_ALLOCA_FLAG(name)
363-
# define do_alloca(p, use_heap) emalloc(p)
364-
# define free_alloca(p, use_heap) efree(p)
365-
#endif
366-
367366
#ifdef HAVE_SIGSETJMP
368367
# define SETJMP(a) sigsetjmp(a, 0)
369368
# define LONGJMP(a,b) siglongjmp(a, b)

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1610,7 +1610,7 @@ PHP_INSTALL_HEADERS([Zend/Optimizer], [ \
16101610
PHP_ADD_SOURCES(TSRM, TSRM.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
16111611

16121612
PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c \
1613-
fopen_wrappers.c alloca.c php_scandir.c \
1613+
fopen_wrappers.c php_scandir.c \
16141614
php_ini_builder.c \
16151615
php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
16161616
strlcat.c explicit_bzero.c reentrancy.c php_variables.c php_ticks.c \

ext/standard/crypt_sha256.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
#ifdef PHP_WIN32
1212
# define __alignof__ __alignof
13-
# define alloca _alloca
1413
#else
1514
# ifndef HAVE_ALIGNOF
1615
# include <stddef.h>
@@ -370,16 +369,23 @@ char * php_sha256_crypt_r(const char *key, const char *salt, char *buffer, int b
370369

371370
salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
372371
key_len = strlen(key);
372+
char *tmp_key = NULL;
373+
ALLOCA_FLAG(use_heap_key);
374+
char *tmp_salt = NULL;
375+
ALLOCA_FLAG(use_heap_salt);
376+
377+
SET_ALLOCA_FLAG(use_heap_key);
378+
SET_ALLOCA_FLAG(use_heap_salt);
373379

374380
if ((key - (char *) 0) % __alignof__ (uint32_t) != 0) {
375-
char *tmp = (char *) alloca(key_len + __alignof__(uint32_t));
376-
key = copied_key = memcpy(tmp + __alignof__(uint32_t) - (tmp - (char *) 0) % __alignof__(uint32_t), key, key_len);
381+
tmp_key = (char *) do_alloca(key_len + __alignof__(uint32_t), use_heap_key);
382+
key = copied_key = memcpy(tmp_key + __alignof__(uint32_t) - (tmp_key - (char *) 0) % __alignof__(uint32_t), key, key_len);
377383
}
378384

379385
if ((salt - (char *) 0) % __alignof__(uint32_t) != 0) {
380-
char *tmp = (char *) alloca(salt_len + 1 + __alignof__(uint32_t));
386+
tmp_salt = (char *) do_alloca(salt_len + 1 + __alignof__(uint32_t), use_heap_salt);
381387
salt = copied_salt =
382-
memcpy(tmp + __alignof__(uint32_t) - (tmp - (char *) 0) % __alignof__ (uint32_t), salt, salt_len);
388+
memcpy(tmp_salt + __alignof__(uint32_t) - (tmp_salt - (char *) 0) % __alignof__ (uint32_t), salt, salt_len);
383389
copied_salt[salt_len] = 0;
384390
}
385391

@@ -443,7 +449,8 @@ char * php_sha256_crypt_r(const char *key, const char *salt, char *buffer, int b
443449
sha256_finish_ctx(&alt_ctx, temp_result);
444450

445451
/* Create byte sequence P. */
446-
cp = p_bytes = alloca(key_len);
452+
ALLOCA_FLAG(use_heap_p_bytes);
453+
cp = p_bytes = do_alloca(key_len, use_heap_p_bytes);
447454
for (cnt = key_len; cnt >= 32; cnt -= 32) {
448455
cp = __php_mempcpy((void *)cp, (const void *)temp_result, 32);
449456
}
@@ -461,7 +468,8 @@ char * php_sha256_crypt_r(const char *key, const char *salt, char *buffer, int b
461468
sha256_finish_ctx(&alt_ctx, temp_result);
462469

463470
/* Create byte sequence S. */
464-
cp = s_bytes = alloca(salt_len);
471+
ALLOCA_FLAG(use_heap_s_bytes);
472+
cp = s_bytes = do_alloca(salt_len, use_heap_s_bytes);
465473
for (cnt = salt_len; cnt >= 32; cnt -= 32) {
466474
cp = __php_mempcpy(cp, temp_result, 32);
467475
}
@@ -571,6 +579,14 @@ char * php_sha256_crypt_r(const char *key, const char *salt, char *buffer, int b
571579
if (copied_salt != NULL) {
572580
ZEND_SECURE_ZERO(copied_salt, salt_len);
573581
}
582+
if (tmp_key != NULL) {
583+
free_alloca(tmp_key, use_heap_key);
584+
}
585+
if (tmp_salt != NULL) {
586+
free_alloca(tmp_salt, use_heap_salt);
587+
}
588+
free_alloca(p_bytes, use_heap_p_bytes);
589+
free_alloca(s_bytes, use_heap_s_bytes);
574590

575591
return buffer;
576592
}

ext/standard/crypt_sha512.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include <limits.h>
1010
#ifdef PHP_WIN32
1111
# define __alignof__ __alignof
12-
# define alloca _alloca
1312
#else
1413
# ifndef HAVE_ALIGNOF
1514
# include <stddef.h>
@@ -404,16 +403,23 @@ php_sha512_crypt_r(const char *key, const char *salt, char *buffer, int buflen)
404403

405404
salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
406405
key_len = strlen(key);
406+
char *tmp_key = NULL;
407+
ALLOCA_FLAG(use_heap_key);
408+
char *tmp_salt = NULL;
409+
ALLOCA_FLAG(use_heap_salt);
410+
411+
SET_ALLOCA_FLAG(use_heap_key);
412+
SET_ALLOCA_FLAG(use_heap_salt);
407413

408414
if ((key - (char *) 0) % __alignof__ (uint64_t) != 0) {
409-
char *tmp = (char *) alloca (key_len + __alignof__ (uint64_t));
415+
tmp_key = (char *) do_alloca(key_len + __alignof__ (uint64_t), use_heap_key);
410416
key = copied_key =
411-
memcpy(tmp + __alignof__(uint64_t) - (tmp - (char *) 0) % __alignof__(uint64_t), key, key_len);
417+
memcpy(tmp_key + __alignof__(uint64_t) - (tmp_key - (char *) 0) % __alignof__(uint64_t), key, key_len);
412418
}
413419

414420
if ((salt - (char *) 0) % __alignof__ (uint64_t) != 0) {
415-
char *tmp = (char *) alloca(salt_len + 1 + __alignof__(uint64_t));
416-
salt = copied_salt = memcpy(tmp + __alignof__(uint64_t) - (tmp - (char *) 0) % __alignof__(uint64_t), salt, salt_len);
421+
tmp_salt = (char *) do_alloca(salt_len + 1 + __alignof__(uint64_t), use_heap_salt);
422+
salt = copied_salt = memcpy(tmp_salt + __alignof__(uint64_t) - (tmp_salt - (char *) 0) % __alignof__(uint64_t), salt, salt_len);
417423
copied_salt[salt_len] = 0;
418424
}
419425

@@ -477,7 +483,8 @@ php_sha512_crypt_r(const char *key, const char *salt, char *buffer, int buflen)
477483
sha512_finish_ctx(&alt_ctx, temp_result);
478484

479485
/* Create byte sequence P. */
480-
cp = p_bytes = alloca(key_len);
486+
ALLOCA_FLAG(use_heap_p_bytes);
487+
cp = p_bytes = do_alloca(key_len, use_heap_p_bytes);
481488
for (cnt = key_len; cnt >= 64; cnt -= 64) {
482489
cp = __php_mempcpy((void *) cp, (const void *)temp_result, 64);
483490
}
@@ -496,7 +503,8 @@ php_sha512_crypt_r(const char *key, const char *salt, char *buffer, int buflen)
496503
sha512_finish_ctx(&alt_ctx, temp_result);
497504

498505
/* Create byte sequence S. */
499-
cp = s_bytes = alloca(salt_len);
506+
ALLOCA_FLAG(use_heap_s_bytes);
507+
cp = s_bytes = do_alloca(salt_len, use_heap_s_bytes);
500508
for (cnt = salt_len; cnt >= 64; cnt -= 64) {
501509
cp = __php_mempcpy(cp, temp_result, 64);
502510
}
@@ -618,6 +626,14 @@ php_sha512_crypt_r(const char *key, const char *salt, char *buffer, int buflen)
618626
if (copied_salt != NULL) {
619627
ZEND_SECURE_ZERO(copied_salt, salt_len);
620628
}
629+
if (tmp_key != NULL) {
630+
free_alloca(tmp_key, use_heap_key);
631+
}
632+
if (tmp_salt != NULL) {
633+
free_alloca(tmp_salt, use_heap_salt);
634+
}
635+
free_alloca(p_bytes, use_heap_p_bytes);
636+
free_alloca(s_bytes, use_heap_s_bytes);
621637

622638
return buffer;
623639
}

0 commit comments

Comments
 (0)