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

Kris Van Hees kris.van.hees at oracle.com
Wed Sep 8 14:07:15 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.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_cg.c                         | 30 +++++++++++------------
 test/unittest/codegen/tst.str_store_var.d | 26 ++++++++++++++++++++
 test/unittest/codegen/tst.str_store_var.r |  7 ++++++
 3 files changed, 48 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

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 8a57ca34..0e22fbe1 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,28 @@ 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;
+			dtrace_hdl_t	*dtp = yypcb->pcb_hdl;
+			size_t		srcsz, dstsz;
 
 			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;
+			dstsz = idp->di_size;
+			if (idp->di_ctfp == DT_STR_CTFP(dtp) &&
+			    idp->di_type == DT_STR_TYPE(dtp))
+				dstsz += DT_STRLEN_BYTES;
+			size = MIN(srcsz, dstsz);
 
 			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/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.....
+
-- 
2.33.0




More information about the DTrace-devel mailing list