Rework string_quote API

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.
This commit is contained in:
Дмитрий Левин 2015-01-26 01:17:08 +00:00
parent a10b6feb44
commit 513e96eb94
6 changed files with 133 additions and 65 deletions

6
defs.h
View File

@ -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
*/

26
loop.c
View File

@ -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))

25
mtd.c
View File

@ -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;

12
net.c
View File

@ -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;
tprints(", ");
print_quoted_string(label, label_len, 0);
tprints("}");
string_quote(label, outstr, 0, label_len);
tprintf(", %s}", outstr);
free(outstr);
return true;
}

View 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("]");

117
util.c
View File

@ -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);