summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dix/getevents.c18
-rw-r--r--include/misc.h1
-rw-r--r--mi/mipointer.c2
-rw-r--r--os/log.c50
-rw-r--r--os/utils.c14
-rw-r--r--test/signal-logging.c210
6 files changed, 270 insertions, 25 deletions
diff --git a/dix/getevents.c b/dix/getevents.c
index b3bb162ae..4e62507aa 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -1327,6 +1327,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
RawDeviceEvent *raw;
double screenx = 0.0, screeny = 0.0; /* desktop coordinate system */
double devx = 0.0, devy = 0.0; /* desktop-wide in device coords */
+ int sx, sy; /* for POINTER_SCREEN */
ValuatorMask mask;
ScreenPtr scr;
@@ -1369,8 +1370,11 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
/* valuators are in driver-native format (rel or abs) */
if (flags & POINTER_ABSOLUTE) {
- if (flags & POINTER_SCREEN) /* valuators are in screen coords */
+ if (flags & POINTER_SCREEN) { /* valuators are in screen coords */
+ sx = valuator_mask_get(&mask, 0);
+ sy = valuator_mask_get(&mask, 1);
scale_from_screen(pDev, &mask);
+ }
transformAbsolute(pDev, &mask);
clipAbsolute(pDev, &mask);
@@ -1388,6 +1392,18 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
/* valuators are in device coordinate system in absolute coordinates */
scale_to_desktop(pDev, &mask, &devx, &devy, &screenx, &screeny);
+
+ /* #53037 XWarpPointer's scaling back and forth between screen and
+ device may leave us with rounding errors. End result is that the
+ pointer doesn't end up on the pixel it should.
+ Avoid this by forcing screenx/screeny back to what the input
+ coordinates were.
+ */
+ if (flags & POINTER_SCREEN) {
+ screenx = sx;
+ screeny = sy;
+ }
+
scr = positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
&mask, &devx, &devy, &screenx, &screeny);
diff --git a/include/misc.h b/include/misc.h
index 7f7f221a8..348717676 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -247,6 +247,7 @@ padding_for_int32(const int bytes)
extern char **xstrtokenize(const char *str, const char *separators);
+extern void FormatInt64(int64_t num, char *string);
extern void FormatUInt64(uint64_t num, char *string);
extern void FormatUInt64Hex(uint64_t num, char *string);
diff --git a/mi/mipointer.c b/mi/mipointer.c
index a56838ead..4defaf5ec 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -575,7 +575,7 @@ miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx,
miPointerPtr pPointer;
- if (!pDev || !pDev->coreEvents)
+ if (!pDev)
return NULL;
pPointer = MIPOINTER(pDev);
diff --git a/os/log.c b/os/log.c
index 25da9f63a..4820e9a77 100644
--- a/os/log.c
+++ b/os/log.c
@@ -290,6 +290,7 @@ pnprintf(char *string, size_t size, const char *f, va_list args)
int p_len;
int i;
uint64_t ui;
+ int64_t si;
for (; f_idx < f_len && s_idx < size - 1; f_idx++) {
if (f[f_idx] != '%') {
@@ -314,6 +315,15 @@ pnprintf(char *string, size_t size, const char *f, va_list args)
for (i = 0; i < p_len && s_idx < size - 1; i++)
string[s_idx++] = number[i];
break;
+ case 'i':
+ case 'd':
+ si = va_arg(args, int);
+ FormatInt64(si, number);
+ p_len = strlen_sigsafe(number);
+
+ for (i = 0; i < p_len && s_idx < size - 1; i++)
+ string[s_idx++] = number[i];
+ break;
case 'p':
string[s_idx++] = '0';
@@ -364,7 +374,7 @@ LogSWrite(int verb, const char *buf, size_t len, Bool end_line)
if (verb < 0 || logFileVerbosity >= verb) {
if (inSignalContext && logFileFd >= 0) {
write(logFileFd, buf, len);
-#ifdef WIN32
+#ifndef WIN32
if (logFlush && logSync)
fsync(logFileFd);
#endif
@@ -457,6 +467,7 @@ LogMessageTypeVerbString(MessageType type, int verb)
void
LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
{
+ static unsigned int warned;
const char *type_str;
char buf[1024];
const size_t size = sizeof(buf);
@@ -464,13 +475,17 @@ LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
size_t len = 0;
if (inSignalContext) {
- BUG_WARN_MSG(inSignalContext,
- "Warning: attempting to log data in a signal unsafe "
- "manner while in signal context. Please update to check "
- "inSignalContext and/or use LogMessageVerbSigSafe() or "
- "ErrorFSigSafe(). The offending log format message is:\n"
- "%s\n", format);
- return;
+ if (warned < 3) {
+ BUG_WARN_MSG(inSignalContext,
+ "Warning: attempting to log data in a signal unsafe "
+ "manner while in signal context.\nPlease update to check "
+ "inSignalContext and/or use LogMessageVerbSigSafe() or "
+ "ErrorFSigSafe().\nThe offending log format message is:\n"
+ "%s\n", format);
+ warned++;
+ if (warned == 3)
+ LogMessageVerbSigSafe(X_WARNING, -1, "Warned %u times about sigsafe logging. Will be quiet now.\n", warned);
+ }
}
type_str = LogMessageTypeVerbString(type, verb);
@@ -556,6 +571,7 @@ void
LogVHdrMessageVerb(MessageType type, int verb, const char *msg_format,
va_list msg_args, const char *hdr_format, va_list hdr_args)
{
+ static unsigned int warned;
const char *type_str;
char buf[1024];
const size_t size = sizeof(buf);
@@ -563,13 +579,17 @@ LogVHdrMessageVerb(MessageType type, int verb, const char *msg_format,
size_t len = 0;
if (inSignalContext) {
- BUG_WARN_MSG(inSignalContext,
- "Warning: attempting to log data in a signal unsafe "
- "manner while in signal context. Please update to check "
- "inSignalContext and/or use LogMessageVerbSigSafe(). The "
- "offending header and log message formats are:\n%s %s\n",
- hdr_format, msg_format);
- return;
+ if (warned < 3) {
+ BUG_WARN_MSG(inSignalContext,
+ "Warning: attempting to log data in a signal unsafe "
+ "manner while in signal context.\nPlease update to check "
+ "inSignalContext and/or use LogMessageVerbSigSafe().\nThe "
+ "offending header and log message formats are:\n%s %s\n",
+ hdr_format, msg_format);
+ warned++;
+ if (warned == 3)
+ LogMessageVerbSigSafe(X_WARNING, -1, "Warned %u times about sigsafe logging. Will be quiet now.\n", warned);
+ }
}
type_str = LogMessageTypeVerbString(type, verb);
diff --git a/os/utils.c b/os/utils.c
index 947f8673a..04bcbc61f 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -1924,6 +1924,20 @@ xstrtokenize(const char *str, const char *separators)
return NULL;
}
+/* Format a signed number into a string in a signal safe manner. The string
+ * should be at least 21 characters in order to handle all int64_t values.
+ */
+void
+FormatInt64(int64_t num, char *string)
+{
+ if (num < 0) {
+ string[0] = '-';
+ num *= -1;
+ string++;
+ }
+ FormatUInt64(num, string);
+}
+
/* Format a number into a string in a signal safe manner. The string should be
* at least 21 characters in order to handle all uint64_t values. */
void
diff --git a/test/signal-logging.c b/test/signal-logging.c
index 8aab0dd58..3206ddefa 100644
--- a/test/signal-logging.c
+++ b/test/signal-logging.c
@@ -26,6 +26,7 @@
#endif
#include <stdint.h>
+#include <unistd.h>
#include "assert.h"
#include "misc.h"
@@ -35,6 +36,26 @@ struct number_format_test {
char hex_string[17];
};
+struct signed_number_format_test {
+ int64_t number;
+ char string[21];
+};
+
+static Bool
+check_signed_number_format_test(const struct signed_number_format_test *test)
+{
+ char string[21];
+
+ FormatInt64(test->number, string);
+ if(strncmp(string, test->string, 21) != 0) {
+ fprintf(stderr, "Failed to convert %jd to decimal string (%s vs %s)\n",
+ test->number, test->string, string);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static Bool
check_number_format_test(const struct number_format_test *test)
{
@@ -57,11 +78,11 @@ check_number_format_test(const struct number_format_test *test)
return TRUE;
}
-static Bool
+static void
number_formatting(void)
{
int i;
- struct number_format_test tests[] = {
+ struct number_format_test unsigned_tests[] = {
{ /* Zero */
0,
"0",
@@ -99,17 +120,190 @@ number_formatting(void)
},
};
- for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
- if (!check_number_format_test(tests + i))
- return FALSE;
+ struct signed_number_format_test signed_tests[] = {
+ { /* Zero */
+ 0,
+ "0",
+ },
+ { /* Single digit number */
+ 5,
+ "5",
+ },
+ { /* Two digit decimal number */
+ 12,
+ "12",
+ },
+ { /* Two digit hex number */
+ 37,
+ "37",
+ },
+ { /* Large < 32 bit number */
+ 0xC90B2,
+ "823474",
+ },
+ { /* Large > 32 bit number */
+ 0x15D027BF211B37A,
+ "98237498237498234",
+ },
+ { /* Maximum 64-bit signed number */
+ 0x7FFFFFFFFFFFFFFF,
+ "9223372036854775807",
+ },
+ { /* Single digit number */
+ -1,
+ "-1",
+ },
+ { /* Two digit decimal number */
+ -12,
+ "-12",
+ },
+ { /* Large < 32 bit number */
+ -0xC90B2,
+ "-823474",
+ },
+ { /* Large > 32 bit number */
+ -0x15D027BF211B37A,
+ "-98237498237498234",
+ },
+ { /* Maximum 64-bit number */
+ -0x7FFFFFFFFFFFFFFF,
+ "-9223372036854775807",
+ },
+ };
+
+ for (i = 0; i < sizeof(unsigned_tests) / sizeof(unsigned_tests[0]); i++)
+ assert(check_number_format_test(unsigned_tests + i));
- return TRUE;
+ for (i = 0; i < sizeof(unsigned_tests) / sizeof(signed_tests[0]); i++)
+ assert(check_signed_number_format_test(signed_tests + i));
+}
+
+static void logging_format(void)
+{
+ const char *log_file_path = "/tmp/Xorg-logging-test.log";
+ const char *str = "%s %d %u %% %p %i";
+ char buf[1024];
+ int i;
+ unsigned int ui;
+ FILE *f;
+ char read_buf[2048];
+ char *logmsg;
+ uintptr_t ptr;
+
+ /* set up buf to contain ".....end" */
+ memset(buf, '.', sizeof(buf));
+ strcpy(&buf[sizeof(buf) - 4], "end");
+
+ LogInit(log_file_path, NULL);
+ assert(f = fopen(log_file_path, "r"));
+
+#define read_log_msg(msg) \
+ fgets(read_buf, sizeof(read_buf), f); \
+ msg = strchr(read_buf, ']') + 2; /* advance past [time.stamp] */
+
+ /* boring test message */
+ LogMessageVerbSigSafe(X_ERROR, -1, "test message\n");
+ read_log_msg(logmsg);
+ assert(strcmp(logmsg, "(EE) test message\n") == 0);
+
+ /* long buf is truncated to "....en\n" */
+#pragma GCC diagnostic ignored "-Wformat-security"
+ LogMessageVerbSigSafe(X_ERROR, -1, buf);
+#pragma GCC diagnostic pop "-Wformat-security"
+ read_log_msg(logmsg);
+ assert(strcmp(&logmsg[strlen(logmsg) - 3], "en\n") == 0);
+
+ /* same thing, this time as string substitution */
+ LogMessageVerbSigSafe(X_ERROR, -1, "%s", buf);
+ read_log_msg(logmsg);
+ assert(strcmp(&logmsg[strlen(logmsg) - 3], "en\n") == 0);
+
+ /* strings containing placeholders should just work */
+ LogMessageVerbSigSafe(X_ERROR, -1, "%s\n", str);
+ read_log_msg(logmsg);
+ assert(strcmp(logmsg, "(EE) %s %d %u %% %p %i\n") == 0);
+
+ /* string substitution */
+ LogMessageVerbSigSafe(X_ERROR, -1, "%s\n", "substituted string");
+ read_log_msg(logmsg);
+ assert(strcmp(logmsg, "(EE) substituted string\n") == 0);
+
+ /* number substitution */
+ ui = 0;
+ do {
+ char expected[30];
+ sprintf(expected, "(EE) %u\n", ui);
+ LogMessageVerbSigSafe(X_ERROR, -1, "%u\n", ui);
+ read_log_msg(logmsg);
+ assert(strcmp(logmsg, expected) == 0);
+ if (ui == 0)
+ ui = 1;
+ else
+ ui <<= 1;
+ } while(ui);
+
+ /* signed number substitution */
+ i = 0;
+ do {
+ char expected[30];
+ sprintf(expected, "(EE) %d\n", i);
+ LogMessageVerbSigSafe(X_ERROR, -1, "%d\n", i);
+ read_log_msg(logmsg);
+ assert(strcmp(logmsg, expected) == 0);
+
+
+ sprintf(expected, "(EE) %d\n", i | INT_MIN);
+ LogMessageVerbSigSafe(X_ERROR, -1, "%d\n", i | INT_MIN);
+ read_log_msg(logmsg);
+ assert(strcmp(logmsg, expected) == 0);
+
+ if (i == 0)
+ i = 1;
+ else
+ i <<= 1;
+ } while(i > INT_MIN);
+
+ /* hex number substitution */
+ ui = 0;
+ do {
+ char expected[30];
+ sprintf(expected, "(EE) %x\n", ui);
+ LogMessageVerbSigSafe(X_ERROR, -1, "%x\n", ui);
+ read_log_msg(logmsg);
+ assert(strcmp(logmsg, expected) == 0);
+ if (ui == 0)
+ ui = 1;
+ else
+ ui <<= 1;
+ } while(ui);
+
+ /* pointer substitution */
+ /* we print a null-pointer differently to printf */
+ LogMessageVerbSigSafe(X_ERROR, -1, "%p\n", NULL);
+ read_log_msg(logmsg);
+ assert(strcmp(logmsg, "(EE) 0x0\n") == 0);
+
+ ptr = 1;
+ do {
+ char expected[30];
+ sprintf(expected, "(EE) %p\n", (void*)ptr);
+ LogMessageVerbSigSafe(X_ERROR, -1, "%p\n", (void*)ptr);
+ read_log_msg(logmsg);
+ assert(strcmp(logmsg, expected) == 0);
+ ptr <<= 1;
+ } while(ptr);
+
+ LogClose(EXIT_NO_ERROR);
+ unlink(log_file_path);
+
+#undef read_log_msg
}
int
main(int argc, char **argv)
{
- int ok = number_formatting();
+ number_formatting();
+ logging_format();
- return ok ? 0 : 1;
+ return 0;
}