summaryrefslogtreecommitdiff
path: root/src/print.c
diff options
context:
space:
mode:
authorPhilipp Stephani <phst@google.com>2019-05-04 22:59:46 +0200
committerPhilipp Stephani <phst@google.com>2019-05-04 23:04:24 +0200
commit1242a63671f3fc3d427d9d8061338f826e585031 (patch)
treef911947a957a961f99031ac71211ed8be880cef9 /src/print.c
parent2e0947abbc384a55411880c6d49020b43fe8b5f5 (diff)
downloademacs-1242a63671f3fc3d427d9d8061338f826e585031.tar.gz
emacs-1242a63671f3fc3d427d9d8061338f826e585031.tar.bz2
emacs-1242a63671f3fc3d427d9d8061338f826e585031.zip
Avoid undefined behavior when printing function pointers.
* src/print.c (print_vectorlike): Don’t pass a function pointer to ‘snprintf’, as that is undefined behavior. Instead, print the individual bytes making up the function pointer.
Diffstat (limited to 'src/print.c')
-rw-r--r--src/print.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/src/print.c b/src/print.c
index 68ed6781c81..57aac5f5471 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1794,17 +1794,24 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
if (symbol == NULL)
{
- print_c_string ("at ", printcharfun);
- enum { pointer_bufsize = sizeof ptr * 16 / CHAR_BIT + 2 + 1 };
- char buffer[pointer_bufsize];
- int needed = snprintf (buffer, sizeof buffer, "%p", ptr);
- const char p0x[] = "0x";
- eassert (needed <= sizeof buffer);
- /* ANSI C doesn't guarantee that %p produces a string that
- begins with a "0x". */
- if (c_strncasecmp (buffer, p0x, sizeof (p0x) - 1) != 0)
- print_c_string (p0x, printcharfun);
- print_c_string (buffer, printcharfun);
+ print_c_string ("at 0x", printcharfun);
+ /* See https://stackoverflow.com/a/2741896 for how to
+ portably print a function pointer. */
+ const unsigned char *p = (const unsigned char *) &ptr;
+ for (size_t i = 0; i < sizeof ptr; ++i)
+ {
+#ifdef WORDS_BIGENDIAN
+ unsigned char b = p[i];
+#else
+ unsigned char b = p[sizeof ptr - i - 1];
+#endif
+ enum { digits = (CHAR_BIT + 4 - 1) / 4 };
+ char buffer[digits + 1];
+ int needed
+ = snprintf (buffer, sizeof buffer, "%0*hhx", digits, b);
+ eassert (needed == digits);
+ print_c_string (buffer, printcharfun);
+ }
}
else
print_c_string (symbol, printcharfun);