[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