Skip to content

Commit

Permalink
Fix length stored by strjoin() and optimise the implementation
Browse files Browse the repository at this point in the history
The length that was stored for strjoin() was the sum of the lengths of
the two argument strings.  That means that if the sum was larger than
STRSIZE, we would still store that larger length even though the string
itself got truncated.

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Eugene Loh <eugene.loh@oracle.com>
  • Loading branch information
kvanhees committed Nov 20, 2021
1 parent cf1e9df commit ace8cbf
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 27 deletions.
61 changes: 34 additions & 27 deletions bpf/strjoin.S
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,46 @@ dt_strjoin:
mov %r7, %r2 /* %r7 = s1 */
mov %r8, %r3 /* %r8 = s2 */

mov %r1, %r7
call dt_strlen
mov %r6, %r0 /* len = dt_strlen(s1) */
add %r7, DT_STRLEN_BYTES /* s1 += 2 */

mov %r1, %r8
call dt_strlen
add %r6, %r0 /* len += dt_strlen(s2) */
add %r8, DT_STRLEN_BYTES /* s2 += 2 */

mov %r1, %r6
mov %r2, %r9
call dt_strlen_store /* dt_strlen_store(len, dst) */
add %r9, DT_STRLEN_BYTES /* dst += 2 */

lddw %r6, STRSZ
add %r6, 1
and %r6, 0xffffffff /* len = (STRSZ + 1) & 0xffffffff */
add %r6, 1 /* cnt = STRSZ + 1 */

mov %r1, %r9
add %r1, DT_STRLEN_BYTES /* dst is in %r1 already */
mov %r2, %r6
mov %r3, %r7
call BPF_FUNC_probe_read_str /* cnt = bpf_probe_read_str(dst, len s1) */
jslt %r0, 0, .L1 /* if (cnt < 0) goto .L1 */
jslt %r0, 1, .L2 /* if (cnt < 1) goto .L2 */
sub %r0, 1 /* cnt-- */
add %r9, %r0 /* dst += cnt */
sub %r6, %r0 /* len -= cnt */
.L2:
add %r3, DT_STRLEN_BYTES
call BPF_FUNC_probe_read_str /*
* rc = probe_read_str(
* &dst[DT_STRLEN_BYTES],
* cnt,
* &s1[DT_STRLEN_BYTES]);
*/
jsle %r0, 0, .Lexit /* if (rc s<= 0) goto .Lexit; */
mov %r7, %r0 /* len = rc */
jeq %r7, %r6, .Lset_len /* if (len == cnt) goto .Lset_len; */
sub %r7, 1 /* len-- */

mov %r1, %r9
add %r1, DT_STRLEN_BYTES
add %r1, %r7
mov %r2, %r6
sub %r2, %r7
mov %r3, %r8
call BPF_FUNC_probe_read_str /* bpf_probe_read_str(dst, len, s2 */
.L1:
add %r3, DT_STRLEN_BYTES
call BPF_FUNC_probe_read_str /*
* rc = probe_read_str(
* &dst[DT_STRLEN_BYTES + len],
* cnt - len,
* &s2[DT_STRLEN_BYTES]);
*/
jsle %r0, 0, .Lexit /* if (rc s<= 0) goto .Lset_len; */
add %r7, %r0 /* len += rc */

.Lset_len:
sub %r7, 1 /* len-- */
mov %r1, %r7
mov %r2, %r9
call dt_strlen_store /* dt_strlen_store(len - 1, dst) */

.Lexit:
exit
.size dt_strjoin, .-dt_strjoin
32 changes: 32 additions & 0 deletions test/unittest/funcs/strjoin/tst.strjoin-bordercases.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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=5
#pragma D option quiet

BEGIN
{
trace(strjoin("", "123"));
trace(strjoin("", "12345"));
trace(strjoin("", "1234567890"));

trace(strjoin("123", "abcdefgh"));
trace(strjoin("12345", "abcdefgh"));
trace(strjoin("1234567890", "abcdefgh"));

trace(strjoin("123", ""));
trace(strjoin("12345", ""));
trace(strjoin("1234567890", ""));

exit(0);
}

ERROR
{
exit(1);
}
28 changes: 28 additions & 0 deletions test/unittest/funcs/strjoin/tst.strjoin-bordercases.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 03 31 32 33 00 00 00 ..123...

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 05 31 32 33 34 35 00 ..12345.

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 05 31 32 33 34 35 00 ..12345.

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 05 31 32 33 61 62 00 ..123ab.

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 05 31 32 33 34 35 00 ..12345.

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 05 31 32 33 34 35 00 ..12345.

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 03 31 32 33 00 00 00 ..123...

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 05 31 32 33 34 35 00 ..12345.

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 05 31 32 33 34 35 00 ..12345.

0 comments on commit ace8cbf

Please sign in to comment.