add escaping of non-printable & non-ASCII characters to xvasprintf()
This commit is contained in:
parent
57173bd289
commit
0079ec774a
44
src/util.c
44
src/util.c
|
@ -189,6 +189,10 @@ sys_error( const char *msg, ... )
|
||||||
// Print backslash-escaped string literals. Note that this does not
|
// Print backslash-escaped string literals. Note that this does not
|
||||||
// automatically add quotes around the printed string, so it is
|
// automatically add quotes around the printed string, so it is
|
||||||
// possible to concatenate multiple segments.
|
// possible to concatenate multiple segments.
|
||||||
|
// - %!s
|
||||||
|
// Same as %\\s, but non-ASCII characters are (hex-)escaped as well.
|
||||||
|
// - %!&s
|
||||||
|
// Same as %!s, but linefeeds are also printed verbatim for legibility.
|
||||||
|
|
||||||
// TODO: Trade off segments vs. buffer capacity dynamically.
|
// TODO: Trade off segments vs. buffer capacity dynamically.
|
||||||
#define QPRINTF_SEGS 16
|
#define QPRINTF_SEGS 16
|
||||||
|
@ -238,6 +242,13 @@ xvasprintf( const char *fmt, va_list ap )
|
||||||
if (c == '\\') {
|
if (c == '\\') {
|
||||||
escaped = 1;
|
escaped = 1;
|
||||||
c = *++fmt;
|
c = *++fmt;
|
||||||
|
} else if (c == '!') {
|
||||||
|
escaped = 2;
|
||||||
|
c = *++fmt;
|
||||||
|
if (c == '&') {
|
||||||
|
escaped = 3;
|
||||||
|
c = *++fmt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (c == 'c') {
|
if (c == 'c') {
|
||||||
if (d + 1 > ed)
|
if (d + 1 > ed)
|
||||||
|
@ -249,10 +260,39 @@ xvasprintf( const char *fmt, va_list ap )
|
||||||
if (escaped) {
|
if (escaped) {
|
||||||
char *bd = d;
|
char *bd = d;
|
||||||
for (l = 0; l < maxlen && (c = *s); l++, s++) {
|
for (l = 0; l < maxlen && (c = *s); l++, s++) {
|
||||||
if (d + 2 > ed)
|
if (c == '\\' || c == '"') {
|
||||||
|
if (d >= ed)
|
||||||
oob();
|
oob();
|
||||||
if (c == '\\' || c == '"')
|
|
||||||
*d++ = '\\';
|
*d++ = '\\';
|
||||||
|
} else if (escaped >= 2 && (c < 32 || c > 126)) {
|
||||||
|
switch (c) {
|
||||||
|
case '\r': c = 'r'; break;
|
||||||
|
case '\t': c = 't'; break;
|
||||||
|
case '\a': c = 'a'; break;
|
||||||
|
case '\b': c = 'b'; break;
|
||||||
|
case '\v': c = 'v'; break;
|
||||||
|
case '\f': c = 'f'; break;
|
||||||
|
case '\n':
|
||||||
|
if (escaped == 2) {
|
||||||
|
c = 'n';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (d + 2 >= ed)
|
||||||
|
oob();
|
||||||
|
*d++ = '\\';
|
||||||
|
*d++ = 'n';
|
||||||
|
*d++ = c; // Keep the actual line break for legibility.
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
d += nfsnprintf( d, ed - d, "\\x%02x", (uchar)c );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (d >= ed)
|
||||||
|
oob();
|
||||||
|
*d++ = '\\';
|
||||||
|
}
|
||||||
|
if (d >= ed)
|
||||||
|
oob();
|
||||||
*d++ = c;
|
*d++ = c;
|
||||||
}
|
}
|
||||||
l = d - bd;
|
l = d - bd;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user