[DTrace-devel] [PATCH v2 13/15] Fix data size for value copy in dt_cg_store_var()

Kris Van Hees kris.van.hees at oracle.com
Thu Sep 9 12:15:01 PDT 2021


The size of the data to be copied in dt_cg_store_var() was determined
wrongly.  For strings constants we were copying the size of the string
constant even if that might be larger than the maximum string size.

The offsets for lvars and gvars was also not taking into account the
length prefix to be sotred for each string value.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_cg.c                           | 25 ++++++---------
 libdtrace/dt_ident.c                        |  5 +++
 test/unittest/codegen/tst.str_store_var.d   | 26 ++++++++++++++++
 test/unittest/codegen/tst.str_store_var.r   |  7 +++++
 test/unittest/variables/gvar/tst.str-size.d | 34 +++++++++++++++++++++
 test/unittest/variables/gvar/tst.str-size.r |  1 +
 test/unittest/variables/lvar/tst.str-size.d | 31 +++++++++++++++++++
 test/unittest/variables/lvar/tst.str-size.r |  1 +
 8 files changed, 115 insertions(+), 15 deletions(-)
 create mode 100644 test/unittest/codegen/tst.str_store_var.d
 create mode 100644 test/unittest/codegen/tst.str_store_var.r
 create mode 100644 test/unittest/variables/gvar/tst.str-size.d
 create mode 100644 test/unittest/variables/gvar/tst.str-size.r
 create mode 100644 test/unittest/variables/lvar/tst.str-size.d
 create mode 100644 test/unittest/variables/lvar/tst.str-size.r

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 86031239..60e3e13c 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -2231,7 +2231,8 @@ dt_cg_store_var(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp,
 
 	/* global and local variables (that is, not thread-local) */
 	if (!(idp->di_flags & DT_IDFLG_TLS)) {
-		int reg;
+		int	reg;
+		size_t	size;
 
 		if ((reg = dt_regset_alloc(drp)) == -1)
 			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
@@ -2245,29 +2246,23 @@ dt_cg_store_var(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp,
 
 		/* store by value or by reference */
 		if (src->dn_flags & DT_NF_REF) {
-			size_t	size;
+			size_t		srcsz;
 
 			emit(dlp, BPF_ALU64_IMM(BPF_ADD, reg, idp->di_offset));
 
 			/*
 			 * Determine the amount of data to be copied.  It is
-			 * usually the size of the identifier, except for
-			 * string constants where it is the size of the string
-			 * constant (adjusted for the variable-width length
-			 * prefix).  An assignment of a string constant is a
-			 * store of type 'string' with a RHS of type
-			 * DT_TOK_STRING.
+			 * the lesser of the size of the identifier and the
+			 * size of the data being copied in.
 			 */
-			if (dt_node_is_string(src) &&
-			    src->dn_right->dn_op == DT_TOK_STRING)
-				size = dt_node_type_size(src->dn_right) +
-				       DT_STRLEN_BYTES;
-			else
-				size = idp->di_size;
+			srcsz = dt_node_type_size(src->dn_right);
+			if (dt_node_is_string(src))
+				srcsz += DT_STRLEN_BYTES;
+			size = MIN(srcsz, idp->di_size);
 
 			dt_cg_memcpy(dlp, drp, reg, src->dn_reg, size);
 		} else {
-			size_t	size = idp->di_size;
+			size = idp->di_size;
 
 			assert(size > 0 && size <= 8 &&
 			       (size & (size - 1)) == 0);
diff --git a/libdtrace/dt_ident.c b/libdtrace/dt_ident.c
index d4a6e2a1..2d3d7813 100644
--- a/libdtrace/dt_ident.c
+++ b/libdtrace/dt_ident.c
@@ -1009,8 +1009,13 @@ dt_ident_set_data(dt_ident_t *idp, void *data)
 void
 dt_ident_set_storage(dt_ident_t *idp, uint_t alignment, uint_t size)
 {
+	dtrace_hdl_t	*dtp = yypcb->pcb_hdl;
 	dt_idhash_t	*dhp = idp->di_hash;
 
+	if (idp->di_ctfp == DT_STR_CTFP(dtp) &&
+	    idp->di_type == DT_STR_TYPE(dtp))
+		size += DT_STRLEN_BYTES;
+
 	idp->di_offset = (dhp->dh_nextoff + (alignment - 1)) & ~(alignment - 1);
 	idp->di_size = size;
 
diff --git a/test/unittest/codegen/tst.str_store_var.d b/test/unittest/codegen/tst.str_store_var.d
new file mode 100644
index 00000000..2c64728c
--- /dev/null
+++ b/test/unittest/codegen/tst.str_store_var.d
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#pragma D option rawbytes
+#pragma D option strsize=6
+#pragma D option quiet
+
+string	x;
+
+BEGIN
+{
+	x = "abcdefgh";
+	trace(x);
+	x = "12";
+	trace(x);
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/test/unittest/codegen/tst.str_store_var.r b/test/unittest/codegen/tst.str_store_var.r
new file mode 100644
index 00000000..05932535
--- /dev/null
+++ b/test/unittest/codegen/tst.str_store_var.r
@@ -0,0 +1,7 @@
+
+             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
+         0: 00 06 61 62 63 64 65 66 00                       ..abcdef.
+
+             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
+         0: 00 02 31 32 00 00 00 00 00                       ..12.....
+
diff --git a/test/unittest/variables/gvar/tst.str-size.d b/test/unittest/variables/gvar/tst.str-size.d
new file mode 100644
index 00000000..7fc77518
--- /dev/null
+++ b/test/unittest/variables/gvar/tst.str-size.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: Enough space is allocated for each string variable.
+ *
+ * SECTION: Variables/Scalar Variables
+ */
+
+#pragma D option quiet
+#pragma D option strsize=5
+
+BEGIN
+{
+	x = "abcd";
+	y = "abcd";
+	z = "abcd";
+	exit(0);
+}
+
+END {
+	trace(x);
+	trace(y);
+	trace(z);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/test/unittest/variables/gvar/tst.str-size.r b/test/unittest/variables/gvar/tst.str-size.r
new file mode 100644
index 00000000..0f29a1fe
--- /dev/null
+++ b/test/unittest/variables/gvar/tst.str-size.r
@@ -0,0 +1 @@
+abcdabcdabcd
diff --git a/test/unittest/variables/lvar/tst.str-size.d b/test/unittest/variables/lvar/tst.str-size.d
new file mode 100644
index 00000000..58a6fb3f
--- /dev/null
+++ b/test/unittest/variables/lvar/tst.str-size.d
@@ -0,0 +1,31 @@
+/*
+ * 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: Enough space is allocated for each string variable.
+ *
+ * SECTION: Variables/Scalar Variables
+ */
+
+#pragma D option quiet
+#pragma D option strsize=5
+
+BEGIN
+{
+	this->x = "abcd";
+	this->y = "abcd";
+	this->z = "abcd";
+	trace(this->x);
+	trace(this->y);
+	trace(this->z);
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/test/unittest/variables/lvar/tst.str-size.r b/test/unittest/variables/lvar/tst.str-size.r
new file mode 100644
index 00000000..0f29a1fe
--- /dev/null
+++ b/test/unittest/variables/lvar/tst.str-size.r
@@ -0,0 +1 @@
+abcdabcdabcd
-- 
2.33.0




More information about the DTrace-devel mailing list