[PATCH v1] strace: Enhance --string-limit/-s to remove max string length limit
Gautam Menghani
gautammenghani201 at gmail.com
Sun Jan 21 10:46:02 UTC 2024
Enhance the -s STRSIZE/--string-limit=STRSIZE option to provide the
ability to remove the max string length limit with the value argument
'inf'. This patch resolves issue 269 on github.
Signed-off-by: Gautam Menghani <gum3ng at protonmail.com>
---
NEWS | 2 ++
src/btrfs.c | 2 +-
src/defs.h | 3 +++
src/dm.c | 6 +++---
src/execve.c | 3 +--
src/netlink.c | 2 +-
src/nlattr.c | 2 +-
src/strace.c | 13 ++++++++++---
src/util.c | 31 ++++++++++++++++++++++++-------
tests/gen_tests.in | 1 +
tests/truncate.c | 20 ++++++++++++--------
11 files changed, 59 insertions(+), 26 deletions(-)
diff --git a/NEWS b/NEWS
index bd66e7069..02337ec1d 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ Noteworthy changes in release ?.? (????-??-??)
* Implemented -kk/--stack-traces=source option for libdw-based stack tracing.
* Updated lists of BPF_*, BTRFS_*, IORING_*, KVM_*, LANDLOCK_*, PR_*,
and TCP_* constants.
+ * Enhance --string-limit/-s to introduce a new value argument ('inf') to remove
+ max string length limit.
* Bug fixes
* Fix strace -r during the first second after booting to show correct relative
diff --git a/src/btrfs.c b/src/btrfs.c
index 31ee871b3..c6408c94a 100644
--- a/src/btrfs.c
+++ b/src/btrfs.c
@@ -381,7 +381,7 @@ decode_search_arg_buf(struct tcb *tcp, kernel_ulong_t buf_addr, uint64_t buf_siz
struct btrfs_ioctl_search_header sh;
uint64_t addr = buf_addr + off;
if (addr < buf_addr || off + sizeof(sh) > buf_size ||
- i > max_strlen) {
+ truncation_needed(i, max_strlen + 1)) {
tprint_more_data_follows();
break;
}
diff --git a/src/defs.h b/src/defs.h
index 6f1f25680..8005112c8 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -556,12 +556,15 @@ extern enum stack_trace_modes stack_trace_mode;
# define stack_trace_mode STACK_TRACE_OFF
# endif
extern unsigned max_strlen;
+extern bool truncate_output;
extern unsigned os_release;
# undef KERNEL_VERSION
# define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
extern int read_int_from_file(const char *, int *);
+extern bool truncation_needed(unsigned int size, unsigned int limit);
+
extern void set_sortby(const char *);
extern int set_overhead(const char *);
extern void set_count_summary_columns(const char *columns);
diff --git a/src/dm.c b/src/dm.c
index 2977eac68..0f4cee527 100644
--- a/src/dm.c
+++ b/src/dm.c
@@ -190,7 +190,7 @@ dm_decode_dm_target_spec(struct tcb *const tcp, const kernel_ulong_t addr,
if (offset_end <= offset || offset_end > ioc->data_size)
goto misplaced;
- if (i >= max_strlen) {
+ if (truncation_needed(i, max_strlen)) {
tprint_more_data_follows();
break;
}
@@ -323,7 +323,7 @@ dm_decode_dm_name_list(struct tcb *const tcp, const kernel_ulong_t addr,
if (offset_end <= offset || offset_end > ioc->data_size)
goto misplaced;
- if (count >= max_strlen) {
+ if (truncation_needed(count, max_strlen)) {
tprint_more_data_follows();
break;
}
@@ -413,7 +413,7 @@ dm_decode_dm_target_versions(struct tcb *const tcp, const kernel_ulong_t addr,
if (offset_end <= offset || offset_end > ioc->data_size)
goto misplaced;
- if (count >= max_strlen) {
+ if (truncation_needed(count, max_strlen)) {
tprint_more_data_follows();
break;
}
diff --git a/src/execve.c b/src/execve.c
index a9224543b..a85f5feec 100644
--- a/src/execve.c
+++ b/src/execve.c
@@ -52,8 +52,7 @@ printargv(struct tcb *const tcp, kernel_ulong_t addr)
break;
if (n != 0)
tprint_array_next();
-
- if (abbrev(tcp) && n >= max_strlen) {
+ if (abbrev(tcp) && truncation_needed(n, max_strlen)) {
tprint_more_data_follows();
break;
}
diff --git a/src/netlink.c b/src/netlink.c
index 0e31168c3..a2f2cfa8e 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -684,7 +684,7 @@ decode_netlink(struct tcb *const tcp,
for (unsigned int elt = 0;
fetch_nlmsghdr(tcp, &nlmsghdr, addr, len, is_array);
++elt) {
- if (abbrev(tcp) && elt == max_strlen) {
+ if (abbrev(tcp) && truncation_needed(elt, max_strlen)) {
tprint_more_data_follows();
break;
}
diff --git a/src/nlattr.c b/src/nlattr.c
index 1fb394d7c..762fd7a9d 100644
--- a/src/nlattr.c
+++ b/src/nlattr.c
@@ -128,7 +128,7 @@ decode_nlattr(struct tcb *const tcp,
for (unsigned int elt = 0;
fetch_nlattr(tcp, &nla, addr, len, is_array);
++elt) {
- if (abbrev(tcp) && elt == max_strlen) {
+ if (abbrev(tcp) && truncation_needed(elt, max_strlen)) {
tprint_more_data_follows();
break;
}
diff --git a/src/strace.c b/src/strace.c
index 780e51e91..a4c4b6ec8 100644
--- a/src/strace.c
+++ b/src/strace.c
@@ -27,6 +27,7 @@
#include <locale.h>
#include <sys/utsname.h>
#include <sys/prctl.h>
+#include <ctype.h>
#include "kill_save_errno.h"
#include "exitkill.h"
@@ -154,6 +155,7 @@ static uid_t run_uid;
static gid_t run_gid;
unsigned int max_strlen = DEFAULT_STRLEN;
+bool truncate_output = true;
static int acolumn = DEFAULT_ACOLUMN;
static char *acolumn_spaces;
@@ -2562,10 +2564,15 @@ init(int argc, char *argv[])
error_opt_arg(c, lopt, optarg);
break;
case 's':
- i = string_to_uint(optarg);
- if (i < 0 || (unsigned int) i > -1U / 4)
+ if (isdigit(*optarg)) {
+ i = string_to_uint(optarg);
+ if (i < 0 || (unsigned int) i > -1U / 4)
+ error_opt_arg(c, lopt, optarg);
+ max_strlen = i;
+ } else if (strcmp(optarg, "inf") == 0)
+ truncate_output = false;
+ else
error_opt_arg(c, lopt, optarg);
- max_strlen = i;
break;
case 'S':
set_sortby(optarg);
diff --git a/src/util.c b/src/util.c
index 92c0577ce..68fb0277e 100644
--- a/src/util.c
+++ b/src/util.c
@@ -22,6 +22,7 @@
# include <sys/xattr.h>
#endif
#include <sys/uio.h>
+#include <sys/sysinfo.h>
#include "largefile_wrappers.h"
#include "number_set.h"
@@ -1258,30 +1259,39 @@ printstr_ex(struct tcb *const tcp, const kernel_ulong_t addr,
static char *str;
static char *outstr;
- unsigned int size;
+ unsigned long size;
unsigned int style = user_style;
+ unsigned long max_len = max_strlen;
int rc;
int ellipsis;
+ struct sysinfo info;
if (!addr) {
tprint_null();
return -1;
}
+
+ if (!truncate_output) {
+ sysinfo(&info);
+ max_len = info.totalram;
+ }
+
/* Allocate static buffers if they are not allocated yet. */
+
if (!str) {
const unsigned int outstr_size =
- 4 * max_strlen + /* for quotes and NUL */ 3;
+ 4 * max_len + /* for quotes and NUL */ 3;
/*
* We can assume that outstr_size / 4 == max_strlen
* since we have a guarantee that max_strlen <= -1U / 4.
*/
- str = xmalloc(max_strlen + 1);
+ str = xmalloc(max_len + 1);
outstr = xmalloc(outstr_size);
}
/* Fetch one byte more because string_quote may look one byte ahead. */
- size = max_strlen + 1;
+ size = max_len + 1;
if (size > len)
size = len;
@@ -1295,7 +1305,7 @@ printstr_ex(struct tcb *const tcp, const kernel_ulong_t addr,
return rc;
}
- if (size > max_strlen)
+ if (truncation_needed(size, max_strlen + 1))
size = max_strlen;
else
str[size] = '\xff';
@@ -1312,7 +1322,7 @@ printstr_ex(struct tcb *const tcp, const kernel_ulong_t addr,
ellipsis = string_quote(str, outstr, size, style, NULL)
&& len
&& ((style & (QUOTE_0_TERMINATED | QUOTE_EXPECT_TRAILING_0))
- || len > max_strlen);
+ || truncation_needed(len, max_strlen + 1));
tprints_string(outstr);
if (ellipsis)
@@ -1774,7 +1784,7 @@ print_array_ex(struct tcb *const tcp,
if (cur == start_addr)
tprint_array_begin();
- if (cur >= abbrev_end) {
+ if (truncation_needed(cur, abbrev_end)) {
tprint_more_data_follows();
cur = end_addr;
truncated = true;
@@ -1908,3 +1918,10 @@ read_int_from_file(const char *const fname, int *const pvalue)
*pvalue = (int) lval;
return 0;
}
+
+bool truncation_needed(unsigned int size, unsigned int limit)
+{
+ if (truncate_output && size >= limit)
+ return true;
+ return false;
+}
diff --git a/tests/gen_tests.in b/tests/gen_tests.in
index bf2bcb2f2..4ee039709 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -1140,6 +1140,7 @@ trace_statfs test_trace_expr '' -e%statfs
trace_statfs_like test_trace_expr '' -e%%statfs
trie_test run_prog
truncate
+truncate -s inf
truncate64
ugetrlimit -a28 'QUIRK:START-OF-TEST-OUTPUT:ugetrlimit(0x10 /* RLIMIT_??? */, NULL)'
umask -a11
diff --git a/tests/truncate.c b/tests/truncate.c
index d1ea3f683..f53935bce 100644
--- a/tests/truncate.c
+++ b/tests/truncate.c
@@ -17,18 +17,22 @@
int
main(void)
{
- static const char fname[] = "truncate\nfilename";
- static const char qname[] = "truncate\\nfilename";
+ static const char * const fnames[] = {"truncate\nfilename",
+ "truncate\nfilename_p1\nfilename_p2\nfilename_p3"};
+ static const char * const qnames[] = {"truncate\\nfilename",
+ "truncate\\nfilename_p1\\nfilename_p2\\nfilename_p3"};
const kernel_ulong_t len = (kernel_ulong_t) 0xdefaced0badc0deULL;
long rc;
- if (sizeof(len) > sizeof(long))
- rc = truncate(fname, len);
- else
- rc = syscall(__NR_truncate, fname, len);
+ for (int i = 0; i < 2; i++) {
+ if (sizeof(len) > sizeof(long))
+ rc = truncate(fnames[i], len);
+ else
+ rc = syscall(__NR_truncate, fnames[i], len);
- printf("truncate(\"%s\", %llu) = %s\n",
- qname, (unsigned long long) len, sprintrc(rc));
+ printf("truncate(\"%s\", %llu) = %s\n",
+ qnames[i], (unsigned long long) len, sprintrc(rc));
+ }
puts("+++ exited with 0 +++");
return 0;
--
2.34.1
More information about the Strace-devel
mailing list