summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2011-04-06 20:34:05 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2011-04-06 20:34:05 -0700
commit5fdb398c4b75b0c834aff7132f90b0ce5317a25a (patch)
tree29ebb8fc5700fefdd867fa497eac27fb7d0bcfe0 /src
parentb189fa667ed7ac7b17f9665cd8a0c26316b3c521 (diff)
downloademacs-5fdb398c4b75b0c834aff7132f90b0ce5317a25a.tar.gz
error: Print 32- and 64-bit integers portably (Bug#8435).
Without this change, on typical 64-bit hosts error ("...%d...", N) was used to print both 32- and 64-bit integers N, which relied on undefined behavior. * lisp.h, src/m/amdx86-64.h, src/m/ia64.h, src/m/ibms390x.h (pEd): New macro. * lisp.h (error, verror): Mark as printf-like functions. * eval.c (verror): Use vsnprintf, not doprnt, to do the real work. Report overflow in size calculations when allocating printf buffer. Do not truncate output string at its first null byte. * xdisp.c (vmessage): Use vsnprintf, not doprnt, to do the real work. Truncate the output at a character boundary, since vsnprintf does not do that. * charset.c (check_iso_charset_parameter): Convert internal character to string before calling 'error', since %c now has the printf meaning. * coding.c (Fdecode_sjis_char, Fdecode_big5_char): Avoid int overflow when computing char to be passed to 'error'. Do not pass Lisp_Object to 'error'; pass the integer instead. * nsfns.m (Fns_do_applescript): Use int, not long, since it's formatted with plain %d.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog22
-rw-r--r--src/category.c4
-rw-r--r--src/charset.c18
-rw-r--r--src/coding.c53
-rw-r--r--src/doc.c4
-rw-r--r--src/eval.c21
-rw-r--r--src/fns.c2
-rw-r--r--src/intervals.c2
-rw-r--r--src/lisp.h7
-rw-r--r--src/m/amdx86-64.h1
-rw-r--r--src/m/ia64.h1
-rw-r--r--src/m/ibms390x.h2
-rw-r--r--src/nsfns.m15
-rw-r--r--src/sysdep.c3
-rw-r--r--src/window.c4
-rw-r--r--src/xdisp.c16
-rw-r--r--src/xfns.c2
17 files changed, 117 insertions, 60 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 6f2509429d2..c1bea6b4cc7 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,27 @@
2011-04-07 Paul Eggert <eggert@cs.ucla.edu>
+ error: Print 32- and 64-bit integers portably (Bug#8435).
+ Without this change, on typical 64-bit hosts error ("...%d...", N)
+ was used to print both 32- and 64-bit integers N, which relied on
+ undefined behavior.
+ * lisp.h, src/m/amdx86-64.h, src/m/ia64.h, src/m/ibms390x.h (pEd):
+ New macro.
+ * lisp.h (error, verror): Mark as printf-like functions.
+ * eval.c (verror): Use vsnprintf, not doprnt, to do the real work.
+ Report overflow in size calculations when allocating printf buffer.
+ Do not truncate output string at its first null byte.
+ * xdisp.c (vmessage): Use vsnprintf, not doprnt, to do the real work.
+ Truncate the output at a character boundary, since vsnprintf does not
+ do that.
+ * charset.c (check_iso_charset_parameter): Convert internal
+ character to string before calling 'error', since %c now has the
+ printf meaning.
+ * coding.c (Fdecode_sjis_char, Fdecode_big5_char): Avoid int
+ overflow when computing char to be passed to 'error'. Do not
+ pass Lisp_Object to 'error'; pass the integer instead.
+ * nsfns.m (Fns_do_applescript): Use int, not long, since it's
+ formatted with plain %d.
+
* eval.c (internal_lisp_condition_case): Don't pass spurious arg.
* keyboard.c (access_keymap_keyremap): Print func name, not garbage.
diff --git a/src/category.c b/src/category.c
index cc7ff88474f..bba030360c4 100644
--- a/src/category.c
+++ b/src/category.c
@@ -128,7 +128,7 @@ the current buffer's category table. */)
table = check_category_table (table);
if (!NILP (CATEGORY_DOCSTRING (table, XFASTINT (category))))
- error ("Category `%c' is already defined", XFASTINT (category));
+ error ("Category `%c' is already defined", (int) XFASTINT (category));
if (!NILP (Vpurify_flag))
docstring = Fpurecopy (docstring);
CATEGORY_DOCSTRING (table, XFASTINT (category)) = docstring;
@@ -373,7 +373,7 @@ then delete CATEGORY from the category set instead of adding it. */)
table = check_category_table (table);
if (NILP (CATEGORY_DOCSTRING (table, XFASTINT (category))))
- error ("Undefined category: %c", XFASTINT (category));
+ error ("Undefined category: %c", (int) XFASTINT (category));
set_value = NILP (reset) ? Qt : Qnil;
diff --git a/src/charset.c b/src/charset.c
index 32836d459f3..55cbfc4a399 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -493,7 +493,7 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int co
unbind_to (count, Qnil);
if (fd < 0
|| ! (fp = fdopen (fd, "r")))
- error ("Failure in loading charset map: %S", SDATA (mapfile));
+ error ("Failure in loading charset map: %s", SDATA (mapfile));
/* Use SAFE_ALLOCA instead of alloca, as `charset_map_entries' is
large (larger than MAX_ALLOCA). */
@@ -1000,7 +1000,7 @@ usage: (define-charset-internal ...) */)
{
CHECK_NUMBER (val);
if (XINT (val) < '0' || XINT (val) > 127)
- error ("Invalid iso-final-char: %d", XINT (val));
+ error ("Invalid iso-final-char: %"pEd, XINT (val));
charset.iso_final = XINT (val);
}
@@ -1022,7 +1022,7 @@ usage: (define-charset-internal ...) */)
{
CHECK_NATNUM (val);
if ((XINT (val) > 0 && XINT (val) <= 128) || XINT (val) >= 256)
- error ("Invalid emacs-mule-id: %d", XINT (val));
+ error ("Invalid emacs-mule-id: %"pEd, XINT (val));
charset.emacs_mule_id = XINT (val);
}
@@ -1440,11 +1440,17 @@ check_iso_charset_parameter (Lisp_Object dimension, Lisp_Object chars, Lisp_Obje
CHECK_NATNUM (final_char);
if (XINT (dimension) > 3)
- error ("Invalid DIMENSION %d, it should be 1, 2, or 3", XINT (dimension));
+ error ("Invalid DIMENSION %"pEd", it should be 1, 2, or 3",
+ XINT (dimension));
if (XINT (chars) != 94 && XINT (chars) != 96)
- error ("Invalid CHARS %d, it should be 94 or 96", XINT (chars));
+ error ("Invalid CHARS %"pEd", it should be 94 or 96", XINT (chars));
if (XINT (final_char) < '0' || XINT (final_char) > '~')
- error ("Invalid FINAL-CHAR %c, it should be `0'..`~'", XINT (chars));
+ {
+ unsigned char str[MAX_MULTIBYTE_LENGTH + 1];
+ int len = CHAR_STRING (XINT (chars), str);
+ str[len] = '\0';
+ error ("Invalid FINAL-CHAR %s, it should be `0'..`~'", str);
+ }
}
diff --git a/src/coding.c b/src/coding.c
index 798e5c533f6..f099605c774 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -9023,14 +9023,15 @@ Return the corresponding character. */)
{
Lisp_Object spec, attrs, val;
struct charset *charset_roman, *charset_kanji, *charset_kana, *charset;
- EMACS_INT c;
+ EMACS_INT ch;
+ int c;
CHECK_NATNUM (code);
- c = XFASTINT (code);
+ ch = XFASTINT (code);
CHECK_CODING_SYSTEM_GET_SPEC (Vsjis_coding_system, spec);
attrs = AREF (spec, 0);
- if (ASCII_BYTE_P (c)
+ if (ASCII_BYTE_P (ch)
&& ! NILP (CODING_ATTR_ASCII_COMPAT (attrs)))
return code;
@@ -9039,27 +9040,31 @@ Return the corresponding character. */)
charset_kana = CHARSET_FROM_ID (XINT (XCAR (val))), val = XCDR (val);
charset_kanji = CHARSET_FROM_ID (XINT (XCAR (val)));
- if (c <= 0x7F)
- charset = charset_roman;
- else if (c >= 0xA0 && c < 0xDF)
+ if (ch <= 0x7F)
+ {
+ c = ch;
+ charset = charset_roman;
+ }
+ else if (ch >= 0xA0 && ch < 0xDF)
{
+ c = ch - 0x80;
charset = charset_kana;
- c -= 0x80;
}
else
{
- EMACS_INT c1 = c >> 8;
- int c2 = c & 0xFF;
+ EMACS_INT c1 = ch >> 8;
+ int c2 = ch & 0xFF;
if (c1 < 0x81 || (c1 > 0x9F && c1 < 0xE0) || c1 > 0xEF
|| c2 < 0x40 || c2 == 0x7F || c2 > 0xFC)
- error ("Invalid code: %d", code);
+ error ("Invalid code: %"pEd, ch);
+ c = ch;
SJIS_TO_JIS (c);
charset = charset_kanji;
}
c = DECODE_CHAR (charset, c);
if (c < 0)
- error ("Invalid code: %d", code);
+ error ("Invalid code: %"pEd, ch);
return make_number (c);
}
@@ -9099,14 +9104,15 @@ Return the corresponding character. */)
{
Lisp_Object spec, attrs, val;
struct charset *charset_roman, *charset_big5, *charset;
+ EMACS_INT ch;
int c;
CHECK_NATNUM (code);
- c = XFASTINT (code);
+ ch = XFASTINT (code);
CHECK_CODING_SYSTEM_GET_SPEC (Vbig5_coding_system, spec);
attrs = AREF (spec, 0);
- if (ASCII_BYTE_P (c)
+ if (ASCII_BYTE_P (ch)
&& ! NILP (CODING_ATTR_ASCII_COMPAT (attrs)))
return code;
@@ -9114,19 +9120,24 @@ Return the corresponding character. */)
charset_roman = CHARSET_FROM_ID (XINT (XCAR (val))), val = XCDR (val);
charset_big5 = CHARSET_FROM_ID (XINT (XCAR (val)));
- if (c <= 0x7F)
- charset = charset_roman;
+ if (ch <= 0x7F)
+ {
+ c = ch;
+ charset = charset_roman;
+ }
else
{
- int b1 = c >> 8, b2 = c & 0x7F;
+ EMACS_INT b1 = ch >> 8;
+ int b2 = ch & 0x7F;
if (b1 < 0xA1 || b1 > 0xFE
|| b2 < 0x40 || (b2 > 0x7E && b2 < 0xA1) || b2 > 0xFE)
- error ("Invalid code: %d", code);
+ error ("Invalid code: %"pEd, ch);
+ c = ch;
charset = charset_big5;
}
- c = DECODE_CHAR (charset, (unsigned )c);
+ c = DECODE_CHAR (charset, c);
if (c < 0)
- error ("Invalid code: %d", code);
+ error ("Invalid code: %"pEd, ch);
return make_number (c);
}
@@ -9298,7 +9309,7 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS...) */)
|| (EQ (operation, Qinsert_file_contents) && CONSP (target)
&& STRINGP (XCAR (target)) && BUFFERP (XCDR (target)))
|| (EQ (operation, Qopen_network_stream) && INTEGERP (target))))
- error ("Invalid %dth argument", XFASTINT (target_idx) + 1);
+ error ("Invalid %"pEd"th argument", XFASTINT (target_idx) + 1);
if (CONSP (target))
target = XCAR (target);
@@ -9774,7 +9785,7 @@ usage: (define-coding-system-internal ...) */)
CHECK_CHARSET_GET_ID (tmp1, id);
CHECK_NATNUM_CDR (val);
if (XINT (XCDR (val)) >= 4)
- error ("Invalid graphic register number: %d", XINT (XCDR (val)));
+ error ("Invalid graphic register number: %"pEd, XINT (XCDR (val)));
XSETCAR (val, make_number (id));
}
diff --git a/src/doc.c b/src/doc.c
index 158b09790f7..ed0d2323ed5 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -154,7 +154,7 @@ get_doc_string (Lisp_Object filepos, int unibyte, int definition)
if (0 > lseek (fd, position - offset, 0))
{
emacs_close (fd);
- error ("Position %ld out of range in doc string file \"%s\"",
+ error ("Position %"pEd" out of range in doc string file \"%s\"",
position, name);
}
@@ -669,7 +669,7 @@ the same file name is found in the `doc-directory'. */)
; /* Just a source file name boundary marker. Ignore it. */
else
- error ("DOC file invalid at position %d", pos);
+ error ("DOC file invalid at position %"pEd, pos);
}
}
pos += end - buf;
diff --git a/src/eval.c b/src/eval.c
index 8b029967e7a..77411a911ee 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1977,21 +1977,26 @@ void
verror (const char *m, va_list ap)
{
char buf[200];
- EMACS_INT size = 200;
- int mlen;
+ size_t size = sizeof buf;
+ size_t size_max = (size_t) -1;
char *buffer = buf;
int allocated = 0;
+ int used;
Lisp_Object string;
- mlen = strlen (m);
-
while (1)
{
- EMACS_INT used;
- used = doprnt (buffer, size, m, m + mlen, ap);
+ used = vsnprintf (buffer, size, m, ap);
+ if (used < 0)
+ used = 0;
if (used < size)
break;
- size *= 2;
+ if (size <= size_max / 2)
+ size *= 2;
+ else if (size < size_max)
+ size = size_max;
+ else
+ memory_full ();
if (allocated)
buffer = (char *) xrealloc (buffer, size);
else
@@ -2001,7 +2006,7 @@ verror (const char *m, va_list ap)
}
}
- string = build_string (buffer);
+ string = make_string (buffer, used);
if (allocated)
xfree (buffer);
diff --git a/src/fns.c b/src/fns.c
index c45d9e31ef2..09ce8c1b597 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1076,7 +1076,7 @@ an error is signaled. */)
EMACS_INT converted = str_to_unibyte (SDATA (string), str, chars, 0);
if (converted < chars)
- error ("Can't convert the %dth character to unibyte", converted);
+ error ("Can't convert the %"pEd"th character to unibyte", converted);
string = make_unibyte_string ((char *) str, chars);
xfree (str);
}
diff --git a/src/intervals.c b/src/intervals.c
index 729e6810f74..952f826778c 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -777,7 +777,7 @@ update_interval (register INTERVAL i, EMACS_INT pos)
i = i->right; /* Move to the right child */
}
else if (NULL_PARENT (i))
- error ("Point %d after end of properties", pos);
+ error ("Point %"pEd" after end of properties", pos);
else
i = INTERVAL_PARENT (i);
continue;
diff --git a/src/lisp.h b/src/lisp.h
index 41a64d2f47d..7999fb42d5f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -38,6 +38,7 @@ extern void check_cons_list (void);
#ifndef EMACS_INT
#define EMACS_INT long
#define BITS_PER_EMACS_INT BITS_PER_LONG
+#define pEd "ld"
#endif
#ifndef EMACS_UINT
#define EMACS_UINT unsigned long
@@ -46,6 +47,7 @@ extern void check_cons_list (void);
#ifndef EMACS_INT
#define EMACS_INT int
#define BITS_PER_EMACS_INT BITS_PER_INT
+#define pEd "d"
#endif
#ifndef EMACS_UINT
#define EMACS_UINT unsigned int
@@ -2872,8 +2874,9 @@ extern Lisp_Object internal_condition_case_n (Lisp_Object (*) (size_t, Lisp_Obje
extern void specbind (Lisp_Object, Lisp_Object);
extern void record_unwind_protect (Lisp_Object (*) (Lisp_Object), Lisp_Object);
extern Lisp_Object unbind_to (int, Lisp_Object);
-extern void error (const char *, ...) NO_RETURN;
-extern void verror (const char *, va_list) NO_RETURN;
+extern void error (const char *, ...) NO_RETURN ATTRIBUTE_FORMAT_PRINTF (1, 2);
+extern void verror (const char *, va_list)
+ NO_RETURN ATTRIBUTE_FORMAT_PRINTF (1, 0);
extern void do_autoload (Lisp_Object, Lisp_Object);
extern Lisp_Object un_autoload (Lisp_Object);
EXFUN (Ffetch_bytecode, 1);
diff --git a/src/m/amdx86-64.h b/src/m/amdx86-64.h
index 441f41b4444..dbca9b5b838 100644
--- a/src/m/amdx86-64.h
+++ b/src/m/amdx86-64.h
@@ -28,6 +28,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Define the type to use. */
#define EMACS_INT long
+#define pEd "ld"
#define EMACS_UINT unsigned long
/* Define XPNTR to avoid or'ing with DATA_SEG_BITS */
diff --git a/src/m/ia64.h b/src/m/ia64.h
index 101d56e648b..a1374d7c224 100644
--- a/src/m/ia64.h
+++ b/src/m/ia64.h
@@ -28,6 +28,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Define the type to use. */
#define EMACS_INT long
+#define pEd "ld"
#define EMACS_UINT unsigned long
#ifdef REL_ALLOC
diff --git a/src/m/ibms390x.h b/src/m/ibms390x.h
index d4ef5c291ef..14228b61e56 100644
--- a/src/m/ibms390x.h
+++ b/src/m/ibms390x.h
@@ -24,6 +24,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Define the type to use. */
#define EMACS_INT long
+#define pEd "ld"
#define EMACS_UINT unsigned long
/* On the 64 bit architecture, we can use 60 bits for addresses */
@@ -31,4 +32,3 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Define XPNTR to avoid or'ing with DATA_SEG_BITS */
#define XPNTR(a) XUINT (a)
-
diff --git a/src/nsfns.m b/src/nsfns.m
index 6a5adbd7bf3..d4445d1d627 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -483,7 +483,7 @@ ns_set_name_internal (FRAME_PTR f, Lisp_Object name)
if (!STRINGP (f->icon_name))
encoded_icon_name = encoded_name;
else
- encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
+ encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
str = [NSString stringWithUTF8String: SDATA (encoded_icon_name)];
@@ -637,7 +637,7 @@ ns_set_name_as_filename (struct frame *f)
if (FRAME_ICONIFIED_P (f))
[[view window] setMiniwindowTitle: str];
- else
+ else
{
NSString *fstr;
@@ -1021,8 +1021,8 @@ frame_parm_handler ns_frame_parm_handlers[] =
0, /* x_set_fullscreen will ignore */
x_set_font_backend, /* generic OK */
x_set_alpha,
- 0, /* x_set_sticky */
- 0, /* x_set_tool_bar_position */
+ 0, /* x_set_sticky */
+ 0, /* x_set_tool_bar_position */
};
@@ -2044,7 +2044,7 @@ In case the execution fails, an error is signaled. */)
(Lisp_Object script)
{
Lisp_Object result;
- long status;
+ int status;
CHECK_STRING (script);
check_ns ();
@@ -2330,7 +2330,7 @@ If omitted or nil, that stands for the selected frame's display. */)
{
struct ns_display_info *dpyinfo;
check_ns ();
-
+
dpyinfo = check_ns_display_info (display);
/* We force 24+ bit depths to 24-bit to prevent an overflow. */
return make_number (1 << min (dpyinfo->n_planes, 24));
@@ -2373,7 +2373,7 @@ compute_tip_xy (struct frame *f,
pt.y = x_display_pixel_height (FRAME_NS_DISPLAY_INFO (f)) - XINT (top)
- height;
}
-
+
/* Ensure in bounds. (Note, screen origin = lower left.) */
if (INTEGERP (left))
*root_x = pt.x;
@@ -2655,4 +2655,3 @@ be used as the image of the icon representing the frame. */);
check_window_system_func = check_ns;
}
-
diff --git a/src/sysdep.c b/src/sysdep.c
index a165a9ca52f..f4f767dac3f 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -2361,7 +2361,8 @@ serial_configure (struct Lisp_Process *p,
CHECK_NUMBER (tem);
err = cfsetspeed (&attr, XINT (tem));
if (err != 0)
- error ("cfsetspeed(%d) failed: %s", XINT (tem), emacs_strerror (errno));
+ error ("cfsetspeed(%"pEd") failed: %s", XINT (tem),
+ emacs_strerror (errno));
childp2 = Fplist_put (childp2, QCspeed, tem);
/* Configure bytesize. */
diff --git a/src/window.c b/src/window.c
index 5ca46dd3316..ebfd1b0f778 100644
--- a/src/window.c
+++ b/src/window.c
@@ -3804,7 +3804,7 @@ See Info node `(elisp)Splitting Windows' for more details and examples. */)
error ("Window height %d too small (after splitting)", size_int);
if (size_int + window_safe_height > XFASTINT (o->total_lines))
error ("Window height %d too small (after splitting)",
- XFASTINT (o->total_lines) - size_int);
+ (int) (XFASTINT (o->total_lines) - size_int));
if (NILP (o->parent)
|| NILP (XWINDOW (o->parent)->vchild))
{
@@ -3821,7 +3821,7 @@ See Info node `(elisp)Splitting Windows' for more details and examples. */)
error ("Window width %d too small (after splitting)", size_int);
if (size_int + window_safe_width > XFASTINT (o->total_cols))
error ("Window width %d too small (after splitting)",
- XFASTINT (o->total_cols) - size_int);
+ (int) (XFASTINT (o->total_cols) - size_int));
if (NILP (o->parent)
|| NILP (XWINDOW (o->parent)->hchild))
{
diff --git a/src/xdisp.c b/src/xdisp.c
index 16954d0f809..a296fb33a9f 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -8407,10 +8407,18 @@ vmessage (const char *m, va_list ap)
{
if (m)
{
- EMACS_INT len;
-
- len = doprnt (FRAME_MESSAGE_BUF (f),
- FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap);
+ char *buf = FRAME_MESSAGE_BUF (f);
+ size_t bufsize = FRAME_MESSAGE_BUF_SIZE (f);
+ int len = vsnprintf (buf, bufsize, m, ap);
+ if (len < 0)
+ len = 0;
+
+ /* Do any truncation at a character boundary. */
+ if (0 < bufsize && bufsize <= len)
+ for (len = bufsize - 1;
+ len && ! CHAR_HEAD_P (buf[len - 1]);
+ len--)
+ continue;
message2 (FRAME_MESSAGE_BUF (f), len, 0);
}
diff --git a/src/xfns.c b/src/xfns.c
index 8e5639681df..04b8e44b561 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -215,7 +215,7 @@ check_x_display_info (Lisp_Object object)
struct terminal *t = get_terminal (object, 1);
if (t->type != output_x_window)
- error ("Terminal %d is not an X display", XINT (object));
+ error ("Terminal %"pEd" is not an X display", XINT (object));
dpyinfo = t->display_info.x;
}