diff options
Diffstat (limited to 'xorg-server/os')
-rw-r--r-- | xorg-server/os/io.c | 1 | ||||
-rw-r--r-- | xorg-server/os/log.c | 111 |
2 files changed, 103 insertions, 9 deletions
diff --git a/xorg-server/os/io.c b/xorg-server/os/io.c index 2f091c417..0d980ab9f 100644 --- a/xorg-server/os/io.c +++ b/xorg-server/os/io.c @@ -1063,6 +1063,7 @@ FreeOsBuffers(OsCommPtr oc) oci->bufptr = oci->buffer; oci->bufcnt = 0; oci->lenLastReq = 0; + oci->ignoreBytes = 0; } } if ((oco = oc->output)) { diff --git a/xorg-server/os/log.c b/xorg-server/os/log.c index dc6e2888b..f19faf5ee 100644 --- a/xorg-server/os/log.c +++ b/xorg-server/os/log.c @@ -250,7 +250,7 @@ void LogClose(enum ExitCode error) { if (logFile) { - ErrorF("Server terminated %s (%d). Closing log file.\n", + ErrorFSigSafe("Server terminated %s (%d). Closing log file.\n", (error == EXIT_NO_ERROR) ? "successfully" : "with error", error); fclose(logFile); logFile = NULL; @@ -279,6 +279,55 @@ LogSetParameter(LogParameter param, int value) } } +enum { + LMOD_LONG = 0x1, + LMOD_LONGLONG = 0x2, + LMOD_SHORT = 0x4, + LMOD_SIZET = 0x8, +}; + +/** + * Parse non-digit length modifiers and set the corresponding flag in + * flags_return. + * + * @return the number of bytes parsed + */ +static int parse_length_modifier(const char *format, size_t len, int *flags_return) +{ + int idx = 0; + int length_modifier = 0; + + while (idx < len) { + switch (format[idx]) { + case 'l': + BUG_RETURN_VAL(length_modifier & LMOD_SHORT, 0); + + if (length_modifier & LMOD_LONG) + length_modifier |= LMOD_LONGLONG; + else + length_modifier |= LMOD_LONG; + break; + case 'h': + BUG_RETURN_VAL(length_modifier & (LMOD_LONG|LMOD_LONGLONG), 0); + length_modifier |= LMOD_SHORT; + /* gcc says 'short int' is promoted to 'int' when + * passed through '...', so ignored during + * processing */ + break; + case 'z': + length_modifier |= LMOD_SIZET; + break; + default: + goto out; + } + idx++; + } + +out: + *flags_return = length_modifier; + return idx; +} + /** * Signal-safe snprintf, with some limitations over snprintf. Be careful * which directives you use. @@ -297,6 +346,7 @@ pnprintf(char *string, size_t size, const char *f, va_list args) int64_t si; for (; f_idx < f_len && s_idx < size - 1; f_idx++) { + int length_modifier = 0; if (f[f_idx] != '%') { string[s_idx++] = f[f_idx]; continue; @@ -304,10 +354,18 @@ pnprintf(char *string, size_t size, const char *f, va_list args) f_idx++; - /* silently swallow length modifiers */ + /* silently swallow digit length modifiers */ while (f_idx < f_len && ((f[f_idx] >= '0' && f[f_idx] <= '9') || f[f_idx] == '.')) f_idx++; + /* non-digit length modifiers */ + if (f_idx < f_len) { + int parsed_bytes = parse_length_modifier(&f[f_idx], f_len - f_idx, &length_modifier); + if (parsed_bytes < 0) + return 0; + f_idx += parsed_bytes; + } + if (f_idx >= f_len) break; @@ -321,7 +379,15 @@ pnprintf(char *string, size_t size, const char *f, va_list args) break; case 'u': - ui = va_arg(args, unsigned); + if (length_modifier & LMOD_LONGLONG) + ui = va_arg(args, unsigned long long); + else if (length_modifier & LMOD_LONG) + ui = va_arg(args, unsigned long); + else if (length_modifier & LMOD_SIZET) + ui = va_arg(args, size_t); + else + ui = va_arg(args, unsigned); + FormatUInt64(ui, number); p_len = strlen_sigsafe(number); @@ -330,7 +396,15 @@ pnprintf(char *string, size_t size, const char *f, va_list args) break; case 'i': case 'd': - si = va_arg(args, int); + if (length_modifier & LMOD_LONGLONG) + si = va_arg(args, long long); + else if (length_modifier & LMOD_LONG) + si = va_arg(args, long); + else if (length_modifier & LMOD_SIZET) + si = va_arg(args, ssize_t); + else + si = va_arg(args, int); + FormatInt64(si, number); p_len = strlen_sigsafe(number); @@ -351,7 +425,15 @@ pnprintf(char *string, size_t size, const char *f, va_list args) break; case 'x': - ui = va_arg(args, unsigned); + if (length_modifier & LMOD_LONGLONG) + ui = va_arg(args, unsigned long long); + else if (length_modifier & LMOD_LONG) + ui = va_arg(args, unsigned long); + else if (length_modifier & LMOD_SIZET) + ui = va_arg(args, size_t); + else + ui = va_arg(args, unsigned); + FormatUInt64Hex(ui, number); p_len = strlen_sigsafe(number); @@ -368,7 +450,18 @@ pnprintf(char *string, size_t size, const char *f, va_list args) string[s_idx++] = number[i]; } break; + case 'c': + { + char c = va_arg(args, int); + if (s_idx < size - 1) + string[s_idx++] = c; + } + break; + case '%': + string[s_idx++] = '%'; + break; default: + BUG_WARN_MSG(f[f_idx], "Unsupported printf directive '%c'\n", f[f_idx]); va_arg(args, char*); string[s_idx++] = '%'; if (s_idx < size - 1) @@ -785,9 +878,9 @@ FatalError(const char *f, ...) static Bool beenhere = FALSE; if (beenhere) - ErrorF("\nFatalError re-entered, aborting\n"); + ErrorFSigSafe("\nFatalError re-entered, aborting\n"); else - ErrorF("\nFatal server error:\n"); + ErrorFSigSafe("\nFatal server error:\n"); va_start(args, f); @@ -804,9 +897,9 @@ FatalError(const char *f, ...) va_end(apple_args); } #endif - VErrorF(f, args); + VErrorFSigSafe(f, args); va_end(args); - ErrorF("\n"); + ErrorFSigSafe("\n"); if (!beenhere) OsVendorFatalError(f, args2); va_end(args2); |