[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