[DTrace-devel] [PATCH 12/14] Add support for NULL strings

eugene.loh at oracle.com eugene.loh at oracle.com
Tue May 2 03:47:20 UTC 2023


From: Eugene Loh <eugene.loh at oracle.com>

In C, strings are (char*), and it is possible to have a NULL pointer.

In D, strings have fixed length strsize.  There may still be NULL
pointers -- say, as inputs to strtok() or as outputs from unsuccessful
strchr() (and other) functions.

Such NULL pointers are not a problem for storing strings as dynamic
variables (thread-local variables or associative arrays), since storing
0 clears a dynamic element and reading a cleared element means 0.

Static (global and local) variables are a different story.  Each
string has strsize bytes allocated for it, and every possible string
value is legal:  bytes up to the first NUL are part of the string
and subsequent bytes are ignored.  There is no value that represents
a NULL string.

Specifically, there is an important semantic difference between NULL
and empty strings.  The former are NULL pointers, while the latter are
strings that simply start with the NUL terminating char.

Add code to handle store and load of NULL-pointer strings to and from
global and local variables.

Specifically, define a byte string DT_NULL_STRING whose first byte is
0x00 but with extra nonzero bytes to distinguish between empty and NULL
strings.  An empty string stored as a static variable will have its
first bytes all zero.  A NULL string will have its first bytes be
DT_NULL_STRING.  That is, both will have initial byte 0, and then we
have to go further to distinguish the two cases.

We require strsize >= sizeof(DT_NULL_STRING), which is reasonable.

Note that comparisons between NULL and empty strings should work the
same way as between NULL strings and any other non-NULL strings.  Note
that Solaris and legacy DTrace on Linux incorrectly treated comparisons
between NULL and empty strings as between equal values.

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 libdtrace/dt_cg.c                             | 84 +++++++++++++++++--
 libdtrace/dt_impl.h                           | 23 +++++
 libdtrace/dt_options.c                        |  5 ++
 .../unittest/codegen/err.deref_string-assoc.d | 30 +++++++
 .../unittest/codegen/err.deref_string-assoc.r |  3 +
 .../codegen/err.deref_string-assoc.r.p        |  6 ++
 test/unittest/codegen/err.deref_string-gvar.d | 30 +++++++
 test/unittest/codegen/err.deref_string-gvar.r |  3 +
 .../codegen/err.deref_string-gvar.r.p         |  6 ++
 test/unittest/codegen/err.deref_string-lvar.d | 30 +++++++
 test/unittest/codegen/err.deref_string-lvar.r |  3 +
 .../codegen/err.deref_string-lvar.r.p         |  6 ++
 test/unittest/codegen/err.deref_string-tvar.d | 30 +++++++
 test/unittest/codegen/err.deref_string-tvar.r |  3 +
 .../codegen/err.deref_string-tvar.r.p         |  6 ++
 .../tst.str_comparison-basic-with-NULL.d      | 30 ++++++-
 test/unittest/options/err.strsize-min.d       | 13 +++
 test/unittest/options/err.strsize-min.r       |  2 +
 test/unittest/options/tst.strsize-min.d       | 13 +++
 test/unittest/options/tst.strsize-min.r       |  5 ++
 test/unittest/vars/tst.nullassign.d           | 21 +++--
 21 files changed, 331 insertions(+), 21 deletions(-)
 create mode 100644 test/unittest/codegen/err.deref_string-assoc.d
 create mode 100644 test/unittest/codegen/err.deref_string-assoc.r
 create mode 100755 test/unittest/codegen/err.deref_string-assoc.r.p
 create mode 100644 test/unittest/codegen/err.deref_string-gvar.d
 create mode 100644 test/unittest/codegen/err.deref_string-gvar.r
 create mode 100755 test/unittest/codegen/err.deref_string-gvar.r.p
 create mode 100644 test/unittest/codegen/err.deref_string-lvar.d
 create mode 100644 test/unittest/codegen/err.deref_string-lvar.r
 create mode 100755 test/unittest/codegen/err.deref_string-lvar.r.p
 create mode 100644 test/unittest/codegen/err.deref_string-tvar.d
 create mode 100644 test/unittest/codegen/err.deref_string-tvar.r
 create mode 100755 test/unittest/codegen/err.deref_string-tvar.r.p
 create mode 100644 test/unittest/options/err.strsize-min.d
 create mode 100644 test/unittest/options/err.strsize-min.r
 create mode 100644 test/unittest/options/tst.strsize-min.d
 create mode 100644 test/unittest/options/tst.strsize-min.r

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 76614747..3c0a4a81 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -2614,7 +2614,32 @@ 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 (dt_node_is_string(dst)) {
+			/*
+			 * Strings are a special case of by-reference.  If we have
+			 * a NULL string, we want to set the pointer to 0.
+			 */
+			size_t	size = sizeof(DT_NULL_STRING);
+			int	reg;
+			uint_t	L1 = dt_irlist_label(dlp);
+			uint_t	L2 = dt_irlist_label(dlp);
+
+			assert(dst->dn_flags & DT_NF_REF);
+			assert(size > 0 && size <= 8 &&
+			       (size & (size - 1)) == 0);
+
+			if ((reg = dt_regset_alloc(drp)) == -1)
+				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+			emit(dlp,  BPF_LOAD(ldstw[size], reg, dst->dn_reg, idp->di_offset));
+			emit(dlp,  BPF_BRANCH_IMM(BPF_JNE, reg, DT_NULL_STRING, L1));
+			emit(dlp,  BPF_MOV_IMM(dst->dn_reg, 0));
+			emit(dlp,  BPF_JUMP(L2));
+			emitl(dlp, L1,
+				   BPF_ALU64_IMM(BPF_ADD, dst->dn_reg, idp->di_offset));
+			emitl(dlp, L2,
+				   BPF_NOP());
+			dt_regset_free(drp, reg);
+		} else 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 {
@@ -3252,15 +3277,58 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
 			emit(dlp, BPF_ALU64_IMM(BPF_ADD, reg, idp->di_offset));
 
 			/*
-			 * Determine the amount of data to be copied.  It is
-			 * the lesser of the size of the identifier and the
-			 * size of the data being copied in.
+			 * Handle storing NULL to a string separately:
+			 * xxx left-hand side is a string
+			 *       dt_node_is_string(dnp)
+			 *       dt_node_is_string(dnp->dn_left)
+			 * xxx right-hand side is an integer constant
+			 *       dt_node_is_integer(dnp->dn_right)
+			 *       dnp->dn_right->dn_kind == DT_NODE_INT
+			 *     by the way:
+			 *       srcsz = dt_node_type_size(dnp->dn_right) could be 1, 2, 4, or 8
+			 *
+			 * The parser has already ensured the rhs is 0.  In
+			 * dt_cook_op2() for DT_TOK_ASGN, it checks dt_node_is_argcompat().
+			 * Since rhs is not string compatible (string or char*), we move on
+			 * to dt_node_is_ptrcompat(lp, rp, NULL, NULL).  There we see a test
+			 * if (rp_is_int && (rp->dn_kind != DT_NODE_INT || rp->dn_value != 0))
+			 * 	return 0; // fail if rp is an integer that is not 0 constant
 			 */
-			srcsz = dt_node_type_size(dnp->dn_right);
-			size = MIN(srcsz, idp->di_size);
+			assert(dt_node_is_string(dnp) == dt_node_is_string(dnp->dn_left));
+			assert(idp->di_size == dt_node_type_size(dnp->dn_left));
+			assert(dt_node_is_integer(dnp->dn_right) == (dnp->dn_right->dn_kind == DT_NODE_INT));
+			if (dt_node_is_string(dnp) && dt_node_is_integer(dnp->dn_right)) {
+				assert(dnp->dn_right->dn_value == 0);
 
-			dt_cg_check_ptr_arg(dlp, drp, dnp->dn_right, NULL);
-			dt_cg_memcpy(dlp, drp, reg, dnp->dn_reg, size);
+				size = sizeof(DT_NULL_STRING);
+				assert(size > 0 && size <= 8 &&
+				       (size & (size - 1)) == 0);
+
+				emit(dlp, BPF_STORE_IMM(ldstw[size], reg, 0, DT_NULL_STRING));
+			} else {
+				/*
+				 * If the lhs is a string, start by zeroing out the first bytes.
+				 * FIXME: need to do the right thing if rhs is a NULL string
+				 */
+				if (dt_node_is_string(dnp)) {
+					size = sizeof(DT_NULL_STRING);
+					assert(size > 0 && size <= 8 &&
+					       (size & (size - 1)) == 0);
+
+					emit(dlp, BPF_STORE_IMM(ldstw[size], reg, 0, 0));
+				}
+
+				/*
+				 * Determine the amount of data to be copied.  It is
+				 * the lesser of the size of the identifier and the
+				 * size of the data being copied in.
+				 */
+				srcsz = dt_node_type_size(dnp->dn_right);
+				size = MIN(srcsz, idp->di_size);
+
+				dt_cg_check_ptr_arg(dlp, drp, dnp->dn_right, NULL);
+				dt_cg_memcpy(dlp, drp, reg, dnp->dn_reg, size);
+			}
 
 			/*
 			 * Since strings are passed by value, we need to force
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index e240cef0..e4665dd3 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -58,6 +58,29 @@ extern "C" {
 # define __stringify(x)          __stringify_(x)
 #endif
 
+/*
+ * Note that string = "" is an empty string:  its first byte is 0x00.
+ * To store a NULL string -- basically, (char*)0 --  make the first byte 0x00.
+ * Then, to distinguish between empty and NULL strings, follow the initial
+ * byte either with 0s (empty string) or a special set of nonzero bytes.
+ * That is, to designate a NULL string, make the initial bytes DT_NULL_STRING,
+ * where:
+ *   - the initial byte is 0x00
+ *   - subsequent bytes are nonzero
+ *   - the width is at least 2 bytes
+ *      (that is, there is at least one nonzero byte)
+ *   - the width is at most 4 bytes
+ *      (so that DT_NULL_STRING can be used as an IMM)
+ *   - the highest bit is 0
+ *      (so that if DT_NULL_STRING is an IMM, it won't get sign extended)
+ * Finally, note that strsize must be large enough to hold DT_NULL_STRING.
+ */
+#ifdef _BIG_ENDIAN
+#define DT_NULL_STRING ((short)0x007f)
+#else
+#define DT_NULL_STRING ((short)0x7f00)
+#endif
+
 struct dt_module;		/* see below */
 struct dt_pfdict;		/* see <dt_printf.h> */
 struct dt_arg;			/* see below */
diff --git a/libdtrace/dt_options.c b/libdtrace/dt_options.c
index d25b2ac9..6d2dd52e 100644
--- a/libdtrace/dt_options.c
+++ b/libdtrace/dt_options.c
@@ -878,6 +878,11 @@ dt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
 	if (dt_opt_size(dtp, arg, option) != 0)
 		return -1; /* dt_errno is set for us */
 
+	if (dtp->dt_options[option] < sizeof(DT_NULL_STRING)) {
+		dtp->dt_options[option] = val;
+		return dt_set_errno(dtp, EDT_BADOPTVAL);
+	}
+
 	if (dtp->dt_options[option] > UINT_MAX) {
 		dtp->dt_options[option] = val;
 		return dt_set_errno(dtp, EOVERFLOW);
diff --git a/test/unittest/codegen/err.deref_string-assoc.d b/test/unittest/codegen/err.deref_string-assoc.d
new file mode 100644
index 00000000..04acf1b5
--- /dev/null
+++ b/test/unittest/codegen/err.deref_string-assoc.d
@@ -0,0 +1,30 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	s[1234] = "ABCDEFG";
+	trace(s[1234][1]);
+}
+
+BEGIN
+{
+	s[1234] = NULL;
+	trace(s[1234][1]);
+}
+
+BEGIN
+{
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/test/unittest/codegen/err.deref_string-assoc.r b/test/unittest/codegen/err.deref_string-assoc.r
new file mode 100644
index 00000000..08277992
--- /dev/null
+++ b/test/unittest/codegen/err.deref_string-assoc.r
@@ -0,0 +1,3 @@
+66
+-- @@stderr --
+dtrace: error on enabled probe ID 4 (ID 1: dtrace:::BEGIN): invalid address (1) in action #2 at BPF pc NNN
diff --git a/test/unittest/codegen/err.deref_string-assoc.r.p b/test/unittest/codegen/err.deref_string-assoc.r.p
new file mode 100755
index 00000000..68ebc99b
--- /dev/null
+++ b/test/unittest/codegen/err.deref_string-assoc.r.p
@@ -0,0 +1,6 @@
+#!/usr/bin/sed -f
+
+# runtest.sh looks for "0x" to filter out pointer values.
+# Strip the 0x so that the illegal address will not be filtered out;
+# we want the address to be checked.
+s/0x//
diff --git a/test/unittest/codegen/err.deref_string-gvar.d b/test/unittest/codegen/err.deref_string-gvar.d
new file mode 100644
index 00000000..e2beeaed
--- /dev/null
+++ b/test/unittest/codegen/err.deref_string-gvar.d
@@ -0,0 +1,30 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	s = "ABCDEFG";
+	trace(s[1]);
+}
+
+BEGIN
+{
+	s = NULL;
+	trace(s[1]);
+}
+
+BEGIN
+{
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/test/unittest/codegen/err.deref_string-gvar.r b/test/unittest/codegen/err.deref_string-gvar.r
new file mode 100644
index 00000000..08277992
--- /dev/null
+++ b/test/unittest/codegen/err.deref_string-gvar.r
@@ -0,0 +1,3 @@
+66
+-- @@stderr --
+dtrace: error on enabled probe ID 4 (ID 1: dtrace:::BEGIN): invalid address (1) in action #2 at BPF pc NNN
diff --git a/test/unittest/codegen/err.deref_string-gvar.r.p b/test/unittest/codegen/err.deref_string-gvar.r.p
new file mode 100755
index 00000000..68ebc99b
--- /dev/null
+++ b/test/unittest/codegen/err.deref_string-gvar.r.p
@@ -0,0 +1,6 @@
+#!/usr/bin/sed -f
+
+# runtest.sh looks for "0x" to filter out pointer values.
+# Strip the 0x so that the illegal address will not be filtered out;
+# we want the address to be checked.
+s/0x//
diff --git a/test/unittest/codegen/err.deref_string-lvar.d b/test/unittest/codegen/err.deref_string-lvar.d
new file mode 100644
index 00000000..36525065
--- /dev/null
+++ b/test/unittest/codegen/err.deref_string-lvar.d
@@ -0,0 +1,30 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	this->s = "ABCDEFG";
+	trace(this->s[1]);
+}
+
+BEGIN
+{
+	this->s = NULL;
+	trace(this->s[1]);
+}
+
+BEGIN
+{
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/test/unittest/codegen/err.deref_string-lvar.r b/test/unittest/codegen/err.deref_string-lvar.r
new file mode 100644
index 00000000..08277992
--- /dev/null
+++ b/test/unittest/codegen/err.deref_string-lvar.r
@@ -0,0 +1,3 @@
+66
+-- @@stderr --
+dtrace: error on enabled probe ID 4 (ID 1: dtrace:::BEGIN): invalid address (1) in action #2 at BPF pc NNN
diff --git a/test/unittest/codegen/err.deref_string-lvar.r.p b/test/unittest/codegen/err.deref_string-lvar.r.p
new file mode 100755
index 00000000..68ebc99b
--- /dev/null
+++ b/test/unittest/codegen/err.deref_string-lvar.r.p
@@ -0,0 +1,6 @@
+#!/usr/bin/sed -f
+
+# runtest.sh looks for "0x" to filter out pointer values.
+# Strip the 0x so that the illegal address will not be filtered out;
+# we want the address to be checked.
+s/0x//
diff --git a/test/unittest/codegen/err.deref_string-tvar.d b/test/unittest/codegen/err.deref_string-tvar.d
new file mode 100644
index 00000000..d7df8bc1
--- /dev/null
+++ b/test/unittest/codegen/err.deref_string-tvar.d
@@ -0,0 +1,30 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	self->s = "ABCDEFG";
+	trace(self->s[1]);
+}
+
+BEGIN
+{
+	self->s = NULL;
+	trace(self->s[1]);
+}
+
+BEGIN
+{
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/test/unittest/codegen/err.deref_string-tvar.r b/test/unittest/codegen/err.deref_string-tvar.r
new file mode 100644
index 00000000..08277992
--- /dev/null
+++ b/test/unittest/codegen/err.deref_string-tvar.r
@@ -0,0 +1,3 @@
+66
+-- @@stderr --
+dtrace: error on enabled probe ID 4 (ID 1: dtrace:::BEGIN): invalid address (1) in action #2 at BPF pc NNN
diff --git a/test/unittest/codegen/err.deref_string-tvar.r.p b/test/unittest/codegen/err.deref_string-tvar.r.p
new file mode 100755
index 00000000..68ebc99b
--- /dev/null
+++ b/test/unittest/codegen/err.deref_string-tvar.r.p
@@ -0,0 +1,6 @@
+#!/usr/bin/sed -f
+
+# runtest.sh looks for "0x" to filter out pointer values.
+# Strip the 0x so that the illegal address will not be filtered out;
+# we want the address to be checked.
+s/0x//
diff --git a/test/unittest/operators/tst.str_comparison-basic-with-NULL.d b/test/unittest/operators/tst.str_comparison-basic-with-NULL.d
index 64bb0579..7cfcd67c 100644
--- a/test/unittest/operators/tst.str_comparison-basic-with-NULL.d
+++ b/test/unittest/operators/tst.str_comparison-basic-with-NULL.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2023, 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: No support for NULL strings yet */
 
 /*
  * ASSERTION: String comparisons work.
@@ -22,6 +21,8 @@ BEGIN
 	s2 = "jklmnopqr";
 	s3 = "stuvwxyz!";
 
+	/* compare normal strings, where lhs < rhs */
+
 	nerrors += (s1 <= s2 ? 0 : 1);
 	nerrors += (s1 <  s2 ? 0 : 1);
 	nerrors += (s1 == s2 ? 1 : 0);
@@ -29,6 +30,8 @@ BEGIN
 	nerrors += (s1 >= s2 ? 1 : 0);
 	nerrors += (s1 >  s2 ? 1 : 0);
 
+	/* compare normal strings, where lhs == rhs */
+
 	nerrors += (s2 <= s2 ? 0 : 1);
 	nerrors += (s2 <  s2 ? 1 : 0);
 	nerrors += (s2 == s2 ? 0 : 1);
@@ -36,6 +39,8 @@ BEGIN
 	nerrors += (s2 >= s2 ? 0 : 1);
 	nerrors += (s2 >  s2 ? 1 : 0);
 
+	/* compare normal strings, where lhs > rhs */
+
 	nerrors += (s3 <= s2 ? 1 : 0);
 	nerrors += (s3 <  s2 ? 1 : 0);
 	nerrors += (s3 == s2 ? 1 : 0);
@@ -43,6 +48,8 @@ BEGIN
 	nerrors += (s3 >= s2 ? 0 : 1);
 	nerrors += (s3 >  s2 ? 0 : 1);
 
+	/* compare strings, where one is NULL */
+
 	s2 = NULL;
 	nerrors += (s3 <= s2 ? 1 : 0);
 	nerrors += (s3 <  s2 ? 1 : 0);
@@ -58,6 +65,25 @@ BEGIN
 	nerrors += (s2 >= s3 ? 1 : 0);
 	nerrors += (s2 >  s3 ? 1 : 0);
 
+	/* compare NULL and empty strings */
+
+	s3 = "";
+	nerrors += (s3 <= s2 ? 1 : 0);
+	nerrors += (s3 <  s2 ? 1 : 0);
+	nerrors += (s3 == s2 ? 1 : 0);
+	nerrors += (s3 != s2 ? 0 : 1);
+	nerrors += (s3 >= s2 ? 0 : 0);
+	nerrors += (s3 >  s2 ? 0 : 0);
+
+	nerrors += (s2 <= s3 ? 0 : 1);
+	nerrors += (s2 <  s3 ? 0 : 1);
+	nerrors += (s2 == s3 ? 1 : 0);
+	nerrors += (s2 != s3 ? 0 : 1);
+	nerrors += (s2 >= s3 ? 1 : 0);
+	nerrors += (s2 >  s3 ? 1 : 0);
+
+	/* compare two NULL strings */
+
 	s3 = NULL;
 	nerrors += (s2 <= s3 ? 0 : 1);
 	nerrors += (s2 <  s3 ? 1 : 0);
diff --git a/test/unittest/options/err.strsize-min.d b/test/unittest/options/err.strsize-min.d
new file mode 100644
index 00000000..a2aeca0f
--- /dev/null
+++ b/test/unittest/options/err.strsize-min.d
@@ -0,0 +1,13 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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.
+ */
+
+/* @@runtest-opts: -xstrsize=1 */
+
+BEGIN
+{
+	exit(0);
+}
diff --git a/test/unittest/options/err.strsize-min.r b/test/unittest/options/err.strsize-min.r
new file mode 100644
index 00000000..00d527e0
--- /dev/null
+++ b/test/unittest/options/err.strsize-min.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to set -x strsize: Invalid value for specified option
diff --git a/test/unittest/options/tst.strsize-min.d b/test/unittest/options/tst.strsize-min.d
new file mode 100644
index 00000000..9fd902b1
--- /dev/null
+++ b/test/unittest/options/tst.strsize-min.d
@@ -0,0 +1,13 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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.
+ */
+
+/* @@runtest-opts: -xstrsize=2 */
+
+BEGIN
+{
+	exit(0);
+}
diff --git a/test/unittest/options/tst.strsize-min.r b/test/unittest/options/tst.strsize-min.r
new file mode 100644
index 00000000..1a72a90f
--- /dev/null
+++ b/test/unittest/options/tst.strsize-min.r
@@ -0,0 +1,5 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+
+-- @@stderr --
+dtrace: script 'test/unittest/options/tst.strsize-min.d' matched 1 probe
diff --git a/test/unittest/vars/tst.nullassign.d b/test/unittest/vars/tst.nullassign.d
index 1de59a43..44ccc30e 100644
--- a/test/unittest/vars/tst.nullassign.d
+++ b/test/unittest/vars/tst.nullassign.d
@@ -1,25 +1,24 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2023, 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 */
 
 #pragma D option quiet
 
 BEGIN
 {
-	die = "Die";
-	tap = ", SystemTap, ";
-	the = "The";
+	lv = "Live";
+	dt = ", DTrace, ";
+	ps = "Prosper";
 }
 
 BEGIN
 {
-	phrase = strjoin(die, tap);
-	phrase = strjoin(phrase, die);
-	expected = "Die, SystemTap, Die";
+	phrase = strjoin(lv, dt);
+	phrase = strjoin(phrase, lv);
+	expected = "Live, DTrace, Live";
 }
 
 BEGIN
@@ -31,13 +30,13 @@ BEGIN
 
 BEGIN
 {
-	this->phrase = strjoin(the, tap);
+	this->phrase = strjoin(ps, dt);
 }
 
 BEGIN
 {
-	this->phrase = strjoin(this->phrase, the);
-	expected = "The, SystemTap, The";
+	this->phrase = strjoin(this->phrase, ps);
+	expected = "Prosper, DTrace, Prosper";
 }
 
 BEGIN
-- 
2.18.4




More information about the DTrace-devel mailing list