[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] /srv/bzr/emacs/trunk r104390: Merge: Integer overflow fixe
From: |
Paul Eggert |
Subject: |
[Emacs-diffs] /srv/bzr/emacs/trunk r104390: Merge: Integer overflow fixes. |
Date: |
Fri, 27 May 2011 13:32:41 -0700 |
User-agent: |
Bazaar (2.3.1) |
------------------------------------------------------------
revno: 104390 [merge]
fixes bug(s): http://debbugs.gnu.org/8722 http://debbugs.gnu.org/8719
http://debbugs.gnu.org/8668
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Fri 2011-05-27 13:32:41 -0700
message:
Merge: Integer overflow fixes.
modified:
src/ChangeLog
src/alloc.c
src/ccl.c
src/character.c
src/character.h
src/data.c
src/dbusbind.c
src/editfns.c
src/fns.c
src/insdel.c
src/lisp.h
src/mem-limits.h
src/print.c
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog 2011-05-27 19:39:18 +0000
+++ b/src/ChangeLog 2011-05-27 19:58:54 +0000
@@ -1,3 +1,85 @@
+2011-05-27 Paul Eggert <address@hidden>
+
+ Integer overflow fixes.
+
+ * dbusbind.c: Serial number integer overflow fixes.
+ (CHECK_DBUS_SERIAL_GET_SERIAL): New macro.
+ (Fdbus_call_method_asynchronously, xd_read_message_1): Use a float
+ to hold a serial number that is too large for a fixnum.
+ (Fdbus_method_return_internal, Fdbus_method_error_internal):
+ Check for serial numbers out of range. Decode any serial number
+ that was so large that it became a float. (Bug#8722)
+
+ * dbusbind.c: Use XFASTINT rather than XUINT, and check for nonneg.
+ (Fdbus_call_method, Fdbus_call_method_asynchronously):
+ Use XFASTINT rather than XUINT when numbers are nonnegative.
+ (xd_append_arg, Fdbus_method_return_internal):
+ (Fdbus_method_error_internal): Likewise. Also, for unsigned
+ arguments, check that Lisp number is nonnegative, rather than
+ silently wrapping negative numbers around. (Bug#8722)
+ (xd_read_message_1): Don't assume dbus_uint32_t can fit in int.
+ (Bug#8722)
+
+ * data.c (arith_driver, Flsh): Avoid unnecessary casts to EMACS_UINT.
+
+ * ccl.c (ccl_driver): Redo slightly to avoid the need for 'unsigned'.
+
+ ccl: add integer overflow checks
+ * ccl.c (CCL_CODE_MAX, GET_CCL_RANGE, GET_CCL_CODE, GET_CCL_INT):
+ (IN_INT_RANGE): New macros.
+ (ccl_driver): Use them to check for integer overflow when
+ decoding a CCL program. Many of the new checks are whether XINT (x)
+ fits in int; it doesn't always, on 64-bit hosts. The new version
+ doesn't catch all possible integer overflows, but it's an
+ improvement. (Bug#8719)
+
+ * alloc.c (make_event_array): Use XINT, not XUINT.
+ There's no need for unsigned here.
+
+ * mem-limits.h (EXCEEDS_LISP_PTR) [!USE_LSB_TAG]: EMACS_UINT ->
uintptr_t
+ This follows up to the 2011-05-06 change that substituted uintptr_t
+ for EMACS_INT. This case wasn't caught back then.
+
+ Rework Fformat to avoid integer overflow issues.
+ * editfns.c: Include <float.h> unconditionally, as it's everywhere
+ now (part of C89). Include <verify.h>.
+ (MAX_10_EXP, CONVERTED_BYTE_SIZE): Remove; no longer needed.
+ (pWIDE, pWIDElen, signed_wide, unsigned_wide): New defns.
+ (Fformat): Avoid the prepass trying to compute sizes; it was only
+ approximate and thus did not catch overflow reliably. Instead, walk
+ through the format just once, formatting and computing sizes as we go,
+ checking for integer overflow at every step, and allocating a larger
+ buffer as needed. Keep track separately whether the format is
+ multibyte. Keep only the most-recently calculated precision, rather
+ than them all. Record whether each argument has been converted to
+ string. Use EMACS_INT, not int, for byte and char and arg counts.
+ Support field widths and precisions larger than INT_MAX. Avoid
+ sprintf's undefined behavior with conversion specifications such as %#d
+ and %.0c. Fix bug with strchr succeeding on '\0' when looking for
+ flags. Fix bug with (format "%c" 256.0). Avoid integer overflow when
+ formatting out-of-range floating point numbers with int
+ formats. (Bug#8668)
+
+ * lisp.h (FIXNUM_OVERFLOW_P): Work even if arg is a NaN.
+
+ * data.c: Avoid integer truncation in expressions involving floats.
+ * data.c: Include <intprops.h>.
+ (arith_driver): When there's an integer overflow in an expression
+ involving floating point, convert the integers to floating point
+ so that the resulting value does not suffer from catastrophic
+ integer truncation. For example, on a 64-bit host (* 4
+ most-negative-fixnum 0.5) should yield about -4.6e+18, not zero.
+ Do not rely on undefined behavior after integer overflow.
+
+ merge count_size_as_multibyte, parse_str_to_multibyte
+ * character.c, character.h (count_size_as_multibyte):
+ Renamed from parse_str_to_multibyte; all uses changed.
+ Check for integer overflow.
+ * insdel.c, lisp.h (count_size_as_multibyte): Remove,
+ since it's now a duplicate of the other. This is more of
+ a character than a buffer op, so better that it's in character.c.
+ * fns.c, print.c: Adjust to above changes.
+
2011-05-27 Stefan Monnier <address@hidden>
* xselect.c (x_convert_selection): Yet another int/Lisp_Object mixup.
=== modified file 'src/alloc.c'
--- a/src/alloc.c 2011-05-16 01:11:54 +0000
+++ b/src/alloc.c 2011-05-23 00:31:35 +0000
@@ -3244,7 +3244,7 @@
are characters that are in 0...127,
after discarding the meta bit and all the bits above it. */
if (!INTEGERP (args[i])
- || (XUINT (args[i]) & ~(-CHAR_META)) >= 0200)
+ || (XINT (args[i]) & ~(-CHAR_META)) >= 0200)
return Fvector (nargs, args);
/* Since the loop exited, we know that all the things in it are
=== modified file 'src/ccl.c'
--- a/src/ccl.c 2011-05-12 07:07:06 +0000
+++ b/src/ccl.c 2011-05-23 06:58:38 +0000
@@ -98,6 +98,8 @@
and `rrr' are CCL register number, `XXXXX' is one of the following
CCL commands. */
+#define CCL_CODE_MAX ((1 << (28 - 1)) - 1)
+
/* CCL commands
Each comment fields shows one or more lines for command syntax and
@@ -742,6 +744,24 @@
#endif
+#define GET_CCL_RANGE(var, ccl_prog, ic, lo, hi) \
+ do \
+ { \
+ EMACS_INT prog_word = XINT ((ccl_prog)[ic]); \
+ if (! ((lo) <= prog_word && prog_word <= (hi))) \
+ CCL_INVALID_CMD; \
+ (var) = prog_word; \
+ } \
+ while (0)
+
+#define GET_CCL_CODE(code, ccl_prog, ic) \
+ GET_CCL_RANGE (code, ccl_prog, ic, 0, CCL_CODE_MAX)
+
+#define GET_CCL_INT(var, ccl_prog, ic) \
+ GET_CCL_RANGE (var, ccl_prog, ic, INT_MIN, INT_MAX)
+
+#define IN_INT_RANGE(val) (INT_MIN <= (val) && (val) <= INT_MAX)
+
/* Encode one character CH to multibyte form and write to the current
output buffer. If CH is less than 256, CH is written as is. */
#define CCL_WRITE_CHAR(ch) \
@@ -899,7 +919,7 @@
}
this_ic = ic;
- code = XINT (ccl_prog[ic]); ic++;
+ GET_CCL_CODE (code, ccl_prog, ic++);
field1 = code >> 8;
field2 = (code & 0xFF) >> 5;
@@ -920,15 +940,14 @@
break;
case CCL_SetConst: /* 00000000000000000000rrrXXXXX */
- reg[rrr] = XINT (ccl_prog[ic]);
- ic++;
+ GET_CCL_INT (reg[rrr], ccl_prog, ic++);
break;
case CCL_SetArray: /* CCCCCCCCCCCCCCCCCCCCRRRrrrXXXXX */
i = reg[RRR];
j = field1 >> 3;
- if ((unsigned int) i < j)
- reg[rrr] = XINT (ccl_prog[ic + i]);
+ if (0 <= i && i < j)
+ GET_CCL_INT (reg[rrr], ccl_prog, ic + i);
ic += j;
break;
@@ -956,13 +975,13 @@
break;
case CCL_WriteConstJump: /* A--D--D--R--E--S--S-000XXXXX */
- i = XINT (ccl_prog[ic]);
+ GET_CCL_INT (i, ccl_prog, ic);
CCL_WRITE_CHAR (i);
ic += ADDR;
break;
case CCL_WriteConstReadJump: /* A--D--D--R--E--S--S-rrrXXXXX */
- i = XINT (ccl_prog[ic]);
+ GET_CCL_INT (i, ccl_prog, ic);
CCL_WRITE_CHAR (i);
ic++;
CCL_READ_CHAR (reg[rrr]);
@@ -970,18 +989,17 @@
break;
case CCL_WriteStringJump: /* A--D--D--R--E--S--S-000XXXXX */
- j = XINT (ccl_prog[ic]);
- ic++;
+ GET_CCL_INT (j, ccl_prog, ic++);
CCL_WRITE_STRING (j);
ic += ADDR - 1;
break;
case CCL_WriteArrayReadJump: /* A--D--D--R--E--S--S-rrrXXXXX */
i = reg[rrr];
- j = XINT (ccl_prog[ic]);
- if ((unsigned int) i < j)
+ GET_CCL_INT (j, ccl_prog, ic);
+ if (0 <= i && i < j)
{
- i = XINT (ccl_prog[ic + 1 + i]);
+ GET_CCL_INT (i, ccl_prog, ic + 1 + i);
CCL_WRITE_CHAR (i);
}
ic += j + 2;
@@ -998,10 +1016,14 @@
CCL_READ_CHAR (reg[rrr]);
/* fall through ... */
case CCL_Branch: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
- if ((unsigned int) reg[rrr] < field1)
- ic += XINT (ccl_prog[ic + reg[rrr]]);
- else
- ic += XINT (ccl_prog[ic + field1]);
+ {
+ int incr;
+ GET_CCL_INT (incr, ccl_prog,
+ ic + (0 <= reg[rrr] && reg[rrr] < field1
+ ? reg[rrr]
+ : field1));
+ ic += incr;
+ }
break;
case CCL_ReadRegister: /* CCCCCCCCCCCCCCCCCCCCrrXXXXX */
@@ -1009,7 +1031,7 @@
{
CCL_READ_CHAR (reg[rrr]);
if (!field1) break;
- code = XINT (ccl_prog[ic]); ic++;
+ GET_CCL_CODE (code, ccl_prog, ic++);
field1 = code >> 8;
field2 = (code & 0xFF) >> 5;
}
@@ -1018,7 +1040,7 @@
case CCL_WriteExprConst: /* 1:00000OPERATION000RRR000XXXXX */
rrr = 7;
i = reg[RRR];
- j = XINT (ccl_prog[ic]);
+ GET_CCL_INT (j, ccl_prog, ic);
op = field1 >> 6;
jump_address = ic + 1;
goto ccl_set_expr;
@@ -1029,7 +1051,7 @@
i = reg[rrr];
CCL_WRITE_CHAR (i);
if (!field1) break;
- code = XINT (ccl_prog[ic]); ic++;
+ GET_CCL_CODE (code, ccl_prog, ic++);
field1 = code >> 8;
field2 = (code & 0xFF) >> 5;
}
@@ -1051,10 +1073,7 @@
/* If FFF is nonzero, the CCL program ID is in the
following code. */
if (rrr)
- {
- prog_id = XINT (ccl_prog[ic]);
- ic++;
- }
+ GET_CCL_INT (prog_id, ccl_prog, ic++);
else
prog_id = field1;
@@ -1095,9 +1114,9 @@
case CCL_WriteArray: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
i = reg[rrr];
- if ((unsigned int) i < field1)
+ if (0 <= i && i < field1)
{
- j = XINT (ccl_prog[ic + i]);
+ GET_CCL_INT (j, ccl_prog, ic + i);
CCL_WRITE_CHAR (j);
}
ic += field1;
@@ -1122,8 +1141,7 @@
CCL_SUCCESS;
case CCL_ExprSelfConst: /* 00000OPERATION000000rrrXXXXX */
- i = XINT (ccl_prog[ic]);
- ic++;
+ GET_CCL_INT (i, ccl_prog, ic++);
op = field1 >> 6;
goto ccl_expr_self;
@@ -1159,9 +1177,9 @@
case CCL_SetExprConst: /* 00000OPERATION000RRRrrrXXXXX */
i = reg[RRR];
- j = XINT (ccl_prog[ic]);
+ GET_CCL_INT (j, ccl_prog, ic++);
op = field1 >> 6;
- jump_address = ++ic;
+ jump_address = ic;
goto ccl_set_expr;
case CCL_SetExprReg: /* 00000OPERATIONRrrRRRrrrXXXXX */
@@ -1175,10 +1193,9 @@
CCL_READ_CHAR (reg[rrr]);
case CCL_JumpCondExprConst: /* A--D--D--R--E--S--S-rrrXXXXX */
i = reg[rrr];
- op = XINT (ccl_prog[ic]);
- jump_address = ic++ + ADDR;
- j = XINT (ccl_prog[ic]);
- ic++;
+ jump_address = ic + ADDR;
+ GET_CCL_INT (op, ccl_prog, ic++);
+ GET_CCL_INT (j, ccl_prog, ic++);
rrr = 7;
goto ccl_set_expr;
@@ -1186,10 +1203,10 @@
CCL_READ_CHAR (reg[rrr]);
case CCL_JumpCondExprReg:
i = reg[rrr];
- op = XINT (ccl_prog[ic]);
- jump_address = ic++ + ADDR;
- j = reg[XINT (ccl_prog[ic])];
- ic++;
+ jump_address = ic + ADDR;
+ GET_CCL_INT (op, ccl_prog, ic++);
+ GET_CCL_RANGE (j, ccl_prog, ic++, 0, 7);
+ j = reg[j];
rrr = 7;
ccl_set_expr:
@@ -1267,18 +1284,27 @@
break;
case CCL_TranslateCharacterConstTbl:
- op = XINT (ccl_prog[ic]); /* table */
- ic++;
- i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
- op = translate_char (GET_TRANSLATION_TABLE (op), i);
- CCL_ENCODE_CHAR (op, charset_list, reg[RRR], reg[rrr]);
+ {
+ EMACS_INT eop;
+ GET_CCL_RANGE (eop, ccl_prog, ic++, 0,
+ (VECTORP (Vtranslation_table_vector)
+ ? ASIZE (Vtranslation_table_vector)
+ : -1));
+ i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
+ op = translate_char (GET_TRANSLATION_TABLE (eop), i);
+ CCL_ENCODE_CHAR (op, charset_list, reg[RRR], reg[rrr]);
+ }
break;
case CCL_LookupIntConstTbl:
- op = XINT (ccl_prog[ic]); /* table */
- ic++;
{
- struct Lisp_Hash_Table *h = GET_HASH_TABLE (op);
+ EMACS_INT eop;
+ struct Lisp_Hash_Table *h;
+ GET_CCL_RANGE (eop, ccl_prog, ic++, 0,
+ (VECTORP (Vtranslation_hash_table_vector)
+ ? ASIZE (Vtranslation_hash_table_vector)
+ : -1));
+ h = GET_HASH_TABLE (eop);
op = hash_lookup (h, make_number (reg[RRR]), NULL);
if (op >= 0)
@@ -1297,18 +1323,22 @@
break;
case CCL_LookupCharConstTbl:
- op = XINT (ccl_prog[ic]); /* table */
- ic++;
- i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
{
- struct Lisp_Hash_Table *h = GET_HASH_TABLE (op);
+ EMACS_INT eop;
+ struct Lisp_Hash_Table *h;
+ GET_CCL_RANGE (eop, ccl_prog, ic++, 0,
+ (VECTORP (Vtranslation_hash_table_vector)
+ ? ASIZE (Vtranslation_hash_table_vector)
+ : -1));
+ i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
+ h = GET_HASH_TABLE (eop);
op = hash_lookup (h, make_number (i), NULL);
if (op >= 0)
{
Lisp_Object opl;
opl = HASH_VALUE (h, op);
- if (!INTEGERP (opl))
+ if (! (INTEGERP (opl) && IN_INT_RANGE (XINT (opl))))
CCL_INVALID_CMD;
reg[RRR] = XINT (opl);
reg[7] = 1; /* r7 true for success */
@@ -1321,9 +1351,10 @@
case CCL_IterateMultipleMap:
{
Lisp_Object map, content, attrib, value;
- int point, size, fin_ic;
+ EMACS_INT point, size;
+ int fin_ic;
- j = XINT (ccl_prog[ic++]); /* number of maps. */
+ GET_CCL_INT (j, ccl_prog, ic++); /* number of maps. */
fin_ic = ic + j;
op = reg[rrr];
if ((j > reg[RRR]) && (j >= 0))
@@ -1343,7 +1374,7 @@
size = ASIZE (Vcode_conversion_map_vector);
point = XINT (ccl_prog[ic++]);
- if (point >= size) continue;
+ if (! (0 <= point && point < size)) continue;
map = AREF (Vcode_conversion_map_vector, point);
/* Check map validity. */
@@ -1358,18 +1389,19 @@
/* check map type,
[STARTPOINT VAL1 VAL2 ...] or
[t ELEMENT STARTPOINT ENDPOINT] */
- if (NUMBERP (content))
+ if (INTEGERP (content))
{
- point = XUINT (content);
- point = op - point + 1;
- if (!((point >= 1) && (point < size))) continue;
- content = AREF (map, point);
+ point = XINT (content);
+ if (!(point <= op && op - point + 1 < size)) continue;
+ content = AREF (map, op - point + 1);
}
else if (EQ (content, Qt))
{
if (size != 4) continue;
- if ((op >= XUINT (AREF (map, 2)))
- && (op < XUINT (AREF (map, 3))))
+ if (INTEGERP (AREF (map, 2))
+ && XINT (AREF (map, 2)) <= op
+ && INTEGERP (AREF (map, 3))
+ && op < XINT (AREF (map, 3)))
content = AREF (map, 1);
else
continue;
@@ -1379,7 +1411,7 @@
if (NILP (content))
continue;
- else if (NUMBERP (content))
+ else if (INTEGERP (content) && IN_INT_RANGE (XINT
(content)))
{
reg[RRR] = i;
reg[rrr] = XINT(content);
@@ -1394,10 +1426,11 @@
{
attrib = XCAR (content);
value = XCDR (content);
- if (!NUMBERP (attrib) || !NUMBERP (value))
+ if (! (INTEGERP (attrib) && INTEGERP (value)
+ && IN_INT_RANGE (XINT (value))))
continue;
reg[RRR] = i;
- reg[rrr] = XUINT (value);
+ reg[rrr] = XINT (value);
break;
}
else if (SYMBOLP (content))
@@ -1432,8 +1465,9 @@
mapping_stack_pointer = mapping_stack;
stack_idx_of_map_multiple = 0;
- map_set_rest_length =
- XINT (ccl_prog[ic++]); /* number of maps and separators. */
+ /* Get number of maps and separators. */
+ GET_CCL_INT (map_set_rest_length, ccl_prog, ic++);
+
fin_ic = ic + map_set_rest_length;
op = reg[rrr];
@@ -1501,7 +1535,7 @@
do {
for (;map_set_rest_length > 0;i++, ic++,
map_set_rest_length--)
{
- point = XINT(ccl_prog[ic]);
+ GET_CCL_INT (point, ccl_prog, ic);
if (point < 0)
{
/* +1 is for including separator. */
@@ -1531,18 +1565,19 @@
/* check map type,
[STARTPOINT VAL1 VAL2 ...] or
[t ELEMENT STARTPOINT ENDPOINT] */
- if (NUMBERP (content))
+ if (INTEGERP (content))
{
- point = XUINT (content);
- point = op - point + 1;
- if (!((point >= 1) && (point < size))) continue;
- content = AREF (map, point);
+ point = XINT (content);
+ if (!(point <= op && op - point + 1 < size)) continue;
+ content = AREF (map, op - point + 1);
}
else if (EQ (content, Qt))
{
if (size != 4) continue;
- if ((op >= XUINT (AREF (map, 2))) &&
- (op < XUINT (AREF (map, 3))))
+ if (INTEGERP (AREF (map, 2))
+ && XINT (AREF (map, 2)) <= op
+ && INTEGERP (AREF (map, 3))
+ && op < XINT (AREF (map, 3)))
content = AREF (map, 1);
else
continue;
@@ -1554,7 +1589,7 @@
continue;
reg[RRR] = i;
- if (NUMBERP (content))
+ if (INTEGERP (content) && IN_INT_RANGE (XINT (content)))
{
op = XINT (content);
i += map_set_rest_length - 1;
@@ -1566,9 +1601,10 @@
{
attrib = XCAR (content);
value = XCDR (content);
- if (!NUMBERP (attrib) || !NUMBERP (value))
+ if (! (INTEGERP (attrib) && INTEGERP (value)
+ && IN_INT_RANGE (XINT (value))))
continue;
- op = XUINT (value);
+ op = XINT (value);
i += map_set_rest_length - 1;
ic += map_set_rest_length - 1;
POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
@@ -1613,7 +1649,7 @@
case CCL_MapSingle:
{
Lisp_Object map, attrib, value, content;
- int size, point;
+ int point;
j = XINT (ccl_prog[ic++]); /* map_id */
op = reg[rrr];
if (j >= ASIZE (Vcode_conversion_map_vector))
@@ -1628,41 +1664,36 @@
break;
}
map = XCDR (map);
- if (!VECTORP (map))
+ if (! (VECTORP (map)
+ && INTEGERP (AREF (map, 0))
+ && XINT (AREF (map, 0)) <= op
+ && op - XINT (AREF (map, 0)) + 1 < ASIZE (map)))
{
reg[RRR] = -1;
break;
}
- size = ASIZE (map);
- point = XUINT (AREF (map, 0));
+ point = XINT (AREF (map, 0));
point = op - point + 1;
reg[RRR] = 0;
- if ((size <= 1) ||
- (!((point >= 1) && (point < size))))
+ content = AREF (map, point);
+ if (NILP (content))
reg[RRR] = -1;
- else
+ else if (INTEGERP (content))
+ reg[rrr] = XINT (content);
+ else if (EQ (content, Qt));
+ else if (CONSP (content))
{
- reg[RRR] = 0;
- content = AREF (map, point);
- if (NILP (content))
- reg[RRR] = -1;
- else if (NUMBERP (content))
- reg[rrr] = XINT (content);
- else if (EQ (content, Qt));
- else if (CONSP (content))
- {
- attrib = XCAR (content);
- value = XCDR (content);
- if (!NUMBERP (attrib) || !NUMBERP (value))
- continue;
- reg[rrr] = XUINT(value);
- break;
- }
- else if (SYMBOLP (content))
- CCL_CALL_FOR_MAP_INSTRUCTION (content, ic);
- else
- reg[RRR] = -1;
+ attrib = XCAR (content);
+ value = XCDR (content);
+ if (!INTEGERP (attrib) || !INTEGERP (value))
+ continue;
+ reg[rrr] = XINT(value);
+ break;
}
+ else if (SYMBOLP (content))
+ CCL_CALL_FOR_MAP_INSTRUCTION (content, ic);
+ else
+ reg[RRR] = -1;
}
break;
=== modified file 'src/character.c'
--- a/src/character.c 2011-05-16 05:18:38 +0000
+++ b/src/character.c 2011-05-21 04:33:23 +0000
@@ -672,13 +672,18 @@
`str_to_multibyte'. */
EMACS_INT
-parse_str_to_multibyte (const unsigned char *str, EMACS_INT len)
+count_size_as_multibyte (const unsigned char *str, EMACS_INT len)
{
const unsigned char *endp = str + len;
EMACS_INT bytes;
for (bytes = 0; str < endp; str++)
- bytes += (*str < 0x80) ? 1 : 2;
+ {
+ int n = *str < 0x80 ? 1 : 2;
+ if (INT_ADD_OVERFLOW (bytes, n))
+ string_overflow ();
+ bytes += n;
+ }
return bytes;
}
=== modified file 'src/character.h'
--- a/src/character.h 2011-05-16 05:08:59 +0000
+++ b/src/character.h 2011-05-21 04:33:23 +0000
@@ -602,7 +602,7 @@
extern int char_printable_p (int c);
extern void parse_str_as_multibyte (const unsigned char *,
EMACS_INT, EMACS_INT *, EMACS_INT *);
-extern EMACS_INT parse_str_to_multibyte (const unsigned char *, EMACS_INT);
+extern EMACS_INT count_size_as_multibyte (const unsigned char *, EMACS_INT);
extern EMACS_INT str_as_multibyte (unsigned char *, EMACS_INT, EMACS_INT,
EMACS_INT *);
extern EMACS_INT str_to_multibyte (unsigned char *, EMACS_INT, EMACS_INT);
=== modified file 'src/data.c'
--- a/src/data.c 2011-05-12 07:07:06 +0000
+++ b/src/data.c 2011-05-27 19:48:22 +0000
@@ -22,6 +22,9 @@
#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
+
+#include <intprops.h>
+
#include "lisp.h"
#include "puresize.h"
#include "character.h"
@@ -2431,6 +2434,10 @@
register EMACS_INT accum = 0;
register EMACS_INT next;
+ int overflow = 0;
+ size_t ok_args;
+ EMACS_INT ok_accum;
+
switch (SWITCH_ENUM_CAST (code))
{
case Alogior:
@@ -2451,25 +2458,48 @@
for (argnum = 0; argnum < nargs; argnum++)
{
+ if (! overflow)
+ {
+ ok_args = argnum;
+ ok_accum = accum;
+ }
+
/* Using args[argnum] as argument to CHECK_NUMBER_... */
val = args[argnum];
CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (val);
if (FLOATP (val))
- return float_arith_driver ((double) accum, argnum, code,
+ return float_arith_driver (ok_accum, ok_args, code,
nargs, args);
args[argnum] = val;
next = XINT (args[argnum]);
switch (SWITCH_ENUM_CAST (code))
{
case Aadd:
+ if (INT_ADD_OVERFLOW (accum, next))
+ {
+ overflow = 1;
+ accum &= INTMASK;
+ }
accum += next;
break;
case Asub:
+ if (INT_SUBTRACT_OVERFLOW (accum, next))
+ {
+ overflow = 1;
+ accum &= INTMASK;
+ }
accum = argnum ? accum - next : nargs == 1 ? - next : next;
break;
case Amult:
- accum *= next;
+ if (INT_MULTIPLY_OVERFLOW (accum, next))
+ {
+ EMACS_UINT a = accum, b = next, ab = a * b;
+ overflow = 1;
+ accum = ab & INTMASK;
+ }
+ else
+ accum *= next;
break;
case Adiv:
if (!argnum)
@@ -2760,11 +2790,11 @@
if (XINT (count) >= BITS_PER_EMACS_INT)
XSETINT (val, 0);
else if (XINT (count) > 0)
- XSETINT (val, (EMACS_UINT) XUINT (value) << XFASTINT (count));
+ XSETINT (val, XUINT (value) << XFASTINT (count));
else if (XINT (count) <= -BITS_PER_EMACS_INT)
XSETINT (val, 0);
else
- XSETINT (val, (EMACS_UINT) XUINT (value) >> -XINT (count));
+ XSETINT (val, XUINT (value) >> -XINT (count));
return val;
}
=== modified file 'src/dbusbind.c'
--- a/src/dbusbind.c 2011-05-06 22:12:31 +0000
+++ b/src/dbusbind.c 2011-05-24 07:41:16 +0000
@@ -242,6 +242,24 @@
#define XD_NEXT_VALUE(object) \
((XD_DBUS_TYPE_P (CAR_SAFE (object))) ? CDR_SAFE (object) : object)
+/* Check whether X is a valid dbus serial number. If valid, set
+ SERIAL to its value. Otherwise, signal an error. */
+#define CHECK_DBUS_SERIAL_GET_SERIAL(x, serial)
\
+ do \
+ { \
+ dbus_uint32_t DBUS_SERIAL_MAX = -1; \
+ if (NATNUMP (x) && XINT (x) <= DBUS_SERIAL_MAX) \
+ serial = XINT (x); \
+ else if (MOST_POSITIVE_FIXNUM < DBUS_SERIAL_MAX \
+ && FLOATP (x) \
+ && 0 <= XFLOAT_DATA (x) \
+ && XFLOAT_DATA (x) <= DBUS_SERIAL_MAX) \
+ serial = XFLOAT_DATA (x); \
+ else \
+ XD_SIGNAL2 (build_string ("Invalid dbus serial"), x); \
+ } \
+ while (0)
+
/* Compute SIGNATURE of OBJECT. It must have a form that it can be
used in dbus_message_iter_open_container. DTYPE is the DBusType
the object is related to. It is passed as argument, because it
@@ -431,9 +449,9 @@
switch (dtype)
{
case DBUS_TYPE_BYTE:
- CHECK_NUMBER (object);
+ CHECK_NATNUM (object);
{
- unsigned char val = XUINT (object) & 0xFF;
+ unsigned char val = XFASTINT (object) & 0xFF;
XD_DEBUG_MESSAGE ("%c %d", dtype, val);
if (!dbus_message_iter_append_basic (iter, dtype, &val))
XD_SIGNAL2 (build_string ("Unable to append argument"), object);
@@ -460,9 +478,9 @@
}
case DBUS_TYPE_UINT16:
- CHECK_NUMBER (object);
+ CHECK_NATNUM (object);
{
- dbus_uint16_t val = XUINT (object);
+ dbus_uint16_t val = XFASTINT (object);
XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
if (!dbus_message_iter_append_basic (iter, dtype, &val))
XD_SIGNAL2 (build_string ("Unable to append argument"), object);
@@ -483,9 +501,9 @@
#ifdef DBUS_TYPE_UNIX_FD
case DBUS_TYPE_UNIX_FD:
#endif
- CHECK_NUMBER (object);
+ CHECK_NATNUM (object);
{
- dbus_uint32_t val = XUINT (object);
+ dbus_uint32_t val = XFASTINT (object);
XD_DEBUG_MESSAGE ("%c %u", dtype, val);
if (!dbus_message_iter_append_basic (iter, dtype, &val))
XD_SIGNAL2 (build_string ("Unable to append argument"), object);
@@ -503,10 +521,10 @@
}
case DBUS_TYPE_UINT64:
- CHECK_NUMBER (object);
+ CHECK_NATNUM (object);
{
- dbus_uint64_t val = XUINT (object);
- XD_DEBUG_MESSAGE ("%c %"pI"u", dtype, XUINT (object));
+ dbus_uint64_t val = XFASTINT (object);
+ XD_DEBUG_MESSAGE ("%c %"pI"d", dtype, XFASTINT (object));
if (!dbus_message_iter_append_basic (iter, dtype, &val))
XD_SIGNAL2 (build_string ("Unable to append argument"), object);
return;
@@ -1110,7 +1128,7 @@
if ((i+2 <= nargs) && (EQ ((args[i]), QCdbus_timeout)))
{
CHECK_NATNUM (args[i+1]);
- timeout = XUINT (args[i+1]);
+ timeout = XFASTINT (args[i+1]);
i = i+2;
}
@@ -1186,7 +1204,7 @@
/* Return the result. If there is only one single Lisp object,
return it as-it-is, otherwise return the reversed list. */
- if (XUINT (Flength (result)) == 1)
+ if (XFASTINT (Flength (result)) == 1)
RETURN_UNGCPRO (CAR_SAFE (result));
else
RETURN_UNGCPRO (Fnreverse (result));
@@ -1251,6 +1269,7 @@
DBusMessage *dmessage;
DBusMessageIter iter;
unsigned int dtype;
+ dbus_uint32_t serial;
int timeout = -1;
size_t i = 6;
char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
@@ -1292,7 +1311,7 @@
if ((i+2 <= nargs) && (EQ ((args[i]), QCdbus_timeout)))
{
CHECK_NATNUM (args[i+1]);
- timeout = XUINT (args[i+1]);
+ timeout = XFASTINT (args[i+1]);
i = i+2;
}
@@ -1335,7 +1354,8 @@
XD_SIGNAL1 (build_string ("Cannot send message"));
/* The result is the key in Vdbus_registered_objects_table. */
- result = (list2 (bus, make_number (dbus_message_get_serial (dmessage))));
+ serial = dbus_message_get_serial (dmessage);
+ result = list2 (bus, make_fixnum_or_float (serial));
/* Create a hash table entry. */
Fputhash (result, handler, Vdbus_registered_objects_table);
@@ -1368,25 +1388,26 @@
usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS) */)
(size_t nargs, register Lisp_Object *args)
{
- Lisp_Object bus, serial, service;
- struct gcpro gcpro1, gcpro2, gcpro3;
+ Lisp_Object bus, service;
+ struct gcpro gcpro1, gcpro2;
DBusConnection *connection;
DBusMessage *dmessage;
DBusMessageIter iter;
- unsigned int dtype;
+ dbus_uint32_t serial;
+ unsigned int ui_serial, dtype;
size_t i;
char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
/* Check parameters. */
bus = args[0];
- serial = args[1];
service = args[2];
- CHECK_NUMBER (serial);
+ CHECK_DBUS_SERIAL_GET_SERIAL (args[1], serial);
CHECK_STRING (service);
- GCPRO3 (bus, serial, service);
+ GCPRO2 (bus, service);
- XD_DEBUG_MESSAGE ("%"pI"u %s ", XUINT (serial), SDATA (service));
+ ui_serial = serial;
+ XD_DEBUG_MESSAGE ("%u %s ", ui_serial, SSDATA (service));
/* Open a connection to the bus. */
connection = xd_initialize (bus, TRUE);
@@ -1394,7 +1415,7 @@
/* Create the message. */
dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
if ((dmessage == NULL)
- || (!dbus_message_set_reply_serial (dmessage, XUINT (serial)))
+ || (!dbus_message_set_reply_serial (dmessage, serial))
|| (!dbus_message_set_destination (dmessage, SSDATA (service))))
{
UNGCPRO;
@@ -1456,25 +1477,26 @@
usage: (dbus-method-error-internal BUS SERIAL SERVICE &rest ARGS) */)
(size_t nargs, register Lisp_Object *args)
{
- Lisp_Object bus, serial, service;
- struct gcpro gcpro1, gcpro2, gcpro3;
+ Lisp_Object bus, service;
+ struct gcpro gcpro1, gcpro2;
DBusConnection *connection;
DBusMessage *dmessage;
DBusMessageIter iter;
- unsigned int dtype;
+ dbus_uint32_t serial;
+ unsigned int ui_serial, dtype;
size_t i;
char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
/* Check parameters. */
bus = args[0];
- serial = args[1];
service = args[2];
- CHECK_NUMBER (serial);
+ CHECK_DBUS_SERIAL_GET_SERIAL (args[1], serial);
CHECK_STRING (service);
- GCPRO3 (bus, serial, service);
+ GCPRO2 (bus, service);
- XD_DEBUG_MESSAGE ("%"pI"u %s ", XUINT (serial), SDATA (service));
+ ui_serial = serial;
+ XD_DEBUG_MESSAGE ("%u %s ", ui_serial, SSDATA (service));
/* Open a connection to the bus. */
connection = xd_initialize (bus, TRUE);
@@ -1483,7 +1505,7 @@
dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
if ((dmessage == NULL)
|| (!dbus_message_set_error_name (dmessage, DBUS_ERROR_FAILED))
- || (!dbus_message_set_reply_serial (dmessage, XUINT (serial)))
+ || (!dbus_message_set_reply_serial (dmessage, serial))
|| (!dbus_message_set_destination (dmessage, SSDATA (service))))
{
UNGCPRO;
@@ -1663,7 +1685,9 @@
DBusMessage *dmessage;
DBusMessageIter iter;
unsigned int dtype;
- int mtype, serial;
+ int mtype;
+ dbus_uint32_t serial;
+ unsigned int ui_serial;
const char *uname, *path, *interface, *member;
dmessage = dbus_connection_pop_message (connection);
@@ -1692,7 +1716,7 @@
/* Read message type, message serial, unique name, object path,
interface and member from the message. */
mtype = dbus_message_get_type (dmessage);
- serial =
+ ui_serial = serial =
((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
|| (mtype == DBUS_MESSAGE_TYPE_ERROR))
? dbus_message_get_reply_serial (dmessage)
@@ -1702,7 +1726,7 @@
interface = dbus_message_get_interface (dmessage);
member = dbus_message_get_member (dmessage);
- XD_DEBUG_MESSAGE ("Event received: %s %d %s %s %s %s %s",
+ XD_DEBUG_MESSAGE ("Event received: %s %u %s %s %s %s %s",
(mtype == DBUS_MESSAGE_TYPE_INVALID)
? "DBUS_MESSAGE_TYPE_INVALID"
: (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
@@ -1712,14 +1736,14 @@
: (mtype == DBUS_MESSAGE_TYPE_ERROR)
? "DBUS_MESSAGE_TYPE_ERROR"
: "DBUS_MESSAGE_TYPE_SIGNAL",
- serial, uname, path, interface, member,
+ ui_serial, uname, path, interface, member,
SDATA (format2 ("%s", args, Qnil)));
if ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
|| (mtype == DBUS_MESSAGE_TYPE_ERROR))
{
/* Search for a registered function of the message. */
- key = list2 (bus, make_number (serial));
+ key = list2 (bus, make_fixnum_or_float (serial));
value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
/* There shall be exactly one entry. Construct an event. */
@@ -1785,7 +1809,7 @@
event.arg);
event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)),
event.arg);
- event.arg = Fcons (make_number (serial), event.arg);
+ event.arg = Fcons (make_fixnum_or_float (serial), event.arg);
event.arg = Fcons (make_number (mtype), event.arg);
/* Add the bus symbol to the event. */
=== modified file 'src/editfns.c'
--- a/src/editfns.c 2011-05-26 05:36:55 +0000
+++ b/src/editfns.c 2011-05-27 19:37:32 +0000
@@ -45,9 +45,11 @@
#endif
#include <ctype.h>
+#include <float.h>
#include <limits.h>
#include <intprops.h>
#include <strftime.h>
+#include <verify.h>
#include "intervals.h"
#include "buffer.h"
@@ -57,13 +59,6 @@
#include "window.h"
#include "blockinput.h"
-#ifdef STDC_HEADERS
-#include <float.h>
-#define MAX_10_EXP DBL_MAX_10_EXP
-#else
-#define MAX_10_EXP 310
-#endif
-
#ifndef NULL
#define NULL 0
#endif
@@ -3525,14 +3520,21 @@
RETURN_UNGCPRO (string);
}
-
-/* Number of bytes that STRING will occupy when put into the result.
- MULTIBYTE is nonzero if the result should be multibyte. */
-
-#define CONVERTED_BYTE_SIZE(MULTIBYTE, STRING) \
- (((MULTIBYTE) && ! STRING_MULTIBYTE (STRING))
\
- ? count_size_as_multibyte (SDATA (STRING), SBYTES (STRING)) \
- : SBYTES (STRING))
+/* pWIDE is a conversion for printing large decimal integers (possibly with a
+ trailing "d" that is ignored). pWIDElen is its length. signed_wide and
+ unsigned_wide are signed and unsigned types for printing them. Use widest
+ integers if available so that more floating point values can be converted.
*/
+#ifdef PRIdMAX
+# define pWIDE PRIdMAX
+enum { pWIDElen = sizeof PRIdMAX - 2 }; /* Don't count trailing "d". */
+typedef intmax_t signed_wide;
+typedef uintmax_t unsigned_wide;
+#else
+# define pWIDE pI
+enum { pWIDElen = sizeof pI - 1 };
+typedef EMACS_INT signed_wide;
+typedef EMACS_UINT unsigned_wide;
+#endif
DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
doc: /* Format a string out of a format-string and arguments.
@@ -3583,11 +3585,17 @@
usage: (format STRING &rest OBJECTS) */)
(size_t nargs, register Lisp_Object *args)
{
- register size_t n; /* The number of the next arg to substitute */
- register size_t total; /* An estimate of the final length */
- char *buf, *p;
+ EMACS_INT n; /* The number of the next arg to substitute */
+ char initial_buffer[4000];
+ char *buf = initial_buffer;
+ EMACS_INT bufsize = sizeof initial_buffer;
+ EMACS_INT max_bufsize = min (MOST_POSITIVE_FIXNUM + 1, SIZE_MAX);
+ char *p;
+ Lisp_Object buf_save_value IF_LINT (= {0});
register char *format, *end, *format_start;
- int nchars;
+ EMACS_INT formatlen, nchars;
+ /* Nonzero if the format is multibyte. */
+ int multibyte_format = 0;
/* Nonzero if the output should be a multibyte string,
which is true if any of the inputs is one. */
int multibyte = 0;
@@ -3596,14 +3604,6 @@
multibyte character of the previous string. This flag tells if we
must consider such a situation or not. */
int maybe_combine_byte;
- char *this_format;
- /* Precision for each spec, or -1, a flag value meaning no precision
- was given in that spec. Element 0, corresponding to the format
- string itself, will not be used. Element NARGS, corresponding to
- no argument, *will* be assigned to in the case that a `%' and `.'
- occur after the final format specifier. */
- int *precision = (int *) (alloca ((nargs + 1) * sizeof (int)));
- int longest_format;
Lisp_Object val;
int arg_intervals = 0;
USE_SAFE_ALLOCA;
@@ -3611,458 +3611,603 @@
/* discarded[I] is 1 if byte I of the format
string was not copied into the output.
It is 2 if byte I was not the first byte of its character. */
- char *discarded = 0;
+ char *discarded;
/* Each element records, for one argument,
the start and end bytepos in the output string,
+ whether the argument has been converted to string (e.g., due to "%S"),
and whether the argument is a string with intervals.
info[0] is unused. Unused elements have -1 for start. */
struct info
{
- int start, end, intervals;
+ EMACS_INT start, end;
+ int converted_to_string;
+ int intervals;
} *info = 0;
/* It should not be necessary to GCPRO ARGS, because
the caller in the interpreter should take care of that. */
+ CHECK_STRING (args[0]);
+ format_start = SSDATA (args[0]);
+ formatlen = SBYTES (args[0]);
+
+ /* Allocate the info and discarded tables. */
+ {
+ EMACS_INT i;
+ if ((SIZE_MAX - formatlen) / sizeof (struct info) <= nargs)
+ memory_full ();
+ SAFE_ALLOCA (info, struct info *, (nargs + 1) * sizeof *info + formatlen);
+ discarded = (char *) &info[nargs + 1];
+ for (i = 0; i < nargs + 1; i++)
+ {
+ info[i].start = -1;
+ info[i].intervals = info[i].converted_to_string = 0;
+ }
+ memset (discarded, 0, formatlen);
+ }
+
/* Try to determine whether the result should be multibyte.
This is not always right; sometimes the result needs to be multibyte
because of an object that we will pass through prin1,
and in that case, we won't know it here. */
- for (n = 0; n < nargs; n++)
- {
- if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n]))
- multibyte = 1;
- /* Piggyback on this loop to initialize precision[N]. */
- precision[n] = -1;
- }
- precision[nargs] = -1;
-
- CHECK_STRING (args[0]);
- /* We may have to change "%S" to "%s". */
- args[0] = Fcopy_sequence (args[0]);
-
- /* GC should never happen here, so abort if it does. */
- abort_on_gc++;
+ multibyte_format = STRING_MULTIBYTE (args[0]);
+ multibyte = multibyte_format;
+ for (n = 1; !multibyte && n < nargs; n++)
+ if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n]))
+ multibyte = 1;
/* If we start out planning a unibyte result,
- then discover it has to be multibyte, we jump back to retry.
- That can only happen from the first large while loop below. */
+ then discover it has to be multibyte, we jump back to retry. */
retry:
- format = SSDATA (args[0]);
- format_start = format;
- end = format + SBYTES (args[0]);
- longest_format = 0;
-
- /* Make room in result for all the non-%-codes in the control string. */
- total = 5 + CONVERTED_BYTE_SIZE (multibyte, args[0]) + 1;
-
- /* Allocate the info and discarded tables. */
- {
- size_t nbytes = (nargs+1) * sizeof *info;
- size_t i;
- if (!info)
- info = (struct info *) alloca (nbytes);
- memset (info, 0, nbytes);
- for (i = 0; i < nargs + 1; i++)
- info[i].start = -1;
- if (!discarded)
- SAFE_ALLOCA (discarded, char *, SBYTES (args[0]));
- memset (discarded, 0, SBYTES (args[0]));
- }
-
- /* Add to TOTAL enough space to hold the converted arguments. */
-
- n = 0;
- while (format != end)
- if (*format++ == '%')
- {
- EMACS_INT thissize = 0;
- EMACS_INT actual_width = 0;
- char *this_format_start = format - 1;
- int field_width = 0;
-
- /* General format specifications look like
-
- '%' [flags] [field-width] [precision] format
-
- where
-
- flags ::= [-+ #0]+
- field-width ::= [0-9]+
- precision ::= '.' [0-9]*
-
- If a field-width is specified, it specifies to which width
- the output should be padded with blanks, if the output
- string is shorter than field-width.
-
- If precision is specified, it specifies the number of
- digits to print after the '.' for floats, or the max.
- number of chars to print from a string. */
-
- while (format != end
- && (*format == '-' || *format == '0' || *format == '#'
- || * format == ' ' || *format == '+'))
- ++format;
-
- if (*format >= '0' && *format <= '9')
- {
- for (field_width = 0; *format >= '0' && *format <= '9'; ++format)
- field_width = 10 * field_width + *format - '0';
- }
-
- /* N is not incremented for another few lines below, so refer to
- element N+1 (which might be precision[NARGS]). */
- if (*format == '.')
- {
- ++format;
- for (precision[n+1] = 0; *format >= '0' && *format <= '9'; ++format)
- precision[n+1] = 10 * precision[n+1] + *format - '0';
- }
-
- /* Extra +1 for 'l' that we may need to insert into the
- format. */
- if (format - this_format_start + 2 > longest_format)
- longest_format = format - this_format_start + 2;
-
- if (format == end)
- error ("Format string ends in middle of format specifier");
- if (*format == '%')
- format++;
- else if (++n >= nargs)
- error ("Not enough arguments for format string");
- else if (*format == 'S')
- {
- /* For `S', prin1 the argument and then treat like a string. */
- register Lisp_Object tem;
- tem = Fprin1_to_string (args[n], Qnil);
- if (STRING_MULTIBYTE (tem) && ! multibyte)
- {
- multibyte = 1;
- goto retry;
- }
- args[n] = tem;
- /* If we restart the loop, we should not come here again
- because args[n] is now a string and calling
- Fprin1_to_string on it produces superflous double
- quotes. So, change "%S" to "%s" now. */
- *format = 's';
- goto string;
- }
- else if (SYMBOLP (args[n]))
- {
- args[n] = SYMBOL_NAME (args[n]);
- if (STRING_MULTIBYTE (args[n]) && ! multibyte)
- {
- multibyte = 1;
- goto retry;
- }
- goto string;
- }
- else if (STRINGP (args[n]))
- {
- string:
- if (*format != 's' && *format != 'S')
- error ("Format specifier doesn't match argument type");
- /* In the case (PRECISION[N] > 0), THISSIZE may not need
- to be as large as is calculated here. Easy check for
- the case PRECISION = 0. */
- thissize = precision[n] ? CONVERTED_BYTE_SIZE (multibyte, args[n])
: 0;
- /* The precision also constrains how much of the argument
- string will finally appear (Bug#5710). */
- actual_width = lisp_string_width (args[n], -1, NULL, NULL);
- if (precision[n] != -1)
- actual_width = min (actual_width, precision[n]);
- }
- /* Would get MPV otherwise, since Lisp_Int's `point' to low memory. */
- else if (INTEGERP (args[n]) && *format != 's')
- {
- /* The following loop assumes the Lisp type indicates
- the proper way to pass the argument.
- So make sure we have a flonum if the argument should
- be a double. */
- if (*format == 'e' || *format == 'f' || *format == 'g')
- args[n] = Ffloat (args[n]);
- else
- if (*format != 'd' && *format != 'o' && *format != 'x'
- && *format != 'i' && *format != 'X' && *format != 'c')
- error ("Invalid format operation %%%c", *format);
-
- thissize = 30 + (precision[n] > 0 ? precision[n] : 0);
- if (*format == 'c')
- {
- if (! ASCII_CHAR_P (XINT (args[n]))
- /* Note: No one can remember why we have to treat
- the character 0 as a multibyte character here.
- But, until it causes a real problem, let's
- don't change it. */
- || XINT (args[n]) == 0)
- {
- if (! multibyte)
- {
- multibyte = 1;
- goto retry;
- }
- args[n] = Fchar_to_string (args[n]);
- thissize = SBYTES (args[n]);
- }
- }
- }
- else if (FLOATP (args[n]) && *format != 's')
- {
- if (! (*format == 'e' || *format == 'f' || *format == 'g'))
- {
- if (*format != 'd' && *format != 'o' && *format != 'x'
- && *format != 'i' && *format != 'X' && *format != 'c')
- error ("Invalid format operation %%%c", *format);
- /* This fails unnecessarily if args[n] is bigger than
- most-positive-fixnum but smaller than MAXINT.
- These cases are important because we sometimes use floats
- to represent such integer values (typically such values
- come from UIDs or PIDs). */
- /* args[n] = Ftruncate (args[n], Qnil); */
- }
-
- /* Note that we're using sprintf to print floats,
- so we have to take into account what that function
- prints. */
- /* Filter out flag value of -1. */
- thissize = (MAX_10_EXP + 100
- + (precision[n] > 0 ? precision[n] : 0));
- }
- else
- {
- /* Anything but a string, convert to a string using princ. */
- register Lisp_Object tem;
- tem = Fprin1_to_string (args[n], Qt);
- if (STRING_MULTIBYTE (tem) && ! multibyte)
- {
- multibyte = 1;
- goto retry;
- }
- args[n] = tem;
- goto string;
- }
-
- thissize += max (0, field_width - actual_width);
- total += thissize + 4;
- }
-
- abort_on_gc--;
-
- /* Now we can no longer jump to retry.
- TOTAL and LONGEST_FORMAT are known for certain. */
-
- this_format = (char *) alloca (longest_format + 1);
-
- /* Allocate the space for the result.
- Note that TOTAL is an overestimate. */
- SAFE_ALLOCA (buf, char *, total);
-
p = buf;
nchars = 0;
n = 0;
/* Scan the format and store result in BUF. */
- format = SSDATA (args[0]);
- format_start = format;
- end = format + SBYTES (args[0]);
+ format = format_start;
+ end = format + formatlen;
maybe_combine_byte = 0;
+
while (format != end)
{
+ /* The values of N and FORMAT when the loop body is entered. */
+ EMACS_INT n0 = n;
+ char *format0 = format;
+
+ /* Bytes needed to represent the output of this conversion. */
+ EMACS_INT convbytes;
+
if (*format == '%')
{
- int minlen;
- int negative = 0;
- char *this_format_start = format;
-
+ /* General format specifications look like
+
+ '%' [flags] [field-width] [precision] format
+
+ where
+
+ flags ::= [-+0# ]+
+ field-width ::= [0-9]+
+ precision ::= '.' [0-9]*
+
+ If a field-width is specified, it specifies to which width
+ the output should be padded with blanks, if the output
+ string is shorter than field-width.
+
+ If precision is specified, it specifies the number of
+ digits to print after the '.' for floats, or the max.
+ number of chars to print from a string. */
+
+ int minus_flag = 0;
+ int plus_flag = 0;
+ int space_flag = 0;
+ int sharp_flag = 0;
+ int zero_flag = 0;
+ EMACS_INT field_width;
+ int precision_given;
+ uintmax_t precision = UINTMAX_MAX;
+ char *num_end;
+ char conversion;
+
+ while (1)
+ {
+ switch (*++format)
+ {
+ case '-': minus_flag = 1; continue;
+ case '+': plus_flag = 1; continue;
+ case ' ': space_flag = 1; continue;
+ case '#': sharp_flag = 1; continue;
+ case '0': zero_flag = 1; continue;
+ }
+ break;
+ }
+
+ /* Ignore flags when sprintf ignores them. */
+ space_flag &= ~ plus_flag;
+ zero_flag &= ~ minus_flag;
+
+ {
+ uintmax_t w = strtoumax (format, &num_end, 10);
+ if (max_bufsize <= w)
+ string_overflow ();
+ field_width = w;
+ }
+ precision_given = *num_end == '.';
+ if (precision_given)
+ precision = strtoumax (num_end + 1, &num_end, 10);
+ format = num_end;
+
+ if (format == end)
+ error ("Format string ends in middle of format specifier");
+
+ memset (&discarded[format0 - format_start], 1, format - format0);
+ conversion = *format;
+ if (conversion == '%')
+ goto copy_char;
discarded[format - format_start] = 1;
format++;
- while (strchr ("-+0# ", *format))
- {
- if (*format == '-')
- {
- negative = 1;
- }
- discarded[format - format_start] = 1;
- ++format;
- }
-
- minlen = atoi (format);
-
- while ((*format >= '0' && *format <= '9') || *format == '.')
- {
- discarded[format - format_start] = 1;
- format++;
- }
-
- if (*format++ == '%')
- {
- *p++ = '%';
- nchars++;
- continue;
- }
-
++n;
-
- discarded[format - format_start - 1] = 1;
- info[n].start = nchars;
-
- if (STRINGP (args[n]))
+ if (! (n < nargs))
+ error ("Not enough arguments for format string");
+
+ /* For 'S', prin1 the argument, and then treat like 's'.
+ For 's', princ any argument that is not a string or
+ symbol. But don't do this conversion twice, which might
+ happen after retrying. */
+ if ((conversion == 'S'
+ || (conversion == 's'
+ && ! STRINGP (args[n]) && ! SYMBOLP (args[n]))))
+ {
+ if (! info[n].converted_to_string)
+ {
+ Lisp_Object noescape = conversion == 'S' ? Qnil : Qt;
+ args[n] = Fprin1_to_string (args[n], noescape);
+ info[n].converted_to_string = 1;
+ if (STRING_MULTIBYTE (args[n]) && ! multibyte)
+ {
+ multibyte = 1;
+ goto retry;
+ }
+ }
+ conversion = 's';
+ }
+ else if (conversion == 'c')
+ {
+ if (FLOATP (args[n]))
+ {
+ double d = XFLOAT_DATA (args[n]);
+ args[n] = make_number (FIXNUM_OVERFLOW_P (d) ? -1 : d);
+ }
+
+ if (INTEGERP (args[n]) && ! ASCII_CHAR_P (XINT (args[n])))
+ {
+ if (!multibyte)
+ {
+ multibyte = 1;
+ goto retry;
+ }
+ args[n] = Fchar_to_string (args[n]);
+ info[n].converted_to_string = 1;
+ }
+
+ if (info[n].converted_to_string)
+ conversion = 's';
+ zero_flag = 0;
+ }
+
+ if (SYMBOLP (args[n]))
+ {
+ args[n] = SYMBOL_NAME (args[n]);
+ if (STRING_MULTIBYTE (args[n]) && ! multibyte)
+ {
+ multibyte = 1;
+ goto retry;
+ }
+ }
+
+ if (conversion == 's')
{
/* handle case (precision[n] >= 0) */
- int width, padding;
- EMACS_INT nbytes, start;
+ EMACS_INT width, padding, nbytes;
EMACS_INT nchars_string;
+ EMACS_INT prec = -1;
+ if (precision_given && precision <= TYPE_MAXIMUM (EMACS_INT))
+ prec = precision;
+
/* lisp_string_width ignores a precision of 0, but GNU
libc functions print 0 characters when the precision
is 0. Imitate libc behavior here. Changing
lisp_string_width is the right thing, and will be
done, but meanwhile we work with it. */
- if (precision[n] == 0)
+ if (prec == 0)
width = nchars_string = nbytes = 0;
- else if (precision[n] > 0)
- width = lisp_string_width (args[n], precision[n],
- &nchars_string, &nbytes);
- else
- { /* no precision spec given for this argument */
- width = lisp_string_width (args[n], -1, NULL, NULL);
- nbytes = SBYTES (args[n]);
- nchars_string = SCHARS (args[n]);
- }
-
- /* If spec requires it, pad on right with spaces. */
- padding = minlen - width;
- if (! negative)
- while (padding-- > 0)
- {
- *p++ = ' ';
- ++nchars;
- }
-
- info[n].start = start = nchars;
- nchars += nchars_string;
-
- if (p > buf
- && multibyte
- && !ASCII_BYTE_P (*((unsigned char *) p - 1))
- && STRING_MULTIBYTE (args[n])
- && !CHAR_HEAD_P (SREF (args[n], 0)))
- maybe_combine_byte = 1;
-
- p += copy_text (SDATA (args[n]), (unsigned char *) p,
- nbytes,
- STRING_MULTIBYTE (args[n]), multibyte);
-
- info[n].end = nchars;
-
- if (negative)
- while (padding-- > 0)
- {
- *p++ = ' ';
- nchars++;
- }
-
- /* If this argument has text properties, record where
- in the result string it appears. */
- if (STRING_INTERVALS (args[n]))
- info[n].intervals = arg_intervals = 1;
- }
- else if (INTEGERP (args[n]) || FLOATP (args[n]))
- {
- int this_nchars;
-
- memcpy (this_format, this_format_start,
- format - this_format_start);
- this_format[format - this_format_start] = 0;
-
- if (format[-1] == 'e' || format[-1] == 'f' || format[-1] == 'g')
- sprintf (p, this_format, XFLOAT_DATA (args[n]));
- else
- {
- if (sizeof (EMACS_INT) > sizeof (int)
- && format[-1] != 'c')
- {
- /* Insert 'l' before format spec. */
- this_format[format - this_format_start]
- = this_format[format - this_format_start - 1];
- this_format[format - this_format_start - 1] = 'l';
- this_format[format - this_format_start + 1] = 0;
- }
-
- if (INTEGERP (args[n]))
- {
- if (format[-1] == 'c')
- sprintf (p, this_format, (int) XINT (args[n]));
- else if (format[-1] == 'd')
- sprintf (p, this_format, XINT (args[n]));
- /* Don't sign-extend for octal or hex printing. */
- else
- sprintf (p, this_format, XUINT (args[n]));
- }
- else if (format[-1] == 'c')
- sprintf (p, this_format, (int) XFLOAT_DATA (args[n]));
- else if (format[-1] == 'd')
- /* Maybe we should use "%1.0f" instead so it also works
- for values larger than MAXINT. */
- sprintf (p, this_format, (EMACS_INT) XFLOAT_DATA (args[n]));
- else
- /* Don't sign-extend for octal or hex printing. */
- sprintf (p, this_format, (EMACS_UINT) XFLOAT_DATA
(args[n]));
- }
-
- if (p > buf
- && multibyte
- && !ASCII_BYTE_P (*((unsigned char *) p - 1))
- && !CHAR_HEAD_P (*((unsigned char *) p)))
- maybe_combine_byte = 1;
- this_nchars = strlen (p);
- if (multibyte)
- p += str_to_multibyte ((unsigned char *) p,
- buf + total - 1 - p, this_nchars);
- else
- p += this_nchars;
- nchars += this_nchars;
- info[n].end = nchars;
- }
-
- }
- else if (STRING_MULTIBYTE (args[0]))
- {
- /* Copy a whole multibyte character. */
- if (p > buf
- && multibyte
- && !ASCII_BYTE_P (*((unsigned char *) p - 1))
- && !CHAR_HEAD_P (*format))
- maybe_combine_byte = 1;
- *p++ = *format++;
- while (! CHAR_HEAD_P (*format))
- {
- discarded[format - format_start] = 2;
- *p++ = *format++;
- }
- nchars++;
- }
- else if (multibyte)
- {
- /* Convert a single-byte character to multibyte. */
- int len = copy_text ((unsigned char *) format, (unsigned char *) p,
- 1, 0, 1);
-
- p += len;
- format++;
- nchars++;
+ else
+ {
+ EMACS_INT nch, nby;
+ width = lisp_string_width (args[n], prec, &nch, &nby);
+ if (prec < 0)
+ {
+ nchars_string = SCHARS (args[n]);
+ nbytes = SBYTES (args[n]);
+ }
+ else
+ {
+ nchars_string = nch;
+ nbytes = nby;
+ }
+ }
+
+ convbytes = nbytes;
+ if (convbytes && multibyte && ! STRING_MULTIBYTE (args[n]))
+ convbytes = count_size_as_multibyte (SDATA (args[n]), nbytes);
+
+ padding = width < field_width ? field_width - width : 0;
+
+ if (max_bufsize - padding <= convbytes)
+ string_overflow ();
+ convbytes += padding;
+ if (convbytes <= buf + bufsize - p)
+ {
+ if (! minus_flag)
+ {
+ memset (p, ' ', padding);
+ p += padding;
+ nchars += padding;
+ }
+
+ if (p > buf
+ && multibyte
+ && !ASCII_BYTE_P (*((unsigned char *) p - 1))
+ && STRING_MULTIBYTE (args[n])
+ && !CHAR_HEAD_P (SREF (args[n], 0)))
+ maybe_combine_byte = 1;
+
+ p += copy_text (SDATA (args[n]), (unsigned char *) p,
+ nbytes,
+ STRING_MULTIBYTE (args[n]), multibyte);
+
+ info[n].start = nchars;
+ nchars += nchars_string;
+ info[n].end = nchars;
+
+ if (minus_flag)
+ {
+ memset (p, ' ', padding);
+ p += padding;
+ nchars += padding;
+ }
+
+ /* If this argument has text properties, record where
+ in the result string it appears. */
+ if (STRING_INTERVALS (args[n]))
+ info[n].intervals = arg_intervals = 1;
+
+ continue;
+ }
+ }
+ else if (! (conversion == 'c' || conversion == 'd'
+ || conversion == 'e' || conversion == 'f'
+ || conversion == 'g' || conversion == 'i'
+ || conversion == 'o' || conversion == 'x'
+ || conversion == 'X'))
+ error ("Invalid format operation %%%c",
+ STRING_CHAR ((unsigned char *) format - 1));
+ else if (! (INTEGERP (args[n]) || FLOATP (args[n])))
+ error ("Format specifier doesn't match argument type");
+ else
+ {
+ enum
+ {
+ /* Maximum precision for a %f conversion such that the
+ trailing output digit might be nonzero. Any precisions
+ larger than this will not yield useful information. */
+ USEFUL_PRECISION_MAX =
+ ((1 - DBL_MIN_EXP)
+ * (FLT_RADIX == 2 || FLT_RADIX == 10 ? 1
+ : FLT_RADIX == 16 ? 4
+ : -1)),
+
+ /* Maximum number of bytes generated by any format, if
+ precision is no more than DBL_USEFUL_PRECISION_MAX.
+ On all practical hosts, %f is the worst case. */
+ SPRINTF_BUFSIZE =
+ sizeof "-." + (DBL_MAX_10_EXP + 1) + USEFUL_PRECISION_MAX
+ };
+ verify (0 < USEFUL_PRECISION_MAX);
+
+ int prec;
+ EMACS_INT padding, sprintf_bytes;
+ uintmax_t excess_precision, numwidth;
+ uintmax_t leading_zeros = 0, trailing_zeros = 0;
+
+ char sprintf_buf[SPRINTF_BUFSIZE];
+
+ /* Copy of conversion specification, modified somewhat.
+ At most three flags F can be specified at once. */
+ char convspec[sizeof "%FFF.*d" + pWIDElen];
+
+ /* Avoid undefined behavior in underlying sprintf. */
+ if (conversion == 'd' || conversion == 'i')
+ sharp_flag = 0;
+
+ /* Create the copy of the conversion specification, with
+ any width and precision removed, with ".*" inserted,
+ and with pWIDE inserted for integer formats. */
+ {
+ char *f = convspec;
+ *f++ = '%';
+ *f = '-'; f += minus_flag;
+ *f = '+'; f += plus_flag;
+ *f = ' '; f += space_flag;
+ *f = '#'; f += sharp_flag;
+ *f = '0'; f += zero_flag;
+ *f++ = '.';
+ *f++ = '*';
+ if (conversion == 'd' || conversion == 'i'
+ || conversion == 'o' || conversion == 'x'
+ || conversion == 'X')
+ {
+ memcpy (f, pWIDE, pWIDElen);
+ f += pWIDElen;
+ zero_flag &= ~ precision_given;
+ }
+ *f++ = conversion;
+ *f = '\0';
+ }
+
+ prec = -1;
+ if (precision_given)
+ prec = min (precision, USEFUL_PRECISION_MAX);
+
+ /* Use sprintf to format this number into sprintf_buf. Omit
+ padding and excess precision, though, because sprintf limits
+ output length to INT_MAX.
+
+ There are four types of conversion: double, unsigned
+ char (passed as int), wide signed int, and wide
+ unsigned int. Treat them separately because the
+ sprintf ABI is sensitive to which type is passed. Be
+ careful about integer overflow, NaNs, infinities, and
+ conversions; for example, the min and max macros are
+ not suitable here. */
+ if (conversion == 'e' || conversion == 'f' || conversion == 'g')
+ {
+ double x = (INTEGERP (args[n])
+ ? XINT (args[n])
+ : XFLOAT_DATA (args[n]));
+ sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
+ }
+ else if (conversion == 'c')
+ {
+ /* Don't use sprintf here, as it might mishandle prec. */
+ sprintf_buf[0] = XINT (args[n]);
+ sprintf_bytes = prec != 0;
+ }
+ else if (conversion == 'd')
+ {
+ /* For float, maybe we should use "%1.0f"
+ instead so it also works for values outside
+ the integer range. */
+ signed_wide x;
+ if (INTEGERP (args[n]))
+ x = XINT (args[n]);
+ else
+ {
+ double d = XFLOAT_DATA (args[n]);
+ if (d < 0)
+ {
+ x = TYPE_MINIMUM (signed_wide);
+ if (x < d)
+ x = d;
+ }
+ else
+ {
+ x = TYPE_MAXIMUM (signed_wide);
+ if (d < x)
+ x = d;
+ }
+ }
+ sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
+ }
+ else
+ {
+ /* Don't sign-extend for octal or hex printing. */
+ unsigned_wide x;
+ if (INTEGERP (args[n]))
+ x = XUINT (args[n]);
+ else
+ {
+ double d = XFLOAT_DATA (args[n]);
+ if (d < 0)
+ x = 0;
+ else
+ {
+ x = TYPE_MAXIMUM (unsigned_wide);
+ if (d < x)
+ x = d;
+ }
+ }
+ sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
+ }
+
+ /* Now the length of the formatted item is known, except it omits
+ padding and excess precision. Deal with excess precision
+ first. This happens only when the format specifies
+ ridiculously large precision. */
+ excess_precision = precision - prec;
+ if (excess_precision)
+ {
+ if (conversion == 'e' || conversion == 'f'
+ || conversion == 'g')
+ {
+ if ((conversion == 'g' && ! sharp_flag)
+ || ! ('0' <= sprintf_buf[sprintf_bytes - 1]
+ && sprintf_buf[sprintf_bytes - 1] <= '9'))
+ excess_precision = 0;
+ else
+ {
+ if (conversion == 'g')
+ {
+ char *dot = strchr (sprintf_buf, '.');
+ if (!dot)
+ excess_precision = 0;
+ }
+ }
+ trailing_zeros = excess_precision;
+ }
+ else
+ leading_zeros = excess_precision;
+ }
+
+ /* Compute the total bytes needed for this item, including
+ excess precision and padding. */
+ numwidth = sprintf_bytes + excess_precision;
+ padding = numwidth < field_width ? field_width - numwidth : 0;
+ if (max_bufsize - sprintf_bytes <= excess_precision
+ || max_bufsize - padding <= numwidth)
+ string_overflow ();
+ convbytes = numwidth + padding;
+
+ if (convbytes <= buf + bufsize - p)
+ {
+ /* Copy the formatted item from sprintf_buf into buf,
+ inserting padding and excess-precision zeros. */
+
+ char *src = sprintf_buf;
+ char src0 = src[0];
+ int exponent_bytes = 0;
+ int signedp = src0 == '-' || src0 == '+' || src0 == ' ';
+ int significand_bytes;
+ if (zero_flag && '0' <= src[signedp] && src[signedp] <= '9')
+ {
+ leading_zeros += padding;
+ padding = 0;
+ }
+
+ if (excess_precision
+ && (conversion == 'e' || conversion == 'g'))
+ {
+ char *e = strchr (src, 'e');
+ if (e)
+ exponent_bytes = src + sprintf_bytes - e;
+ }
+
+ if (! minus_flag)
+ {
+ memset (p, ' ', padding);
+ p += padding;
+ nchars += padding;
+ }
+
+ *p = src0;
+ src += signedp;
+ p += signedp;
+ memset (p, '0', leading_zeros);
+ p += leading_zeros;
+ significand_bytes = sprintf_bytes - signedp - exponent_bytes;
+ memcpy (p, src, significand_bytes);
+ p += significand_bytes;
+ src += significand_bytes;
+ memset (p, '0', trailing_zeros);
+ p += trailing_zeros;
+ memcpy (p, src, exponent_bytes);
+ p += exponent_bytes;
+
+ info[n].start = nchars;
+ nchars += leading_zeros + sprintf_bytes + trailing_zeros;
+ info[n].end = nchars;
+
+ if (minus_flag)
+ {
+ memset (p, ' ', padding);
+ p += padding;
+ nchars += padding;
+ }
+
+ continue;
+ }
+ }
}
else
- *p++ = *format++, nchars++;
+ copy_char:
+ {
+ /* Copy a single character from format to buf. */
+
+ char *src = format;
+ unsigned char str[MAX_MULTIBYTE_LENGTH];
+
+ if (multibyte_format)
+ {
+ /* Copy a whole multibyte character. */
+ if (p > buf
+ && !ASCII_BYTE_P (*((unsigned char *) p - 1))
+ && !CHAR_HEAD_P (*format))
+ maybe_combine_byte = 1;
+
+ do
+ format++;
+ while (! CHAR_HEAD_P (*format));
+
+ convbytes = format - format0;
+ memset (&discarded[format0 + 1 - format_start], 2, convbytes - 1);
+ }
+ else
+ {
+ unsigned char uc = *format++;
+ if (! multibyte || ASCII_BYTE_P (uc))
+ convbytes = 1;
+ else
+ {
+ int c = BYTE8_TO_CHAR (uc);
+ convbytes = CHAR_STRING (c, str);
+ src = (char *) str;
+ }
+ }
+
+ if (convbytes <= buf + bufsize - p)
+ {
+ memcpy (p, src, convbytes);
+ p += convbytes;
+ nchars++;
+ continue;
+ }
+ }
+
+ /* There wasn't enough room to store this conversion or single
+ character. CONVBYTES says how much room is needed. Allocate
+ enough room (and then some) and do it again. */
+ {
+ EMACS_INT used = p - buf;
+
+ if (max_bufsize - used < convbytes)
+ string_overflow ();
+ bufsize = used + convbytes;
+ bufsize = bufsize < max_bufsize / 2 ? bufsize * 2 : max_bufsize;
+
+ if (buf == initial_buffer)
+ {
+ buf = xmalloc (bufsize);
+ sa_must_free = 1;
+ buf_save_value = make_save_value (buf, 0);
+ record_unwind_protect (safe_alloca_unwind, buf_save_value);
+ memcpy (buf, initial_buffer, used);
+ }
+ else
+ XSAVE_VALUE (buf_save_value)->pointer = buf = xrealloc (buf, bufsize);
+
+ p = buf + used;
+ }
+
+ format = format0;
+ n = n0;
}
- if (p > buf + total)
+ if (bufsize < p - buf)
abort ();
if (maybe_combine_byte)
@@ -4089,7 +4234,7 @@
if (CONSP (props))
{
EMACS_INT bytepos = 0, position = 0, translated = 0;
- int argn = 1;
+ EMACS_INT argn = 1;
Lisp_Object list;
/* Adjust the bounds of each text property
=== modified file 'src/fns.c'
--- a/src/fns.c 2011-05-27 19:30:12 +0000
+++ b/src/fns.c 2011-05-27 19:37:32 +0000
@@ -898,7 +898,7 @@
if (STRING_MULTIBYTE (string))
return string;
- nbytes = parse_str_to_multibyte (SDATA (string), SBYTES (string));
+ nbytes = count_size_as_multibyte (SDATA (string), SBYTES (string));
/* If all the chars are ASCII, they won't need any more bytes once
converted. */
if (nbytes == SBYTES (string))
=== modified file 'src/insdel.c'
--- a/src/insdel.c 2011-05-16 05:15:51 +0000
+++ b/src/insdel.c 2011-05-21 04:33:23 +0000
@@ -570,37 +570,6 @@
return to_addr - initial_to_addr;
}
}
-
-/* Return the number of bytes it would take
- to convert some single-byte text to multibyte.
- The single-byte text consists of NBYTES bytes at PTR. */
-
-EMACS_INT
-count_size_as_multibyte (const unsigned char *ptr, EMACS_INT nbytes)
-{
- EMACS_INT i;
- EMACS_INT outgoing_nbytes = 0;
-
- for (i = 0; i < nbytes; i++)
- {
- unsigned int c = *ptr++;
- int n;
-
- if (ASCII_CHAR_P (c))
- n = 1;
- else
- {
- c = BYTE8_TO_CHAR (c);
- n = CHAR_BYTES (c);
- }
-
- if (INT_ADD_OVERFLOW (outgoing_nbytes, n))
- string_overflow ();
- outgoing_nbytes += n;
- }
-
- return outgoing_nbytes;
-}
/* Insert a string of specified length before point.
This function judges multibyteness based on
=== modified file 'src/lisp.h'
--- a/src/lisp.h 2011-05-16 01:11:54 +0000
+++ b/src/lisp.h 2011-05-22 07:12:24 +0000
@@ -544,11 +544,10 @@
/* Value is non-zero if I doesn't fit into a Lisp fixnum. It is
written this way so that it also works if I is of unsigned
- type. */
+ type or if I is a NaN. */
#define FIXNUM_OVERFLOW_P(i) \
- ((i) > MOST_POSITIVE_FIXNUM \
- || ((i) < 0 && (i) < MOST_NEGATIVE_FIXNUM))
+ (! ((0 <= (i) || MOST_NEGATIVE_FIXNUM <= (i)) && (i) <=
MOST_POSITIVE_FIXNUM))
/* Extract a value or address from a Lisp_Object. */
@@ -2574,7 +2573,6 @@
extern void make_gap (EMACS_INT);
extern EMACS_INT copy_text (const unsigned char *, unsigned char *,
EMACS_INT, int, int);
-extern EMACS_INT count_size_as_multibyte (const unsigned char *, EMACS_INT);
extern int count_combining_before (const unsigned char *,
EMACS_INT, EMACS_INT, EMACS_INT);
extern int count_combining_after (const unsigned char *,
=== modified file 'src/mem-limits.h'
--- a/src/mem-limits.h 2011-01-25 04:08:28 +0000
+++ b/src/mem-limits.h 2011-05-23 00:22:43 +0000
@@ -40,8 +40,7 @@
#define EXCEEDS_LISP_PTR(ptr) 0
#elif defined DATA_SEG_BITS
#define EXCEEDS_LISP_PTR(ptr) \
- (((EMACS_UINT) (ptr) & ~DATA_SEG_BITS) >> VALBITS)
+ (((uintptr_t) (ptr) & ~DATA_SEG_BITS) >> VALBITS)
#else
-#define EXCEEDS_LISP_PTR(ptr) ((EMACS_UINT) (ptr) >> VALBITS)
+#define EXCEEDS_LISP_PTR(ptr) ((uintptr_t) (ptr) >> VALBITS)
#endif
-
=== modified file 'src/print.c'
--- a/src/print.c 2011-05-12 07:07:06 +0000
+++ b/src/print.c 2011-05-21 04:33:23 +0000
@@ -381,7 +381,7 @@
EMACS_INT bytes;
chars = SBYTES (string);
- bytes = parse_str_to_multibyte (SDATA (string), chars);
+ bytes = count_size_as_multibyte (SDATA (string), chars);
if (chars < bytes)
{
newstr = make_uninit_multibyte_string (chars, bytes);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] /srv/bzr/emacs/trunk r104390: Merge: Integer overflow fixes.,
Paul Eggert <=