]> granicus.if.org Git - strace/commitdiff
Rework string_quote API
authorDmitry V. Levin <ldv@altlinux.org>
Mon, 26 Jan 2015 01:17:08 +0000 (01:17 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 26 Jan 2015 15:58:18 +0000 (15:58 +0000)
string_quote() has proven to be too hard to use, replace it with
print_quoted_string() that does memory allocation and prints the result.

* defs.h (string_quote): Remove.
(QUOTE_0_TERMINATED, QUOTE_OMIT_LEADING_TRAILING_QUOTES): New macros.
(print_quoted_string): New prototype.
* util.c (string_quote): Make static; take "style" flags instead
of "len", treat QUOTE_0_TERMINATED style flag as former (len == -1);
add QUOTE_OMIT_LEADING_TRAILING_QUOTES style flag support.
(ALLOCA_CUTOFF, use_alloca): New macros.
(print_quoted_string): New function.
(printpathn, printstr): Update to new API.
* loop.c (loop_ioctl): Likewise.
* mtd.c (ubi_ioctl): Likewise.
* net.c (print_scm_security): Likewise.
* socketutils.c (unix_parse_response): Likewise.

defs.h
loop.c
mtd.c
net.c
socketutils.c
util.c

diff --git a/defs.h b/defs.h
index 8d654a593079f3b0269c107f99dee3fbf09e8f1a..97865daf2fb8ff58f531c2c0c90ecfad45baafa5 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -665,9 +665,13 @@ extern const char *xlookup(const struct xlat *, const unsigned int);
 extern const char *xlat_search(const struct xlat *, const size_t, const unsigned int);
 
 extern int string_to_uint(const char *str);
-extern int string_quote(const char *, char *, long, int);
 extern int next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits);
 
+#define QUOTE_0_TERMINATED                     0x01
+#define QUOTE_OMIT_LEADING_TRAILING_QUOTES     0x02
+
+extern int print_quoted_string(const char *, unsigned int, unsigned int);
+
 /* a refers to the lower numbered u_arg,
  * b refers to the higher numbered u_arg
  */
diff --git a/loop.c b/loop.c
index 6ce6545a0508f3f8255462503b26785484af999f..bb622fd901f35d8c622c88c648cf4bcbccdbaf70 100644 (file)
--- a/loop.c
+++ b/loop.c
@@ -39,7 +39,6 @@ loop_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 {
        struct loop_info info;
        struct loop_info64 info64;
-       char *s = alloca((LO_NAME_SIZE + LO_KEY_SIZE) * 4);
 
        if (entering(tcp))
                return 0;
@@ -72,12 +71,14 @@ loop_ioctl(struct tcb *tcp, const unsigned int code, long arg)
                tprints(", flags=");
                printflags(loop_flags_options, info.lo_flags, "LO_FLAGS_???");
 
-               string_quote(info.lo_name, s, -1, LO_NAME_SIZE);
-               tprintf(", name=%s", s);
+               tprints(", name=");
+               print_quoted_string(info.lo_name, LO_NAME_SIZE,
+                                   QUOTE_0_TERMINATED);
 
                if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
-                       string_quote((void *) info.lo_encrypt_key, s, 0, LO_KEY_SIZE);
-                       tprintf(", encrypt_key=%s", s);
+                       tprints(", encrypt_key=");
+                       print_quoted_string((void *) info.lo_encrypt_key,
+                                           LO_KEY_SIZE, 0);
                }
 
                if (!abbrev(tcp))
@@ -125,14 +126,17 @@ loop_ioctl(struct tcb *tcp, const unsigned int code, long arg)
                tprints(", flags=");
                printflags(loop_flags_options, info64.lo_flags, "LO_FLAGS_???");
 
-               string_quote((void *) info64.lo_file_name, s, -1, LO_NAME_SIZE);
-               tprintf(", file_name=%s", s);
+               tprints(", file_name=");
+               print_quoted_string((void *) info64.lo_file_name,
+                                   LO_NAME_SIZE, QUOTE_0_TERMINATED);
 
                if (!abbrev(tcp) || info64.lo_encrypt_type != LO_CRYPT_NONE) {
-                       string_quote((void *) info64.lo_crypt_name, s, -1, LO_NAME_SIZE);
-                       tprintf(", crypt_name=%s", s);
-                       string_quote((void *) info64.lo_encrypt_key, s, 0, LO_KEY_SIZE);
-                       tprintf(", encrypt_key=%s", s);
+                       tprints(", crypt_name=");
+                       print_quoted_string((void *) info64.lo_crypt_name,
+                                           LO_NAME_SIZE, QUOTE_0_TERMINATED);
+                       tprints(", encrypt_key=");
+                       print_quoted_string((void *) info64.lo_encrypt_key,
+                                           LO_KEY_SIZE, 0);
                }
 
                if (!abbrev(tcp))
diff --git a/mtd.c b/mtd.c
index 8f05d040239193396e09f1eb2c2626f0bf26eadf..87a6e5d15fcf1422449af9f5ffa165ae10f585d5 100644 (file)
--- a/mtd.c
+++ b/mtd.c
@@ -262,9 +262,6 @@ ubi_ioctl(struct tcb *tcp, const unsigned int code, long arg)
        struct ubi_attach_req attach;
        struct ubi_map_req map;
        struct ubi_set_vol_prop_req prop;
-       /* 4*(n-1) + 3 for quotes and NUL */
-       char vol_name[(UBI_MAX_VOLUME_NAME + 1) * 4];
-       int ret;
 
        if (entering(tcp))
                return 0;
@@ -278,10 +275,12 @@ ubi_ioctl(struct tcb *tcp, const unsigned int code, long arg)
                        ", bytes=%" PRIi64 ", vol_type=", mkvol.vol_id,
                        mkvol.alignment, (int64_t)mkvol.bytes);
                printxval(ubi_volume_types, mkvol.vol_type, "UBI_???_VOLUME");
-               ret = string_quote(mkvol.name, vol_name, -1,
-                       CLAMP(mkvol.name_len, 0, UBI_MAX_VOLUME_NAME));
-               tprintf(", name_len=%" PRIi16 ", name=%s%s",
-                       mkvol.name_len, vol_name, ret ? "..." : "");
+               tprintf(", name_len=%" PRIi16 ", name=", mkvol.name_len);
+               if (print_quoted_string(mkvol.name,
+                               CLAMP(mkvol.name_len, 0, UBI_MAX_VOLUME_NAME),
+                               QUOTE_0_TERMINATED) > 0) {
+                       tprints("...");
+               }
                tprints("}");
                return 1;
 
@@ -303,11 +302,15 @@ ubi_ioctl(struct tcb *tcp, const unsigned int code, long arg)
                for (c = 0; c < CLAMP(rnvol.count, 0, UBI_MAX_RNVOL); ++c) {
                        if (c)
                                tprints(", ");
-                       ret = string_quote(rnvol.ents[c].name, vol_name, -1,
-                               CLAMP(rnvol.ents[c].name_len, 0, UBI_MAX_VOLUME_NAME));
                        tprintf("{vol_id=%" PRIi32 ", name_len=%" PRIi16
-                               ", name=%s%s}", rnvol.ents[c].vol_id,
-                               rnvol.ents[c].name_len, vol_name, ret ? "..." : "");
+                               ", name=", rnvol.ents[c].vol_id,
+                               rnvol.ents[c].name_len);
+                       if (print_quoted_string(rnvol.ents[c].name,
+                                       CLAMP(rnvol.ents[c].name_len, 0, UBI_MAX_VOLUME_NAME),
+                                       QUOTE_0_TERMINATED) > 0) {
+                               tprints("...");
+                       }
+                       tprints("}");
                }
                tprints("]}");
                return 1;
diff --git a/net.c b/net.c
index 829f3ad849abda74a4119af7138c2d0416efb410..ef72d4fee4ee357402aafea6987f105d0c2e68f4 100644 (file)
--- a/net.c
+++ b/net.c
@@ -402,17 +402,11 @@ print_scm_security(struct tcb *tcp, size_t cmsg_size, char *ptr, size_t cmsg_len
 
        const char *label = (const char *) (ptr + cmsg_size);
        const size_t label_len = cmsg_len - cmsg_size;
-       char *outstr;
-       const size_t alloc_len = 4 * label_len + 3;
 
-       if (label_len != alloc_len / 4 ||
-           !(outstr = malloc(alloc_len)))
-               return false;
-
-       string_quote(label, outstr, 0, label_len);
-       tprintf(", %s}", outstr);
+       tprints(", ");
+       print_quoted_string(label, label_len, 0);
+       tprints("}");
 
-       free(outstr);
        return true;
 }
 
index 93bb0c3c269c67b05668003d9b9a6b8012e33c29..2de59cd3f0ba608c7069589cda2cdfe30722efaa 100644 (file)
@@ -252,13 +252,13 @@ unix_parse_response(const char *proto_name, const void *data, int data_len,
                        tprintf("->%u", peer);
                if (path_len) {
                        if (path[0] == '\0') {
-                               char *outstr = alloca(4 * path_len - 1);
-                               string_quote(path + 1, outstr, -1, path_len);
-                               tprintf(",@%s", outstr);
+                               tprints(",@");
+                               print_quoted_string(path + 1, path_len,
+                                                   QUOTE_0_TERMINATED);
                        } else {
-                               char *outstr = alloca(4 * path_len + 3);
-                               string_quote(path, outstr, -1, path_len + 1);
-                               tprintf(",%s", outstr);
+                               tprints(",");
+                               print_quoted_string(path, path_len + 1,
+                                                   QUOTE_0_TERMINATED);
                        }
                }
                tprints("]");
diff --git a/util.c b/util.c
index 3b50191d9b7adf3ef9e570736afd16fcb97b386d..00ee5a02b8d9436ca393b07b1807b4e8cfcf2fde 100644 (file)
--- a/util.c
+++ b/util.c
@@ -519,24 +519,30 @@ printfd(struct tcb *tcp, int fd)
 /*
  * Quote string `instr' of length `size'
  * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
- * If `len' is -1, treat `instr' as a NUL-terminated string
- * and quote at most (`size' - 1) bytes.
  *
- * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
- * Note that if len >= 0, always returns 1.
+ * If QUOTE_0_TERMINATED `style' flag is set,
+ * treat `instr' as a NUL-terminated string,
+ * checking up to (`size' + 1) bytes of `instr'.
+ *
+ * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
+ * do not add leading and trailing quoting symbols.
+ *
+ * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
+ * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
  */
-int
-string_quote(const char *instr, char *outstr, long len, int size)
+static int
+string_quote(const char *instr, char *outstr, const unsigned int size,
+            const unsigned int style)
 {
        const unsigned char *ustr = (const unsigned char *) instr;
        char *s = outstr;
-       int usehex, c, i, eol;
+       unsigned int i;
+       int usehex, c, eol;
 
-       eol = 0x100; /* this can never match a char */
-       if (len == -1) {
-               size--;
+       if (style & QUOTE_0_TERMINATED)
                eol = '\0';
-       }
+       else
+               eol = 0x100; /* this can never match a char */
 
        usehex = 0;
        if (xflag > 1)
@@ -565,7 +571,8 @@ string_quote(const char *instr, char *outstr, long len, int size)
                }
        }
 
-       *s++ = '\"';
+       if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
+               *s++ = '\"';
 
        if (usehex) {
                /* Hex-quote the whole string. */
@@ -638,11 +645,12 @@ string_quote(const char *instr, char *outstr, long len, int size)
                }
        }
 
-       *s++ = '\"';
+       if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
+               *s++ = '\"';
        *s = '\0';
 
        /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
-       if (len == -1 && ustr[i] == '\0') {
+       if (style & QUOTE_0_TERMINATED && ustr[i] == '\0') {
                /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
                 * but next char is NUL.
                 */
@@ -652,12 +660,70 @@ string_quote(const char *instr, char *outstr, long len, int size)
        return 1;
 
  asciz_ended:
-       *s++ = '\"';
+       if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
+               *s++ = '\"';
        *s = '\0';
        /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
        return 0;
 }
 
+#ifndef ALLOCA_CUTOFF
+# define ALLOCA_CUTOFF 4032
+#endif
+#define use_alloca(n) ((n) <= ALLOCA_CUTOFF)
+
+/*
+ * Quote string `str' of length `size' and print the result.
+ *
+ * If QUOTE_0_TERMINATED `style' flag is set,
+ * treat `str' as a NUL-terminated string and
+ * quote at most (`size' - 1) bytes.
+ *
+ * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
+ * do not add leading and trailing quoting symbols.
+ *
+ * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
+ * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
+ */
+int
+print_quoted_string(const char *str, unsigned int size,
+                   const unsigned int style)
+{
+       char *buf;
+       char *outstr;
+       unsigned int alloc_size;
+       int rc;
+
+       if (size && style & QUOTE_0_TERMINATED)
+               --size;
+
+       alloc_size = 4 * size;
+       if (alloc_size / 4 != size) {
+               error_msg("Out of memory");
+               tprints("???");
+               return -1;
+       }
+       alloc_size += 1 + (style & QUOTE_OMIT_LEADING_TRAILING_QUOTES ? 0 : 2);
+
+       if (use_alloca(alloc_size)) {
+               outstr = alloca(alloc_size);
+               buf = NULL;
+       } else {
+               outstr = buf = malloc(alloc_size);
+               if (!buf) {
+                       error_msg("Out of memory");
+                       tprints("???");
+                       return -1;
+               }
+       }
+
+       rc = string_quote(str, outstr, size, style);
+       tprints(outstr);
+
+       free(buf);
+       return rc;
+}
+
 /*
  * Print path string specified by address `addr' and length `n'.
  * If path length exceeds `n', append `...' to the output.
@@ -682,13 +748,8 @@ printpathn(struct tcb *tcp, long addr, unsigned int n)
        if (nul_seen < 0)
                tprintf("%#lx", addr);
        else {
-               char *outstr;
-
-               path[n] = '\0';
-               n++;
-               outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
-               string_quote(path, outstr, -1, n);
-               tprints(outstr);
+               path[n++] = '\0';
+               print_quoted_string(path, n, QUOTE_0_TERMINATED);
                if (!nul_seen)
                        tprints("...");
        }
@@ -712,6 +773,7 @@ printstr(struct tcb *tcp, long addr, long len)
        static char *str = NULL;
        static char *outstr;
        unsigned int size;
+       unsigned int style;
        int ellipsis;
 
        if (!addr) {
@@ -732,31 +794,32 @@ printstr(struct tcb *tcp, long addr, long len)
                        die_out_of_memory();
        }
 
+       size = max_strlen;
        if (len == -1) {
                /*
                 * Treat as a NUL-terminated string: fetch one byte more
-                * because string_quote() quotes one byte less.
+                * because string_quote may look one byte ahead.
                 */
-               size = max_strlen + 1;
-               if (umovestr(tcp, addr, size, str) < 0) {
+               if (umovestr(tcp, addr, size + 1, str) < 0) {
                        tprintf("%#lx", addr);
                        return;
                }
+               style = QUOTE_0_TERMINATED;
        }
        else {
-               size = max_strlen;
                if (size > (unsigned long)len)
                        size = (unsigned long)len;
                if (umoven(tcp, addr, size, str) < 0) {
                        tprintf("%#lx", addr);
                        return;
                }
+               style = 0;
        }
 
        /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
         * or we were requested to print more than -s NUM chars)...
         */
-       ellipsis = (string_quote(str, outstr, len, size) &&
+       ellipsis = (string_quote(str, outstr, size, style) &&
                        (len < 0 || (unsigned long) len > max_strlen));
 
        tprints(outstr);