[DTrace-devel] [PATCH v3 09/19] alloca: deref

Kris Van Hees kris.van.hees at oracle.com
Thu Mar 31 04:36:17 UTC 2022


Still going through this patch in further detail but here are some first
comments:

1. It seems that several tests in this patch are not related to alloca
   ptr deref at all.  They should be moved to the patch(es) that provide
   the implementation code that is being tested.

2. The following test is added as a test that is expected to report a fault:

	unittest/funcs/alloca/err.alloca-store-load-aliasing-arith-bottom.d	

   However, this test does not report a fault on DTrace on Solaris.  It does
   work there:

dtrace -n 'BEGIN { s = (char *)alloca(10); j = s - 1; j[1] = 65; trace(s[0]); exit(0); }'
dtrace: description 'BEGIN ' matched 1 probe
 CPU     ID                    FUNCTION:NAME
   0      1                           :BEGIN   65

   I would expect it to work for DTrace based on BPF as well.  After all, there
   is no deref of j until we handle j[1] which is *(j + 1) and that is a valid
   pointer.

Again, this is just first observation.  But points out a problem in terms of
equivalent behaviour with the reference implementation for DTrace.

On Thu, Mar 24, 2022 at 06:24:35PM +0000, Nick Alcock via DTrace-devel wrote:
> After the last commit we can alloca()te, store the returned pointers in
> variables and get them back out looking identical to how they were
> stored, with suitable verifier bounds.
> 
> All that is left is handling dereferences.  We have two distinct sorts
> of derefs to deal with: non-lvalue derefs, like *foo, for which the
> load is done at the time of dereferencing and the size is known, and
> lvalue loads, like foo[10]=bar, where the size stored is not known
> until after the deref is complete.  In both cases we must
> re-bounds-check: the pointer that we are dealing with will have been
> bounds-checked already, one way or another, but it is common to modify
> that pointer (usually via addition, sometimes, e.g. in lvalues,
> compiler-generated addition), and we must bounds-check again after that
> to make sure it is still in bounds.
> 
> For non-lvalue derefs this is quite easy: adjust dt_cg_load so it tells
> us the size of load it's generating an op for, and add a bounds check to
> the DT_TOK_DEREF case in dt_cg_node.  We do the actual bounds-checking
> using a new dt_cg_check_scratch_bounds, which handles the annoying
> getting-the-scratch-base part and then calls the bounds checker we
> already wrote, dt_cg_check_bounds (exploiting its previously unused
> ability to bounds-check not just offsets but pointers too).
> 
> For lvalue derefs this is trickier: at DT_TOK_DEREF codegen time we have
> no idea what size of store will be carried out, and in fact dt_cg_node
> generates no code at all to deref an lvalue store.  The deref is carried
> out in dt_cg_store, which has to grow a special case for a store to a
> writable lvalue node whose child is a deref with the DT_NF_ALLOCA flag
> turned on.  (This combination is generated by the compiler for lvalue
> stores, so is completely stereotyped and safe to rely on).  When this
> case fires we can do a bounds-check just like the one done for reads.
> 
> We can also add a lot of tests and flip off XFAIL for a few pre-existing
> ones, now that alloca, and variable storage, and dereferencing all work.
> 
> Signed-off-by: Nick Alcock <nick.alcock at oracle.com>
> ---
>  libdtrace/dt_cg.c                             | 75 +++++++++++++++++--
>  test/unittest/dif/alloca.d                    |  3 +-
>  .../alloca/err.D_ALLOCA_INCOMPAT.ternary.d    | 26 +++++++
>  .../alloca/err.D_ALLOCA_INCOMPAT.ternary.r    |  2 +
>  ...rr.D_ALLOCA_INCOMPAT.var-clash-non-first.d | 28 +++++++
>  ...rr.D_ALLOCA_INCOMPAT.var-clash-non-first.r |  2 +
>  .../alloca/err.D_ALLOCA_INCOMPAT.var-clash.d  | 28 +++++++
>  .../alloca/err.D_ALLOCA_INCOMPAT.var-clash.r  |  2 +
>  .../alloca/err.alloca-crossing-clauses.d      | 31 ++++++++
>  .../alloca/err.alloca-crossing-clauses.r      |  3 +
>  .../alloca/err.alloca-load-before-bottom.d    | 26 +++++++
>  .../alloca/err.alloca-load-before-bottom.r    |  3 +
>  .../funcs/alloca/err.alloca-load-beyond-top.d | 28 +++++++
>  .../funcs/alloca/err.alloca-load-beyond-top.r |  3 +
>  .../alloca/err.alloca-load-crossing-bottom.d  | 25 +++++++
>  .../alloca/err.alloca-load-crossing-bottom.r  |  3 +
>  .../alloca/err.alloca-load-crossing-top.d     | 25 +++++++
>  .../alloca/err.alloca-load-crossing-top.r     |  3 +
>  .../alloca/err.alloca-store-before-bottom.d   | 26 +++++++
>  .../alloca/err.alloca-store-before-bottom.r   |  3 +
>  .../alloca/err.alloca-store-beyond-top.d      | 28 +++++++
>  .../alloca/err.alloca-store-beyond-top.r      |  3 +
>  .../alloca/err.alloca-store-crossing-bottom.d | 26 +++++++
>  .../alloca/err.alloca-store-crossing-bottom.r |  3 +
>  .../alloca/err.alloca-store-crossing-top.d    | 25 +++++++
>  .../alloca/err.alloca-store-crossing-top.r    |  3 +
>  ....alloca-store-load-aliasing-arith-bottom.d | 28 +++++++
>  ....alloca-store-load-aliasing-arith-bottom.r |  3 +
>  .../funcs/alloca/tst.alloca-alignment.d       | 34 +++++++++
>  .../alloca/tst.alloca-crossing-clauses.d      | 33 ++++++++
>  .../funcs/alloca/tst.alloca-overtainting.sh   | 35 +++++++++
>  .../tst.alloca-store-load-aliasing-arith.d    | 29 +++++++
>  .../alloca/tst.alloca-store-load-bottom.d     | 27 +++++++
>  .../alloca/tst.alloca-store-load-idx-1.d      | 27 +++++++
>  .../funcs/alloca/tst.alloca-store-load-top.d  | 27 +++++++
>  .../alloca/tst.alloca0-after-alloca-load.d    | 28 +++++++
>  .../funcs/alloca/tst.alloca0-after-alloca.d   | 26 +++++++
>  test/unittest/funcs/alloca/tst.alloca0-load.d | 27 +++++++
>  .../funcs/alloca/tst.alloca0-values.sh        | 34 +++++++++
>  test/unittest/funcs/alloca/tst.alloca0.d      | 25 +++++++
>  test/unittest/funcs/alloca/tst.ternary.d      | 27 +++++++
>  .../funcs/err.D_ALLOCA_SIZE.big_alloca.d      | 24 ++++++
>  .../funcs/err.D_ALLOCA_SIZE.big_alloca.r      |  2 +
>  test/unittest/funcs/err.badalloca2.d          |  3 +-
>  test/unittest/funcs/err.badalloca2.r          |  6 +-
>  ...CA_INCOMPAT.alloca-postinc-instantiation.d | 21 ++++++
>  ...CA_INCOMPAT.alloca-postinc-instantiation.r |  2 +
>  .../tst.alloca-postinc-instantiation.d        | 46 ++++++++++++
>  48 files changed, 933 insertions(+), 14 deletions(-)
>  create mode 100644 test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.ternary.d
>  create mode 100644 test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.ternary.r
>  create mode 100644 test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash-non-first.d
>  create mode 100644 test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash-non-first.r
>  create mode 100644 test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash.d
>  create mode 100644 test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash.r
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-crossing-clauses.d
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-crossing-clauses.r
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-load-before-bottom.d
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-load-before-bottom.r
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-load-beyond-top.d
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-load-beyond-top.r
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-load-crossing-bottom.d
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-load-crossing-bottom.r
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-load-crossing-top.d
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-load-crossing-top.r
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-store-before-bottom.d
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-store-before-bottom.r
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-store-beyond-top.d
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-store-beyond-top.r
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-store-crossing-bottom.d
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-store-crossing-bottom.r
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-store-crossing-top.d
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-store-crossing-top.r
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-store-load-aliasing-arith-bottom.d
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-store-load-aliasing-arith-bottom.r
>  create mode 100644 test/unittest/funcs/alloca/tst.alloca-alignment.d
>  create mode 100644 test/unittest/funcs/alloca/tst.alloca-crossing-clauses.d
>  create mode 100755 test/unittest/funcs/alloca/tst.alloca-overtainting.sh
>  create mode 100644 test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith.d
>  create mode 100644 test/unittest/funcs/alloca/tst.alloca-store-load-bottom.d
>  create mode 100644 test/unittest/funcs/alloca/tst.alloca-store-load-idx-1.d
>  create mode 100644 test/unittest/funcs/alloca/tst.alloca-store-load-top.d
>  create mode 100644 test/unittest/funcs/alloca/tst.alloca0-after-alloca-load.d
>  create mode 100644 test/unittest/funcs/alloca/tst.alloca0-after-alloca.d
>  create mode 100644 test/unittest/funcs/alloca/tst.alloca0-load.d
>  create mode 100755 test/unittest/funcs/alloca/tst.alloca0-values.sh
>  create mode 100644 test/unittest/funcs/alloca/tst.alloca0.d
>  create mode 100644 test/unittest/funcs/alloca/tst.ternary.d
>  create mode 100644 test/unittest/funcs/err.D_ALLOCA_SIZE.big_alloca.d
>  create mode 100644 test/unittest/funcs/err.D_ALLOCA_SIZE.big_alloca.r
>  create mode 100644 test/unittest/predicates/err.D_ALLOCA_INCOMPAT.alloca-postinc-instantiation.d
>  create mode 100644 test/unittest/predicates/err.D_ALLOCA_INCOMPAT.alloca-postinc-instantiation.r
>  create mode 100644 test/unittest/predicates/tst.alloca-postinc-instantiation.d
> 
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index 0e9b98a32aec..def6cae777b7 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -2043,7 +2043,7 @@ dt_cg_setx(dt_irlist_t *dlp, int reg, uint64_t x)
>   * user=1 sign=1 size=4 => binary index 11011 = decimal index 27
>   */
>  static uint_t
> -dt_cg_load(dt_node_t *dnp, ctf_file_t *ctfp, ctf_id_t type)
> +dt_cg_load(dt_node_t *dnp, ctf_file_t *ctfp, ctf_id_t type, ssize_t *ret_size)
>  {
>  #if 1
>  	ctf_encoding_t e;
> @@ -2065,6 +2065,9 @@ dt_cg_load(dt_node_t *dnp, ctf_file_t *ctfp, ctf_id_t type)
>  		    "size %ld when passed by value\n", (long)size);
>  	}
>  
> +	if (ret_size)
> +		*ret_size = size;
> +
>  	return ldstw[size];
>  #else
>  	static const uint_t ops[] = {
> @@ -2104,6 +2107,9 @@ dt_cg_load(dt_node_t *dnp, ctf_file_t *ctfp, ctf_id_t type)
>  	if (dnp->dn_flags & DT_NF_USERLAND)
>  		size |= 0x10;
>  
> +	if (ret_size)
> +		*ret_size = size;
> +
>  	return ops[size];
>  #endif
>  }
> @@ -2206,6 +2212,38 @@ dt_cg_check_bounds(dt_irlist_t *dlp, dt_regset_t *drp, int regptr, int basereg,
>  			    BPF_NOP());
>  }
>  
> +/*
> + * For an alloca'ed allocation, verify that a read/write op on the pointer REG
> + * of size SIZE lands entirely within scratch space.  On return, REG is
> + * bounds-checked.  If SIZEMAX is >-1, SIZE is a register, with a max
> + * allowed value given by SIZEMAX.
> + */
> +static void
> +dt_cg_check_scratch_bounds(dt_irlist_t *dlp, dt_regset_t *drp, int reg, int size,
> +	int sizemax)
> +{
> +	int	opt_scratchsize = yypcb->pcb_hdl->dt_options[DTRACEOPT_SCRATCHSIZE];
> +	int	scratchlen, scratchbot;
> +
> +	if ((scratchlen = dt_regset_alloc(drp)) == -1 ||
> +	    (scratchbot = dt_regset_alloc(drp)) == -1)
> +		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> +
> +	emit(dlp,  BPF_LOAD(BPF_DW, scratchlen, BPF_REG_FP, DT_STK_DCTX));
> +	emit(dlp,  BPF_LOAD(BPF_DW, scratchlen, scratchlen, DCTX_MST));
> +	emit(dlp,  BPF_LOAD(BPF_DW, scratchlen, scratchlen,
> +			    DMST_SCRATCH_TOP));
> +	emit(dlp, BPF_ALU64_IMM(BPF_AND, scratchlen, clp2(opt_scratchsize + 1) - 1));
> +
> +	emit(dlp, BPF_LOAD(BPF_DW, scratchbot, BPF_REG_FP, DT_STK_DCTX));
> +	emit(dlp, BPF_LOAD(BPF_DW, scratchbot, scratchbot, DCTX_SCRATCHMEM));
> +
> +	dt_cg_check_bounds(dlp, drp, 1, scratchbot, reg, size, scratchlen,
> +			   sizemax, opt_scratchsize * 2);
> +	dt_regset_free(drp, scratchlen);
> +	dt_regset_free(drp, scratchbot);
> +}
> +
>  /* Handle loading a pointer to alloca'ed space.  */
>  
>  static void
> @@ -2528,7 +2566,7 @@ dt_cg_field_set(dt_node_t *src, dt_irlist_t *dlp,
>  	 * r1 |= r2
>  	 */
>  	/* FIXME: Does not handle userland */
> -	emit(dlp, BPF_LOAD(dt_cg_load(dst, fp, m.ctm_type), r1, dst->dn_reg, 0));
> +	emit(dlp, BPF_LOAD(dt_cg_load(dst, fp, m.ctm_type, NULL), r1, dst->dn_reg, 0));
>  	dt_cg_setx(dlp, r2, cmask);
>  	emit(dlp, BPF_ALU64_REG(BPF_AND, r1, r2));
>  	dt_cg_setx(dlp, r2, fmask);
> @@ -2558,6 +2596,18 @@ dt_cg_store(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp, dt_node_t *dst)
>  	else
>  		size = dt_node_type_size(dst);
>  
> +	/*
> +	 * If we're loading a writable non-alloca lvalue, and it's a
> +	 * dereference, and *its* child is an alloca pointer, then this is a
> +	 * dereferenced alloca pointer and needs bounds-checking (which could
> +	 * not be done at deref time due to not knowing the size of the write).
> +	 */
> +	if (dst->dn_flags & DT_NF_WRITABLE && dst->dn_flags & DT_NF_LVALUE
> +	    && dst->dn_op == DT_TOK_DEREF && dst->dn_child->dn_flags & DT_NF_ALLOCA) {
> +		assert(!(dst->dn_flags & DT_NF_BITFIELD));
> +		dt_cg_check_scratch_bounds(dlp, drp, dst->dn_reg, size, -1);
> +	}
> +
>  	if (src->dn_flags & DT_NF_REF)
>  		dt_cg_memcpy(dlp, drp, dst->dn_reg, src->dn_reg, size);
>  	else {
> @@ -4960,6 +5010,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>  
>  		if (!(dnp->dn_flags & DT_NF_REF)) {
>  			uint_t	ubit;
> +			uint_t	op;
> +			ssize_t	size;
>  
>  			/*
>  			 * Save and restore DT_NF_USERLAND across dt_cg_load():
> @@ -4971,9 +5023,20 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>  			    (dnp->dn_child->dn_flags & DT_NF_USERLAND);
>  
>  			dt_cg_check_notnull(dlp, drp, dnp->dn_reg);
> +			op = dt_cg_load(dnp, ctfp, dnp->dn_type, &size);
> +
> +			/*
> +			 * If the child is an alloca pointer, bounds-check it
> +			 * now.
> +			 */
> +			if (dnp->dn_child->dn_flags & DT_NF_ALLOCA) {
> +				assert(!(dnp->dn_flags & DT_NF_ALLOCA));
> +				dt_cg_check_scratch_bounds(dlp, drp, dnp->dn_reg,
> +							   size, -1);
> +			}
>  
>  			/* FIXME: Does not handled signed or userland */
> -			emit(dlp, BPF_LOAD(dt_cg_load(dnp, ctfp, dnp->dn_type), dnp->dn_reg, dnp->dn_reg, 0));
> +			emit(dlp, BPF_LOAD(op, dnp->dn_reg, dnp->dn_reg, 0));
>  
>  			dnp->dn_flags &= ~DT_NF_USERLAND;
>  			dnp->dn_flags |= ubit;
> @@ -5130,7 +5193,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>  			    (dnp->dn_left->dn_flags & DT_NF_USERLAND);
>  
>  			/* FIXME: Does not handle signed and userland */
> -			emit(dlp, BPF_LOAD(dt_cg_load(dnp, ctfp, m.ctm_type), dnp->dn_left->dn_reg, dnp->dn_left->dn_reg, 0));
> +			emit(dlp, BPF_LOAD(dt_cg_load(dnp, ctfp, m.ctm_type, NULL),
> +					   dnp->dn_left->dn_reg, dnp->dn_left->dn_reg, 0));
>  
>  			dnp->dn_flags &= ~DT_NF_USERLAND;
>  			dnp->dn_flags |= ubit;
> @@ -5241,7 +5305,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>  
>  			if (!(dnp->dn_flags & DT_NF_REF)) {
>  				/* FIXME: NO signed or userland yet */
> -				emit(dlp, BPF_LOAD(dt_cg_load(dnp, ctfp, dnp->dn_type), dnp->dn_reg, dnp->dn_reg, 0));
> +				emit(dlp, BPF_LOAD(dt_cg_load(dnp, ctfp, dnp->dn_type, NULL),
> +						   dnp->dn_reg, dnp->dn_reg, 0));
>  			}
>  			break;
>  		}
> diff --git a/test/unittest/dif/alloca.d b/test/unittest/dif/alloca.d
> index 9051ebbab7ed..c080acd2984a 100644
> --- a/test/unittest/dif/alloca.d
> +++ b/test/unittest/dif/alloca.d
> @@ -1,6 +1,5 @@
> -/* @@xfail: dtv2 */
>  BEGIN
>  {
> -	self->a = alloca(1024);
> +	this->a = alloca(256);
>  	exit(0);
>  }
> diff --git a/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.ternary.d b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.ternary.d
> new file mode 100644
> index 000000000000..8de49be05b0f
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.ternary.d
> @@ -0,0 +1,26 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: ternary conditionals with alloca and non-alloca branches
> + *            cannot be assigned to variables.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	a = (char *) alloca(1);
> +        a = (a == NULL) ? (char *) 50 : a;
> +}
> +
> +ERROR
> +{
> +	exit(0);
> +}
> diff --git a/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.ternary.r b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.ternary.r
> new file mode 100644
> index 000000000000..c117d44a081f
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.ternary.r
> @@ -0,0 +1,2 @@
> +-- @@stderr --
> +dtrace: failed to compile script test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.ternary.d: [D_ALLOCA_INCOMPAT] line 20: ternary conditional with alloca and non-alloca branches cannot be assigned to a variable
> diff --git a/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash-non-first.d b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash-non-first.d
> new file mode 100644
> index 000000000000..ace3fd3aa824
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash-non-first.d
> @@ -0,0 +1,28 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: the same variable cannot be reused for alloca and
> + *            non-alloca pointers, even in different clauses.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	b = (char *) &`max_pfn;
> +        a = b + 5;
> +}
> +
> +BEGIN
> +{
> +	a = (char *) alloca(1);
> +	trace(a);
> +	exit(0);
> +}
> diff --git a/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash-non-first.r b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash-non-first.r
> new file mode 100644
> index 000000000000..73ed28ba011b
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash-non-first.r
> @@ -0,0 +1,2 @@
> +-- @@stderr --
> +dtrace: failed to compile script test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash-non-first.d: [D_ALLOCA_INCOMPAT] line 23: a: cannot reuse the same identifier for both alloca and non-alloca allocations
> diff --git a/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash.d b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash.d
> new file mode 100644
> index 000000000000..d6474d5f18ba
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash.d
> @@ -0,0 +1,28 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: the same variable cannot be reused for alloca and
> + *            non-alloca pointers, even in different clauses.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	a = (char *) alloca(1);
> +}
> +
> +BEGIN
> +{
> +	b = (char *) &`max_pfn;
> +        a = b + 5;
> +	trace(a);
> +	exit(0);
> +}
> diff --git a/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash.r b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash.r
> new file mode 100644
> index 000000000000..a2fdf1035407
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash.r
> @@ -0,0 +1,2 @@
> +-- @@stderr --
> +dtrace: failed to compile script test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash.d: [D_ALLOCA_INCOMPAT] line 22: a: cannot reuse the same identifier for both alloca and non-alloca allocations
> diff --git a/test/unittest/funcs/alloca/err.alloca-crossing-clauses.d b/test/unittest/funcs/alloca/err.alloca-crossing-clauses.d
> new file mode 100644
> index 000000000000..eaadc40a533d
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-crossing-clauses.d
> @@ -0,0 +1,31 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: alloca does not live beyond clause boundaries.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (char *)alloca(1);
> +        *s = 'a';
> +}
> +
> +BEGIN
> +{
> +        trace(*s);
> +        exit(0);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> \ No newline at end of file
> diff --git a/test/unittest/funcs/alloca/err.alloca-crossing-clauses.r b/test/unittest/funcs/alloca/err.alloca-crossing-clauses.r
> new file mode 100644
> index 000000000000..f5ff855de001
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-crossing-clauses.r
> @@ -0,0 +1,3 @@
> +
> +-- @@stderr --
> +dtrace: error on enabled probe ID 4 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #2 at BPF pc NNN
> diff --git a/test/unittest/funcs/alloca/err.alloca-load-before-bottom.d b/test/unittest/funcs/alloca/err.alloca-load-before-bottom.d
> new file mode 100644
> index 000000000000..9eeafc0f11f6
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-load-before-bottom.d
> @@ -0,0 +1,26 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Loads before the bottom of alloca()ed memory fail.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (char *)alloca(15);
> +	trace(s[-1]);
> +        exit(0);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/err.alloca-load-before-bottom.r b/test/unittest/funcs/alloca/err.alloca-load-before-bottom.r
> new file mode 100644
> index 000000000000..187543b63023
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-load-before-bottom.r
> @@ -0,0 +1,3 @@
> +
> +-- @@stderr --
> +dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
> diff --git a/test/unittest/funcs/alloca/err.alloca-load-beyond-top.d b/test/unittest/funcs/alloca/err.alloca-load-beyond-top.d
> new file mode 100644
> index 000000000000..b121179cfdf7
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-load-beyond-top.d
> @@ -0,0 +1,28 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Loads from beyond the top of alloca()ed memory fail.
> + *            (Small overreads will often succeed due to alignment
> + *            guarantees.  This one should always fail.)
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (char *)alloca(15);
> +	trace(s[16]);
> +        exit(0);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/err.alloca-load-beyond-top.r b/test/unittest/funcs/alloca/err.alloca-load-beyond-top.r
> new file mode 100644
> index 000000000000..4257f5679dfd
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-load-beyond-top.r
> @@ -0,0 +1,3 @@
> +
> +-- @@stderr --
> +dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid size ({ptr}) in action #1 at BPF pc NNN
> diff --git a/test/unittest/funcs/alloca/err.alloca-load-crossing-bottom.d b/test/unittest/funcs/alloca/err.alloca-load-crossing-bottom.d
> new file mode 100644
> index 000000000000..8208ea5e134e
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-load-crossing-bottom.d
> @@ -0,0 +1,25 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Loads crossing the bottom of alloca()ed memory fail.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (int *)alloca(10);
> +	trace(s[-1]);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/err.alloca-load-crossing-bottom.r b/test/unittest/funcs/alloca/err.alloca-load-crossing-bottom.r
> new file mode 100644
> index 000000000000..187543b63023
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-load-crossing-bottom.r
> @@ -0,0 +1,3 @@
> +
> +-- @@stderr --
> +dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
> diff --git a/test/unittest/funcs/alloca/err.alloca-load-crossing-top.d b/test/unittest/funcs/alloca/err.alloca-load-crossing-top.d
> new file mode 100644
> index 000000000000..9ecd0c7ed4a5
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-load-crossing-top.d
> @@ -0,0 +1,25 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Loads crossing the top of alloca()ed memory fail.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (int *)alloca(10);
> +	trace(s[9]);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/err.alloca-load-crossing-top.r b/test/unittest/funcs/alloca/err.alloca-load-crossing-top.r
> new file mode 100644
> index 000000000000..4257f5679dfd
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-load-crossing-top.r
> @@ -0,0 +1,3 @@
> +
> +-- @@stderr --
> +dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid size ({ptr}) in action #1 at BPF pc NNN
> diff --git a/test/unittest/funcs/alloca/err.alloca-store-before-bottom.d b/test/unittest/funcs/alloca/err.alloca-store-before-bottom.d
> new file mode 100644
> index 000000000000..c0e5e4e0256b
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-store-before-bottom.d
> @@ -0,0 +1,26 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Stores before the bottom of alloca()ed memory fail.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (char *)alloca(15);
> +	s[-1] = 65;
> +        exit(0);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/err.alloca-store-before-bottom.r b/test/unittest/funcs/alloca/err.alloca-store-before-bottom.r
> new file mode 100644
> index 000000000000..187543b63023
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-store-before-bottom.r
> @@ -0,0 +1,3 @@
> +
> +-- @@stderr --
> +dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
> diff --git a/test/unittest/funcs/alloca/err.alloca-store-beyond-top.d b/test/unittest/funcs/alloca/err.alloca-store-beyond-top.d
> new file mode 100644
> index 000000000000..a47024ac6c96
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-store-beyond-top.d
> @@ -0,0 +1,28 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Stores to beyond the top of alloca()ed memory fail.
> + *            (Small overreads will often succeed due to alignment
> + *            guarantees.  This one should always fail.)
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (char *)alloca(15);
> +	s[16] = 65;
> +        exit(0);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/err.alloca-store-beyond-top.r b/test/unittest/funcs/alloca/err.alloca-store-beyond-top.r
> new file mode 100644
> index 000000000000..4257f5679dfd
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-store-beyond-top.r
> @@ -0,0 +1,3 @@
> +
> +-- @@stderr --
> +dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid size ({ptr}) in action #1 at BPF pc NNN
> diff --git a/test/unittest/funcs/alloca/err.alloca-store-crossing-bottom.d b/test/unittest/funcs/alloca/err.alloca-store-crossing-bottom.d
> new file mode 100644
> index 000000000000..b4dc5a4c56e7
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-store-crossing-bottom.d
> @@ -0,0 +1,26 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Stores crossing the bottom of alloca()ed memory fail.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (int *)alloca(15);
> +	s[-1] = 65;
> +        exit(0);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/err.alloca-store-crossing-bottom.r b/test/unittest/funcs/alloca/err.alloca-store-crossing-bottom.r
> new file mode 100644
> index 000000000000..187543b63023
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-store-crossing-bottom.r
> @@ -0,0 +1,3 @@
> +
> +-- @@stderr --
> +dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
> diff --git a/test/unittest/funcs/alloca/err.alloca-store-crossing-top.d b/test/unittest/funcs/alloca/err.alloca-store-crossing-top.d
> new file mode 100644
> index 000000000000..bf935498bdad
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-store-crossing-top.d
> @@ -0,0 +1,25 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Stores crossing the top of alloca()ed memory fail.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (int *)alloca(10);
> +	s[9] = 65;
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/err.alloca-store-crossing-top.r b/test/unittest/funcs/alloca/err.alloca-store-crossing-top.r
> new file mode 100644
> index 000000000000..4257f5679dfd
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-store-crossing-top.r
> @@ -0,0 +1,3 @@
> +
> +-- @@stderr --
> +dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid size ({ptr}) in action #1 at BPF pc NNN
> diff --git a/test/unittest/funcs/alloca/err.alloca-store-load-aliasing-arith-bottom.d b/test/unittest/funcs/alloca/err.alloca-store-load-aliasing-arith-bottom.d
> new file mode 100644
> index 000000000000..6bb54290cb01
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-store-load-aliasing-arith-bottom.d
> @@ -0,0 +1,28 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: You can't use a pointer to alloca'ed memory if it's been
> + *	      modified such that it no longer points there.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (char *)alloca(10);
> +        j = s - 1;
> +	j[1] = 65;
> +	exit((s[0] == 65 ? 0 : 1) ? 0 : 1);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/err.alloca-store-load-aliasing-arith-bottom.r b/test/unittest/funcs/alloca/err.alloca-store-load-aliasing-arith-bottom.r
> new file mode 100644
> index 000000000000..187543b63023
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-store-load-aliasing-arith-bottom.r
> @@ -0,0 +1,3 @@
> +
> +-- @@stderr --
> +dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
> diff --git a/test/unittest/funcs/alloca/tst.alloca-alignment.d b/test/unittest/funcs/alloca/tst.alloca-alignment.d
> new file mode 100644
> index 000000000000..22e6e5ce9fdc
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca-alignment.d
> @@ -0,0 +1,34 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: alloca() allocations are suitably aligned for any native datatype.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	a = alloca(1);
> +	b = alloca(1);
> +	trace((uint64_t) b);
> +        trace("\n");
> +	trace((uint64_t) a);
> +        trace("\n");
> +	trace((uint64_t) b - (uint64_t) a);
> +        trace("\n");
> +	trace(sizeof (uint64_t));
> +        trace("\n");
> +	exit((uint64_t) b - (uint64_t) a != sizeof (uint64_t));
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/tst.alloca-crossing-clauses.d b/test/unittest/funcs/alloca/tst.alloca-crossing-clauses.d
> new file mode 100644
> index 000000000000..91409ec33781
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca-crossing-clauses.d
> @@ -0,0 +1,33 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: alloca does not live beyond clause boundaries; allocas in
> + *	      subsequent clauses reuse the same addresses.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (char *)alloca(1);
> +        *s = 'a';
> +}
> +
> +BEGIN
> +{
> +	s2 = (char *)alloca(1);
> +        *s2 = 'b';
> +        exit(s == s2 ? 0 : 1);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> \ No newline at end of file
> diff --git a/test/unittest/funcs/alloca/tst.alloca-overtainting.sh b/test/unittest/funcs/alloca/tst.alloca-overtainting.sh
> new file mode 100755
> index 000000000000..3d4d64bae9fd
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca-overtainting.sh
> @@ -0,0 +1,35 @@
> +#!/bin/bash
> +#
> +# Oracle Linux DTrace.
> +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> +# Licensed under the Universal Permissive License v 1.0 as shown at
> +# http://oss.oracle.com/licenses/upl.
> +#
> +
> +if [ $# != 1 ]; then
> +	echo expected one argument: '<'dtrace-path'>'
> +	exit 2
> +fi
> +
> +dtrace=$1
> +tmpfile=${tmpdir:-/tmp}/tst.alloca0-overtainting.$$
> +
> +$dtrace $dt_flags -xtree=4 -s /dev/stdin > $tmpfile 2>&1 <<EOT
> +BEGIN
> +{
> +	bar = alloca(10);
> +	trace(bar);
> +	exit(0);
> +}
> +EOT
> +
> +grep -q 'FUNC trace.*ALLOCA' $tmpfile
> +status=$?
> +
> +rm $tmpfile
> +
> +if [[ $status -gt 0 ]]; then
> +    exit 0
> +else
> +    exit 1
> +fi
> diff --git a/test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith.d b/test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith.d
> new file mode 100644
> index 000000000000..291052a888d7
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith.d
> @@ -0,0 +1,29 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: It is possible to store to and load from alloca'ed memory
> + *	      via a pointer modified to still point in there.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (char *)alloca(1);
> +	s = (char *)alloca(10);
> +        j = s - 1;
> +	j[1] = 65;
> +	exit(s[0] == 65 ? 0 : 1);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/tst.alloca-store-load-bottom.d b/test/unittest/funcs/alloca/tst.alloca-store-load-bottom.d
> new file mode 100644
> index 000000000000..61d2eea3f9ae
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca-store-load-bottom.d
> @@ -0,0 +1,27 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: It is possible to store to and load from the bottom byte of
> + *	      alloca()'d memory.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (char *)alloca(10);
> +	s[0] = 65;
> +	exit(s[0] == 65 ? 0 : 1);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/tst.alloca-store-load-idx-1.d b/test/unittest/funcs/alloca/tst.alloca-store-load-idx-1.d
> new file mode 100644
> index 000000000000..77a454a8cab4
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca-store-load-idx-1.d
> @@ -0,0 +1,27 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: It is possible to store to and load from byte 1 of alloca()'d
> + *	      memory.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (char *)alloca(10);
> +	s[1] = 65;
> +	exit(s[1] == 65 ? 0 : 1);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/tst.alloca-store-load-top.d b/test/unittest/funcs/alloca/tst.alloca-store-load-top.d
> new file mode 100644
> index 000000000000..48b50044fec8
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca-store-load-top.d
> @@ -0,0 +1,27 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: It is possible to store to and load from the top byte of
> + *	      alloca()'d memory.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (char *)alloca(10);
> +	s[9] = 65;
> +	exit(s[9] == 65 ? 0 : 1);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/tst.alloca0-after-alloca-load.d b/test/unittest/funcs/alloca/tst.alloca0-after-alloca-load.d
> new file mode 100644
> index 000000000000..904f5ce3e0f6
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca0-after-alloca-load.d
> @@ -0,0 +1,28 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Calling alloca(0) is valid and subsequent calls will give the
> + *	      same result, after a previous non-zero alloca, even when one
> + *	      alloca(0) is stored to and loaded from a variable.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = alloca(10);
> +	s = alloca(0);
> +	exit(alloca(0) == s ? 0 : 1);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/tst.alloca0-after-alloca.d b/test/unittest/funcs/alloca/tst.alloca0-after-alloca.d
> new file mode 100644
> index 000000000000..62e79b906c9a
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca0-after-alloca.d
> @@ -0,0 +1,26 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Calling alloca(0) is valid and subsequent calls will give the
> + *	      same result, after a previous non-zero alloca.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = alloca(10);
> +	exit(alloca(0) == alloca(0) ? 0 : 1);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/tst.alloca0-load.d b/test/unittest/funcs/alloca/tst.alloca0-load.d
> new file mode 100644
> index 000000000000..508c2c971731
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca0-load.d
> @@ -0,0 +1,27 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Calling alloca(0) is valid and subsequent calls will give the
> + *	      same result, even when one is stored to and loaded from a
> + *	      variable.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = alloca(0);
> +	exit(alloca(0) == s ? 0 : 1);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/tst.alloca0-values.sh b/test/unittest/funcs/alloca/tst.alloca0-values.sh
> new file mode 100755
> index 000000000000..fce42423843e
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca0-values.sh
> @@ -0,0 +1,34 @@
> +#!/bin/bash
> +#
> +# Oracle Linux DTrace.
> +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> +# Licensed under the Universal Permissive License v 1.0 as shown at
> +# http://oss.oracle.com/licenses/upl.
> +#
> +
> +if [ $# != 1 ]; then
> +	echo expected one argument: '<'dtrace-path'>'
> +	exit 2
> +fi
> +
> +dtrace=$1
> +tmpfile=${tmpdir:-/tmp}/tst.alloca0-values.$$
> +
> +$dtrace $dt_flags -o $tmpfile -s /dev/stdin <<EOT
> +BEGIN {
> +	trace(alloca(0));
> +	trace(s = alloca(0));
> +	trace(s);
> +	trace(alloca(0));
> +
> +	exit(0);
> +}
> +EOT
> +
> +awk '/:BEGIN/ && $2 == $3 && $3 == $4 && $4 == $5 { exit(0); }
> +     /:BEGIN/ { print; exit(1); }' $tmpfile
> +
> +status=$?
> +rm $tmpfile
> +
> +exit $status
> diff --git a/test/unittest/funcs/alloca/tst.alloca0.d b/test/unittest/funcs/alloca/tst.alloca0.d
> new file mode 100644
> index 000000000000..027cb72831a6
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca0.d
> @@ -0,0 +1,25 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Calling alloca(0) is valid and subsequent calls will give the
> + *	      same result.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	exit(alloca(0) == alloca(0) ? 0 : 1);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/tst.ternary.d b/test/unittest/funcs/alloca/tst.ternary.d
> new file mode 100644
> index 000000000000..c871495d1cb0
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.ternary.d
> @@ -0,0 +1,27 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: ternary conditionals with alloca and non-alloca branches
> + *            can be used for things other than variable assignment.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	a = (char *) alloca(1);
> +        trace((a == NULL) ? (char *) 50 : a);
> +        exit(0);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/err.D_ALLOCA_SIZE.big_alloca.d b/test/unittest/funcs/err.D_ALLOCA_SIZE.big_alloca.d
> new file mode 100644
> index 000000000000..6305001df4de
> --- /dev/null
> +++ b/test/unittest/funcs/err.D_ALLOCA_SIZE.big_alloca.d
> @@ -0,0 +1,24 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION:
> + *	Too-large alloca() allocations are a compile-time error.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + *
> + */
> +
> +#pragma D option quiet
> +
> +#pragma D option scratchsize=1024
> +
> +BEGIN
> +{
> +	ptr = alloca(1025);
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/err.D_ALLOCA_SIZE.big_alloca.r b/test/unittest/funcs/err.D_ALLOCA_SIZE.big_alloca.r
> new file mode 100644
> index 000000000000..0822290ff1b5
> --- /dev/null
> +++ b/test/unittest/funcs/err.D_ALLOCA_SIZE.big_alloca.r
> @@ -0,0 +1,2 @@
> +-- @@stderr --
> +dtrace: failed to compile script test/unittest/funcs/err.D_ALLOCA_SIZE.big_alloca.d: [D_ALLOCA_SIZE] line 22: alloca(1025) size larger than scratchsize 1024
> diff --git a/test/unittest/funcs/err.badalloca2.d b/test/unittest/funcs/err.badalloca2.d
> index fc3e2c25143e..72331e9e80f0 100644
> --- a/test/unittest/funcs/err.badalloca2.d
> +++ b/test/unittest/funcs/err.badalloca2.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
>   * Licensed under the Universal Permissive License v 1.0 as shown at
>   * http://oss.oracle.com/licenses/upl.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/funcs/err.badalloca2.r b/test/unittest/funcs/err.badalloca2.r
> index 4392318d2456..65ace8669383 100644
> --- a/test/unittest/funcs/err.badalloca2.r
> +++ b/test/unittest/funcs/err.badalloca2.r
> @@ -1,6 +1,2 @@
> -                   FUNCTION:NAME
> -                          :ERROR 
> -
>  -- @@stderr --
> -dtrace: script 'test/unittest/funcs/err.badalloca2.d' matched 2 probes
> -dtrace: error on enabled probe ID 1 (ID 1: dtrace:::BEGIN): out of scratch space in action #2 at DIF offset 16
> +dtrace: failed to compile script test/unittest/funcs/err.badalloca2.d: line 20: alloca(18446744073709551615) size larger than scratchsize 256
> diff --git a/test/unittest/predicates/err.D_ALLOCA_INCOMPAT.alloca-postinc-instantiation.d b/test/unittest/predicates/err.D_ALLOCA_INCOMPAT.alloca-postinc-instantiation.d
> new file mode 100644
> index 000000000000..f1d2dffbb5ec
> --- /dev/null
> +++ b/test/unittest/predicates/err.D_ALLOCA_INCOMPAT.alloca-postinc-instantiation.d
> @@ -0,0 +1,21 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: alloca assignment to variables in predicates doesn't
> + *	      interfere with alloca/nonalloca compatibility checking.
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN / (new++ == 0) ? bar = alloca(10) : bar /
> +{
> +	trace(new);
> +        bar = &`max_pfn;
> +}
> +
> +ERROR { exit(1); }
> diff --git a/test/unittest/predicates/err.D_ALLOCA_INCOMPAT.alloca-postinc-instantiation.r b/test/unittest/predicates/err.D_ALLOCA_INCOMPAT.alloca-postinc-instantiation.r
> new file mode 100644
> index 000000000000..2bdf1a87f97c
> --- /dev/null
> +++ b/test/unittest/predicates/err.D_ALLOCA_INCOMPAT.alloca-postinc-instantiation.r
> @@ -0,0 +1,2 @@
> +-- @@stderr --
> +dtrace: failed to compile script test/unittest/predicates/err.D_ALLOCA_INCOMPAT.alloca-postinc-instantiation.d: [D_ALLOCA_INCOMPAT] line 15: bar: cannot reuse the same identifier for both alloca and non-alloca allocations
> diff --git a/test/unittest/predicates/tst.alloca-postinc-instantiation.d b/test/unittest/predicates/tst.alloca-postinc-instantiation.d
> new file mode 100644
> index 000000000000..e411713628ef
> --- /dev/null
> +++ b/test/unittest/predicates/tst.alloca-postinc-instantiation.d
> @@ -0,0 +1,46 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: alloca assignment to variables in predicates works and
> + *	      instantiates the variable in the clause body too, just
> + *	      as already happens for postfix increment.  You can store
> + *	      and load from it.
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN / (new++ == 0) ? bar = alloca(10) : bar /
> +{
> +	trace(new);
> +	trace(bar);
> +	b = (int *) ((long) bar + 1 - 1);
> +        *b = 0;
> +        b_value = *b;
> +}
> +
> +BEGIN / new == 0 /
> +{
> +	trace("new is still zero");
> +	exit(1);
> +}
> +
> +BEGIN / b_value == 0 / { exit(0); }
> +
> +BEGIN / b == 0 /
> +{
> +	printf("b stayed zero");
> +	exit(1);
> +}
> +
> +BEGIN
> +{
> +	printf("*b is %x, not zero", b_value);
> +	exit(1);
> +}
> +
> +ERROR { exit(1); }
> -- 
> 2.35.1.261.g8402f930ba.dirty
> 
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list