Skip to content

Commit

Permalink
Fix data size for value copy in dt_cg_store_var()
Browse files Browse the repository at this point in the history
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 stored for each string value.

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Eugene Loh <eugene.loh@oracle.com>
  • Loading branch information
kvanhees committed Sep 9, 2021
1 parent a1ffa3d commit d78ee59
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 15 deletions.
25 changes: 10 additions & 15 deletions libdtrace/dt_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions libdtrace/dt_ident.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
26 changes: 26 additions & 0 deletions test/unittest/codegen/tst.str_store_var.d
Original file line number Diff line number Diff line change
@@ -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);
}
7 changes: 7 additions & 0 deletions test/unittest/codegen/tst.str_store_var.r
Original file line number Diff line number Diff line change
@@ -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.....

34 changes: 34 additions & 0 deletions test/unittest/variables/gvar/tst.str-size.d
Original file line number Diff line number Diff line change
@@ -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);
}
1 change: 1 addition & 0 deletions test/unittest/variables/gvar/tst.str-size.r
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
abcdabcdabcd
31 changes: 31 additions & 0 deletions test/unittest/variables/lvar/tst.str-size.d
Original file line number Diff line number Diff line change
@@ -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);
}
1 change: 1 addition & 0 deletions test/unittest/variables/lvar/tst.str-size.r
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
abcdabcdabcd

0 comments on commit d78ee59

Please sign in to comment.