]> granicus.if.org Git - strace/commitdiff
util.c: add support for additional escape characters in string_quote
authorEugene Syromyatnikov <evgsyr@gmail.com>
Fri, 2 Feb 2018 17:46:29 +0000 (18:46 +0100)
committerDmitry V. Levin <ldv@altlinux.org>
Thu, 1 Mar 2018 01:00:24 +0000 (01:00 +0000)
Quotes are not always used to denote string limits; printfd uses angle
brackets for that, for example.  As result, mechanism for supplying
set of additional characters in order to avoid ambiguities regarding
the end of the quoted string is needed.

* defs.h (string_quote): Add escape_chars parameter.
(print_quoted_string_ex): New function prototype.
* util.c (string_quote): Add escape_chars parameter.
(print_quoted_string_ex): Rename from print_quoted_string, add
escape_chars parameter, pass it to string_quote call.
(print_quoted_string): Turn into a thin wrapper around
print_quoted_string_ex.
(printstr_ex): Pass NULL as escape_chars argument of string_quote call.
* socketutils.c (unix_parse_response): Pass NULL as escape_chars
argument of string_quote call.
* tests/print_quoted_string.c (print_octal): New function.
print_quoted_memory_ex): Use it.  Add escape_chars parameter.
(print_quoted_memory): Pass NULL as escape_chars argument
of print_quoted_memory_ex call.
* tests/tests.h (print_quoted_string_ex, print_quoted_memory_ex): Add
escape_chars parameter.
* tests/fsync-y.c: Pass NULL as escape_chars argument of
print_quoted_string_ex call.

Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
defs.h
socketutils.c
tests/fsync-y.c
tests/print_quoted_string.c
tests/tests.h
util.c

diff --git a/defs.h b/defs.h
index 2ad6fca53f148133343cfd5480d9bdd90468d14c..b4170af48a007d94455d70055e84c7426fde7f72 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -534,7 +534,10 @@ str_strip_prefix_len(const char *str, const char *prefix, size_t prefix_len)
 #define QUOTE_FORCE_HEX                                0x10
 #define QUOTE_EMIT_COMMENT                     0x20
 
-extern int string_quote(const char *, char *, unsigned int, unsigned int);
+extern int string_quote(const char *, char *, unsigned int, unsigned int,
+                       const char *escape_chars);
+extern int print_quoted_string_ex(const char *, unsigned int, unsigned int,
+                                 const char *escape_chars);
 extern int print_quoted_string(const char *, unsigned int, unsigned int);
 extern int print_quoted_cstring(const char *, unsigned int);
 
index 98222b5f1c1997446b89f1777003c8e9c534d273..38b864cdf16919ca65b18f662550f24cdeeebda9 100644 (file)
@@ -331,10 +331,10 @@ unix_parse_response(const void *data, const int data_len,
                if (path[0] == '\0') {
                        outstr[1] = '@';
                        string_quote(path + 1, outstr + 2,
-                                    path_len - 1, QUOTE_0_TERMINATED);
+                                    path_len - 1, QUOTE_0_TERMINATED, NULL);
                } else {
                        string_quote(path, outstr + 1,
-                                    path_len, QUOTE_0_TERMINATED);
+                                    path_len, QUOTE_0_TERMINATED, NULL);
                }
                path_str = outstr;
        } else {
index e4be87eca8705f75423bd4c340969a367c417fe8..f8bf0f9630717d878491afbac7db7c1e0dca6061 100644 (file)
@@ -60,7 +60,7 @@ main(void)
                int rc = fsync(fd);
 
                printf("fsync(%ld<", fd);
-               print_quoted_string_ex(dir, false);
+               print_quoted_string_ex(dir, false, NULL);
                printf("/%s>) = %s\n", checks[i].fdstr, sprintrc(rc));
 
                close(fd);
index bf4df9ad6ee338398b365fe21c13f708e654bf18..3ca56318e849bd94d651736b725c257a289434ef 100644 (file)
@@ -10,9 +10,9 @@
  */
 
 void
-print_quoted_string_ex(const char *instr, bool quote)
+print_quoted_string_ex(const char *instr, bool quote, const char *escape_chars)
 {
-       print_quoted_memory_ex(instr, strlen(instr), quote);
+       print_quoted_memory_ex(instr, strlen(instr), quote, escape_chars);
 }
 
 void
@@ -33,9 +33,32 @@ print_quoted_cstring(const char *instr, const size_t size)
        }
 }
 
+static void
+print_octal(unsigned char c, char next)
+{
+       putchar('\\');
+
+       char c1 = '0' + (c & 0x7);
+       char c2 = '0' + ((c >> 3) & 0x7);
+       char c3 = '0' + (c >> 6);
+
+       if (next >= '0' && next <= '7') {
+               /* Print \octal */
+               putchar(c3);
+               putchar(c2);
+       } else {
+               /* Print \[[o]o]o */
+               if (c3 != '0')
+                       putchar(c3);
+               if (c3 != '0' || c2 != '0')
+                       putchar(c2);
+       }
+       putchar(c1);
+}
+
 void
 print_quoted_memory_ex(const void *const instr, const size_t len,
-                      bool quote)
+                      bool quote, const char *escape_chars)
 {
        const unsigned char *str = (const unsigned char *) instr;
        size_t i;
@@ -68,30 +91,14 @@ print_quoted_memory_ex(const void *const instr, const size_t len,
                                printf("\\v");
                                break;
                        default:
-                               if (c >= ' ' && c <= 0x7e)
+                               if (c >= ' ' && c <= 0x7e &&
+                                   !(escape_chars && strchr(escape_chars, c))) {
                                        putchar(c);
-                               else {
-                                       putchar('\\');
-
-                                       char c1 = '0' + (c & 0x7);
-                                       char c2 = '0' + ((c >> 3) & 0x7);
-                                       char c3 = '0' + (c >> 6);
-
-                                       if (i < (len - 1) &&
-                                           str[i + 1] >= '0' &&
-                                           str[i + 1] <= '7') {
-                                               /* Print \octal */
-                                               putchar(c3);
-                                               putchar(c2);
-                                       } else {
-                                               /* Print \[[o]o]o */
-                                               if (c3 != '0')
-                                                       putchar(c3);
-                                               if (c3 != '0' || c2 != '0')
-                                                       putchar(c2);
-                                       }
-                                       putchar(c1);
+                               } else {
+                                       print_octal(c,
+                                               i < (len - 1) ? str[i + 1] : 0);
                                }
+
                                break;
                }
        }
@@ -103,7 +110,7 @@ print_quoted_memory_ex(const void *const instr, const size_t len,
 void
 print_quoted_memory(const void *const instr, const size_t len)
 {
-       print_quoted_memory_ex(instr, len, true);
+       print_quoted_memory_ex(instr, len, true, NULL);
 }
 
 void
index ccce17c091a14e7cfb0dd1ba96fe180011d8bd87..a8b8ed6a8c45ceeb76f98c5791e1f9386b029a13 100644 (file)
@@ -142,8 +142,8 @@ const char *hexquote_strndup(const char *, size_t);
 /* Return inode number of socket descriptor. */
 unsigned long inode_of_sockfd(int);
 
-/* Print string in a quoted form. */
-void print_quoted_string_ex(const char *, bool quote);
+/* Print string in a quoted form with optional escape characters. */
+void print_quoted_string_ex(const char *, bool quote, const char *escape_str);
 
 /* Print string in a quoted form. */
 void print_quoted_string(const char *);
@@ -154,8 +154,9 @@ void print_quoted_string(const char *);
  */
 void print_quoted_cstring(const char *str, size_t size);
 
-/* Print memory in a quoted form. */
-void print_quoted_memory_ex(const void *, size_t, bool quote);
+/* Print memory in a quoted form with optional escape characters. */
+void print_quoted_memory_ex(const void *, size_t, bool quote,
+                           const char *escape_chars);
 
 /* Print memory in a quoted form. */
 void print_quoted_memory(const void *, size_t);
diff --git a/util.c b/util.c
index 8365f050f7216c3bb71d139ccda46c137c82c5ca..2758bf01c44c06fc7d775c72acc4be45d38fc74f 100644 (file)
--- a/util.c
+++ b/util.c
@@ -446,6 +446,9 @@ printfd(struct tcb *tcp, int fd)
  * Quote string `instr' of length `size'
  * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
  *
+ * `escape_chars' specifies characters (in addition to characters with
+ * codes 0..31, 127..255, single and double quotes) that should be escaped.
+ *
  * If QUOTE_0_TERMINATED `style' flag is set,
  * treat `instr' as a NUL-terminated string,
  * checking up to (`size' + 1) bytes of `instr'.
@@ -458,12 +461,13 @@ printfd(struct tcb *tcp, int fd)
  */
 int
 string_quote(const char *instr, char *outstr, const unsigned int size,
-            const unsigned int style)
+            const unsigned int style, const char *escape_chars)
 {
        const unsigned char *ustr = (const unsigned char *) instr;
        char *s = outstr;
        unsigned int i;
        int usehex, c, eol;
+       bool escape;
 
        if (style & QUOTE_0_TERMINATED)
                eol = '\0';
@@ -552,9 +556,14 @@ string_quote(const char *instr, char *outstr, const unsigned int size,
                        *s++ = 'v';
                        break;
                default:
-                       if (c >= ' ' && c <= 0x7e)
+                       escape = (c < ' ') || (c > 0x7e);
+
+                       if (!escape && escape_chars)
+                               escape = !!strchr(escape_chars, c);
+
+                       if (!escape) {
                                *s++ = c;
-                       else {
+                       else {
                                /* Print \octal */
                                *s++ = '\\';
                                if (i + 1 < size
@@ -623,8 +632,8 @@ string_quote(const char *instr, char *outstr, const unsigned int size,
  * 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)
+print_quoted_string_ex(const char *str, unsigned int size,
+                      const unsigned int style, const char *escape_chars)
 {
        char *buf;
        char *outstr;
@@ -655,13 +664,20 @@ print_quoted_string(const char *str, unsigned int size,
                }
        }
 
-       rc = string_quote(str, outstr, size, style);
+       rc = string_quote(str, outstr, size, style, escape_chars);
        tprints(outstr);
 
        free(buf);
        return rc;
 }
 
+inline int
+print_quoted_string(const char *str, unsigned int size,
+                   const unsigned int style)
+{
+       return print_quoted_string_ex(str, size, style, NULL);
+}
+
 /*
  * Quote a NUL-terminated string `str' of length up to `size' - 1
  * and print the result.
@@ -783,7 +799,7 @@ printstr_ex(struct tcb *const tcp, const kernel_ulong_t addr,
        /* 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, size, style)
+       ellipsis = string_quote(str, outstr, size, style, NULL)
                   && len
                   && ((style & QUOTE_0_TERMINATED)
                       || len > max_strlen);