[DTrace-devel] [PATCH v2 09/17] alloca: deref

Nick Alcock nick.alcock at oracle.com
Mon Mar 14 21:30:17 UTC 2022


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 +++++++
 .../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 ++++++++++++
 47 files changed, 930 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-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 1eae3c381bc1..8c49b0900fd2 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -2039,7 +2039,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;
@@ -2061,6 +2061,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[] = {
@@ -2100,6 +2103,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
 }
@@ -2198,6 +2204,38 @@ dt_cg_check_bounds(dt_irlist_t *dlp, dt_regset_t *drp, int regptr, int basereg,
 	dt_cg_check_fault(yypcb);
 }
 
+/*
+ * 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
@@ -2520,7 +2558,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);
@@ -2550,6 +2588,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 {
@@ -4776,6 +4826,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():
@@ -4787,9 +4839,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;
@@ -4946,7 +5009,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;
@@ -5057,7 +5121,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..2a56fb7549d6
--- /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
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-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..31cfb8f7b177
--- /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
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..ef424aedd5a8
--- /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
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..31cfb8f7b177
--- /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
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..ef424aedd5a8
--- /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
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..31cfb8f7b177
--- /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
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..ef424aedd5a8
--- /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
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..31cfb8f7b177
--- /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
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..ef424aedd5a8
--- /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
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




More information about the DTrace-devel mailing list