[DTrace-devel] [PATCH v4 05/10] alloca: deref

Kris Van Hees kris.van.hees at oracle.com
Wed Apr 13 19:39:59 UTC 2022


Reviewed-by: Kris Van Hees <kris.van.hees at oracle.com>

... after moving DT_ISIMM and DT_ISREG to an earlier patch [02/10].

On Tue, Apr 12, 2022 at 11:59:04AM +0100, Nick Alcock wrote:
> From: Kris Van Hees <kris.van.hees at oracle.com>
> 
> Dereferencing an alloca() pointer (identified via its parser taint) is a
> matter of validating that it is suitably bounded and not null, then
> converting it into an actual map_value pointer by adding the scratchmem
> base to it.
> 
> But this is made a bit more complex because bounds validation involves
> not only validation of the address but the access size, and there 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.
> 
> 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.  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_val, 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 dereferencing of allocations both work.
> 
> Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
> Signed-off-by: Nick Alcock <nick.alcock at oracle.com>
> ---
>  libdtrace/dt_cg.c                             | 188 ++++++++++++++++--
>  libdtrace/dt_parser.c                         |  18 +-
>  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  |  30 +++
>  .../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-null-deref-lvalue.d     |  29 +++
>  .../alloca/err.alloca-null-deref-lvalue.r     |   3 +
>  .../funcs/alloca/err.alloca-null-deref.d      |  27 +++
>  .../funcs/alloca/err.alloca-null-deref.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 +
>  .../funcs/alloca/tst.alloca-alignment.d       |  34 ++++
>  .../alloca/tst.alloca-crossing-clauses.d      |  33 +++
>  .../funcs/alloca/tst.alloca-overtainting.sh   |  35 ++++
>  ....alloca-store-load-aliasing-arith-bottom.d |  29 +++
>  ....alloca-store-load-aliasing-arith-bottom.r |   1 +
>  .../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.badalloca.r           |   3 +
>  test/unittest/funcs/err.badalloca2.d          |   3 +-
>  test/unittest/funcs/err.badalloca2.r          |   6 +-
>  ...st.ValidPointer2.d => err.AllocaOverrun.d} |  11 +-
>  test/unittest/pointers/err.AllocaOverrun.r    |   3 +
>  test/unittest/pointers/tst.ValidPointer1.d    |   1 -
>  ...CA_INCOMPAT.alloca-postinc-instantiation.d |  21 ++
>  ...CA_INCOMPAT.alloca-postinc-instantiation.r |   2 +
>  .../tst.alloca-postinc-instantiation.d        |  46 +++++
>  53 files changed, 1069 insertions(+), 34 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-null-deref-lvalue.d
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-null-deref-lvalue.r
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-null-deref.d
>  create mode 100644 test/unittest/funcs/alloca/err.alloca-null-deref.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/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-bottom.d
>  create mode 100644 test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith-bottom.r
>  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/funcs/err.badalloca.r
>  rename test/unittest/pointers/{tst.ValidPointer2.d => err.AllocaOverrun.d} (62%)
>  create mode 100644 test/unittest/pointers/err.AllocaOverrun.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 227536a8a99e..b1b498b30085 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -24,6 +24,9 @@
>  #include <dt_string.h>
>  #include <bpf_asm.h>
>  
> +#define DT_ISIMM	0
> +#define DT_ISREG	1
> +
>  static void dt_cg_node(dt_node_t *, dt_irlist_t *, dt_regset_t *);
>  
>  /*
> @@ -887,6 +890,73 @@ dt_cg_tstring_free(dt_pcb_t *pcb, dt_node_t *dnp)
>  	}
>  }
>  
> +/*
> + * Validate sized access from an alloca pointer value.
> + *
> + * pos + size < top <=> pos < top - size
> + */
> +static void
> +dt_cg_alloca_access_check(dt_irlist_t *dlp, dt_regset_t *drp, int reg,
> +			  int isreg, ssize_t size)
> +{
> +	int	scratchsize = yypcb->pcb_hdl->dt_options[DTRACEOPT_SCRATCHSIZE];
> +	uint_t	lbl_illval = dt_irlist_label(dlp);
> +	uint_t	lbl_base_ok = dt_irlist_label(dlp);
> +	uint_t	lbl_ok = dt_irlist_label(dlp);
> +
> +	dt_regset_xalloc(drp, BPF_REG_0);
> +	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_FP, DT_STK_DCTX));
> +	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_0, DCTX_MST));
> +	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_0, DMST_SCRATCH_TOP));
> +
> +	emit(dlp,  BPF_BRANCH_IMM(BPF_JSLT, reg, 8, lbl_illval));
> +	emit(dlp,  BPF_BRANCH_IMM(BPF_JSGE, reg, scratchsize, lbl_illval));
> +	emit(dlp,  BPF_BRANCH_REG(BPF_JLT, reg, BPF_REG_0, lbl_base_ok));
> +	emitl(dlp, lbl_illval,
> +		   BPF_NOP());
> +	dt_cg_probe_error(yypcb, DTRACEFLT_BADADDR, DT_ISREG, reg);
> +
> +	emitl(dlp, lbl_base_ok,
> +		   BPF_NOP());
> +
> +	if (isreg)
> +		emit(dlp, BPF_ALU64_REG(BPF_SUB, BPF_REG_0, size));
> +	else
> +		emit(dlp, BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, size));
> +
> +	emit(dlp,  BPF_BRANCH_REG(BPF_JLE, reg, BPF_REG_0, lbl_ok));
> +
> +	dt_cg_probe_error(yypcb, DTRACEFLT_BADSIZE, isreg, size);
> +
> +	emitl(dlp, lbl_ok,
> +		   BPF_NOP());
> +	dt_regset_free(drp, BPF_REG_0);
> +}
> +
> +/*
> + * Convert an access-checked alloca pointer value into an actual scratchmem
> + * pointer.
> + */
> +static void
> +dt_cg_alloca_ptr(dt_irlist_t *dlp, dt_regset_t *drp, int dreg, int sreg)
> +{
> +	int	reg = dreg;
> +
> +	if (dreg == sreg) {
> +		if ((reg = dt_regset_alloc(drp)) == -1)
> +			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> +	}
> +
> +	emit(dlp,  BPF_LOAD(BPF_DW, reg, BPF_REG_FP, DT_STK_DCTX));
> +	emit(dlp,  BPF_LOAD(BPF_DW, reg, reg, DCTX_SCRATCHMEM));
> +	emit(dlp,  BPF_ALU64_REG(BPF_ADD, reg, sreg));
> +
> +	if (dreg == sreg) {
> +		emit(dlp, BPF_MOV_REG(dreg, reg));
> +		dt_regset_free(drp, reg);
> +	}
> +}
> +
>  static const uint_t	ldstw[] = {
>  					0,
>  					BPF_B,	BPF_H,	0, BPF_W,
> @@ -922,6 +992,7 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
>  	dt_regset_t		*drp = pcb->pcb_regs;
>  	uint_t			off;
>  	size_t			size;
> +	int			not_null = 0;
>  
>  	/*
>  	 * Special case for aggregations: we store the aggregation id.  We
> @@ -933,9 +1004,24 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
>  		emit(dlp, BPF_MOV_IMM(dnp->dn_reg, dnp->dn_ident->di_id));
>  		size = sizeof(dnp->dn_ident->di_id);
>  	} else {
> -		dt_cg_node(dnp, &pcb->pcb_ir, drp);
> +		dt_cg_node(dnp, dlp, drp);
>  		dt_node_diftype(dtp, dnp, &vtype);
>  		size = vtype.dtdt_size;
> +
> +		/*
> +		 * A DEREF of a REF node does not get resolved in dt_cg_node()
> +		 * because the ref node already holds the pointer.  But for
> +		 * alloca pointers, that will be the offset into scratchmem so
> +		 * we still need to turn it into a real pointer here.
> +		 */
> +		if (dnp->dn_kind == DT_NODE_OP1 &&
> +		    dnp->dn_op == DT_TOK_DEREF && (dnp->dn_flags & DT_NF_REF) &&
> +		    (dnp->dn_child->dn_flags & DT_NF_ALLOCA)) {
> +			dt_cg_alloca_access_check(dlp, drp, dnp->dn_reg,
> +						  DT_ISIMM, size);
> +			dt_cg_alloca_ptr(dlp, drp, dnp->dn_reg, dnp->dn_reg);
> +			not_null = 1;
> +		}
>  	}
>  
>  	if (kind == DTRACEACT_USYM ||
> @@ -974,7 +1060,8 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
>  	} else if (dt_node_is_string(dnp)) {
>  		size_t	strsize = pcb->pcb_hdl->dt_options[DTRACEOPT_STRSIZE];
>  
> -		dt_cg_check_notnull(dlp, drp, dnp->dn_reg);
> +		if (!not_null)
> +			dt_cg_check_notnull(dlp, drp, dnp->dn_reg);
>  
>  		TRACE_REGSET("store_val(): Begin ");
>  		off = dt_rec_add(pcb->pcb_hdl, dt_cg_fill_gap, kind, size + 1,
> @@ -1008,7 +1095,8 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
>  		off = dt_rec_add(dtp, dt_cg_fill_gap, kind, size, 2, pfp, arg);
>  
>  		TRACE_REGSET("store_val(): Begin ");
> -		dt_cg_check_notnull(dlp, drp, dnp->dn_reg);
> +		if (!not_null)
> +			dt_cg_check_notnull(dlp, drp, dnp->dn_reg);
>  
>  		if (dt_regset_xalloc_args(drp) == -1)
>  			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> @@ -1969,7 +2057,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;
> @@ -1991,6 +2079,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[] = {
> @@ -2030,6 +2121,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
>  }
> @@ -2056,9 +2150,10 @@ dt_cg_load_var(dt_node_t *dst, dt_irlist_t *dlp, dt_regset_t *drp)
>  			emit(dlp, BPF_LOAD(BPF_DW, dst->dn_reg, dst->dn_reg, DCTX_GVARS));
>  
>  		/* load the variable value or address */
> -		if (dst->dn_flags & DT_NF_REF)
> +		if (dst->dn_flags & DT_NF_REF) {
> +			assert(!(dst->dn_flags & DT_NF_ALLOCA));
>  			emit(dlp, BPF_ALU64_IMM(BPF_ADD, dst->dn_reg, idp->di_offset));
> -		else {
> +		} else {
>  			size_t	size = dt_node_type_size(dst);
>  
>  			assert(size > 0 && size <= 8 &&
> @@ -2297,7 +2392,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);
> @@ -2312,9 +2407,9 @@ dt_cg_field_set(dt_node_t *src, dt_irlist_t *dlp,
>  static void
>  dt_cg_store(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp, dt_node_t *dst)
>  {
> -	ctf_encoding_t e;
> -	size_t size;
> -	int reg;
> +	ctf_encoding_t	e;
> +	size_t		size;
> +	int		dreg = dst->dn_reg;
>  
>  	/*
>  	 * If we're loading a bit-field, the size of our store is found by
> @@ -2327,21 +2422,44 @@ 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));
> +
> +		if ((dreg = dt_regset_alloc(drp)) == -1)
> +			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> +
> +		dt_cg_alloca_access_check(dlp, drp, dst->dn_reg,
> +					  DT_ISIMM, size);
> +		dt_cg_alloca_ptr(dlp, drp, dreg, dst->dn_reg);
> +	}
> +
>  	if (src->dn_flags & DT_NF_REF)
> -		dt_cg_memcpy(dlp, drp, dst->dn_reg, src->dn_reg, size);
> +		dt_cg_memcpy(dlp, drp, dreg, src->dn_reg, size);
>  	else {
> +		int	sreg;
> +
>  		if (dst->dn_flags & DT_NF_BITFIELD)
> -			reg = dt_cg_field_set(src, dlp, drp, dst);
> +			sreg = dt_cg_field_set(src, dlp, drp, dst);
>  		else
> -			reg = src->dn_reg;
> +			sreg = src->dn_reg;
>  
>  		assert(size > 0 && size <= 8 && (size & (size - 1)) == 0);
>  
> -		emit(dlp, BPF_STORE(ldstw[size], dst->dn_reg, 0, reg));
> +		emit(dlp, BPF_STORE(ldstw[size], dreg, 0, sreg));
>  
> -		if (dst->dn_flags & DT_NF_BITFIELD)
> -			dt_regset_free(drp, reg);
> +		if (sreg != src->dn_reg)
> +			dt_regset_free(drp, sreg);
>  	}
> +
> +	if (dreg != dst->dn_reg)
> +		dt_regset_free(drp, dreg);
>  }
>  
>  /*
> @@ -2603,7 +2721,20 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
>  
>  	TRACE_REGSET("    store_var: Begin");
>  
> -	/* Associative (global or TLS) array */
> +	/*
> +	 * Stores of DT_NF_NONALLOCA nodes into identifiers with DT_IDFLG_ALLOCA
> +	 * set indicate that an identifier has been reused for both alloca and
> +	 * non-alloca purposes.  Block this since it prevents us knowing whether
> +	 * to apply an offset to pointers loaded from this identifier.
> +	 */
> +	if (dnp->dn_flags & DT_NF_ALLOCA && idp->di_flags & DT_IDFLG_NONALLOCA) {
> +		xyerror(D_ALLOCA_INCOMPAT, "%s: cannot reuse the "
> +			"same identifier for both alloca and "
> +			"non-alloca allocations\n",
> +			idp->di_name);
> +	}
> +
> +	/* Associative (global or TLS) array.  Cannot be in alloca space.  */
>  	if (idp->di_kind == DT_IDENT_ARRAY) {
>  		dt_cg_arglist(idp, dnp->dn_left->dn_args, dlp, drp);
>  
> @@ -4675,6 +4806,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():
> @@ -4686,9 +4819,22 @@ 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_alloca_access_check(dlp, drp, dnp->dn_reg,
> +							  DT_ISIMM, size);
> +				dt_cg_alloca_ptr(dlp, drp, dnp->dn_reg,
> +						 dnp->dn_reg);
> +			}
>  
>  			/* 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;
> @@ -4845,7 +4991,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;
> @@ -4956,7 +5103,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/libdtrace/dt_parser.c b/libdtrace/dt_parser.c
> index b8f37d8d6b17..e850cd55a65e 100644
> --- a/libdtrace/dt_parser.c
> +++ b/libdtrace/dt_parser.c
> @@ -3153,6 +3153,10 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
>  
>  		if (cp->dn_flags & DT_NF_ALLOCA)
>  			dt_cook_taint_alloca(dnp, NULL, cp);
> +		else if (cp->dn_kind == DT_NODE_OP1 &&
> +			 cp->dn_op == DT_TOK_DEREF &&
> +			 (cp->dn_child->dn_flags & DT_NF_ALLOCA))
> +			dt_cook_taint_alloca(dnp, NULL, cp->dn_child);
>  		break;
>  
>  	case DT_TOK_SIZEOF:
> @@ -3778,9 +3782,14 @@ asgn_common:
>  		if (lp->dn_kind == DT_NODE_VAR)
>  			lp_idp = lp->dn_ident;
>  
> +		/*
> +		 * Transfer alloca taint.  Stores of non-alloca, non-literal-0
> +		 * values turn on DT_IDFLG_NONALLOCA to prevent this identifier
> +		 * from being used for alloca storage anywhere in the program.
> +		 */
>  		if (rp->dn_flags & DT_NF_ALLOCA)
>  			dt_cook_taint_alloca(lp, lp_idp, rp);
> -		else if (lp_idp)
> +		else if (lp_idp && !(rp->dn_kind == DT_NODE_INT && rp->dn_value == 0))
>  			lp_idp->di_flags |= DT_IDFLG_NONALLOCA;
>  
>  		dt_node_type_propagate(lp, dnp); /* see K&R[A7.17] */
> @@ -4022,9 +4031,14 @@ asgn_common:
>  		dnp->dn_args = rp;
>  		dnp->dn_list = NULL;
>  
> +		/*
> +		 * Transfer alloca taint.  Stores of non-alloca, non-literal-0
> +		 * values turn on DT_IDFLG_NONALLOCA to prevent this identifier
> +		 * from being used for alloca storage anywhere in the program.
> +		 */
>  		if (dnp->dn_args->dn_flags & DT_NF_ALLOCA)
>  			dt_cook_taint_alloca(dnp, idp, dnp->dn_args);
> -		else
> +		else if (dnp->dn_kind != DT_NODE_INT || dnp->dn_value != 0)
>  			idp->di_flags |= DT_IDFLG_NONALLOCA;
>  
>  		dt_node_free(lp);
> 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..fe9e274985d1
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash.d
> @@ -0,0 +1,30 @@
> +/*
> + * 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.
> + *            You can't fake it out by assigning NULL in between.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	a = (char *) alloca(1);
> +}
> +
> +BEGIN
> +{
> +	b = (char *) &`max_pfn;
> +        a = NULL;
> +        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..ed642dc71f27
> --- /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 23: 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..187543b63023
> --- /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 address ({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-null-deref-lvalue.d b/test/unittest/funcs/alloca/err.alloca-null-deref-lvalue.d
> new file mode 100644
> index 000000000000..97d13f12a482
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-null-deref-lvalue.d
> @@ -0,0 +1,29 @@
> +/*
> + * 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: You can't dereference a nullified alloca pointer via an lvalue,
> + *            even if the resulting address is merely almost null.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +#pragma D option scratchsize=51
> +
> +BEGIN
> +{
> +	s = (char *) alloca(10);
> +	s = NULL;
> +        s[50] = 4;
> +	exit(0);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/err.alloca-null-deref-lvalue.r b/test/unittest/funcs/alloca/err.alloca-null-deref-lvalue.r
> new file mode 100644
> index 000000000000..187543b63023
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-null-deref-lvalue.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-null-deref.d b/test/unittest/funcs/alloca/err.alloca-null-deref.d
> new file mode 100644
> index 000000000000..77ee730651cd
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-null-deref.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: You can't dereference a nullified alloca pointer.
> + *
> + * SECTION: Actions and Subroutines/alloca()
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	s = (char *) alloca(10);
> +	s = NULL;
> +        *s = 4;
> +	exit(0);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/err.alloca-null-deref.r b/test/unittest/funcs/alloca/err.alloca-null-deref.r
> new file mode 100644
> index 000000000000..187543b63023
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/err.alloca-null-deref.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-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..187543b63023
> --- /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 address ({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/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-bottom.d b/test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith-bottom.d
> new file mode 100644
> index 000000000000..b6b2b737ea2f
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith-bottom.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: You can still use a pointer to alloca'ed memory after it has been
> + *	      modified such that it no longer points there, as long as the
> + *	      access ends up dereferencing alloca'd memory.
> + *
> + * 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);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith-bottom.r b/test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith-bottom.r
> new file mode 100644
> index 000000000000..8b137891791f
> --- /dev/null
> +++ b/test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith-bottom.r
> @@ -0,0 +1 @@
> +
> 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.badalloca.r b/test/unittest/funcs/err.badalloca.r
> new file mode 100644
> index 000000000000..ca6c894991bd
> --- /dev/null
> +++ b/test/unittest/funcs/err.badalloca.r
> @@ -0,0 +1,3 @@
> +
> +-- @@stderr --
> +dtrace: error on enabled probe ID 4 (ID 113831: profile:::tick-1): invalid address ({ptr}) in action #1 at BPF pc NNN
> 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/pointers/tst.ValidPointer2.d b/test/unittest/pointers/err.AllocaOverrun.d
> similarity index 62%
> rename from test/unittest/pointers/tst.ValidPointer2.d
> rename to test/unittest/pointers/err.AllocaOverrun.d
> index ca8c0dcf7578..16654e0ba030 100644
> --- a/test/unittest/pointers/tst.ValidPointer2.d
> +++ b/test/unittest/pointers/err.AllocaOverrun.d
> @@ -4,10 +4,12 @@
>   * Licensed under the Universal Permissive License v 1.0 as shown at
>   * http://oss.oracle.com/licenses/upl.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
> - * ASSERTION: Demonstrating valid memory access.
> + * ASSERTION: Demonstrating invalid memory access.
> + *            (Solaris never implemented bounds checking, so accesses, even
> + *            writes, beyond the alloca()ed region but within scratch space
> + *            were expected to succeed.  They obviously should not.)
>   *
>   * SECTION: Pointers and Arrays/Pointers and Addresses
>   *
> @@ -27,3 +29,8 @@ BEGIN
>  
>  	exit(0);
>  }
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/pointers/err.AllocaOverrun.r b/test/unittest/pointers/err.AllocaOverrun.r
> new file mode 100644
> index 000000000000..187543b63023
> --- /dev/null
> +++ b/test/unittest/pointers/err.AllocaOverrun.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/pointers/tst.ValidPointer1.d b/test/unittest/pointers/tst.ValidPointer1.d
> index 95a2baa7250e..9dd3fdf473ba 100644
> --- a/test/unittest/pointers/tst.ValidPointer1.d
> +++ b/test/unittest/pointers/tst.ValidPointer1.d
> @@ -4,7 +4,6 @@
>   * Licensed under the Universal Permissive License v 1.0 as shown at
>   * http://oss.oracle.com/licenses/upl.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION: Demonstrating valid memory access.
> 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



More information about the DTrace-devel mailing list