diff options
| author | Paul Eggert | 2011-05-15 22:08:59 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-05-15 22:08:59 -0700 |
| commit | 2b4560a850d2ea0767d0a3c4db19e4468f61b4eb (patch) | |
| tree | ca99d199897a9289dfff5a1f492341402d79ae69 /src | |
| parent | cb93f9bef01e95b17b3d7b8786c103505355d98c (diff) | |
| download | emacs-2b4560a850d2ea0767d0a3c4db19e4468f61b4eb.tar.gz emacs-2b4560a850d2ea0767d0a3c4db19e4468f61b4eb.zip | |
* character.c (lisp_string_width): Check for string overflow.
Use EMACS_INT, not int, for string indexes and lengths; in
particular, 2nd arg is now EMACS_INT, not int. Do not crash if
the resulting string length overflows an EMACS_INT; instead,
report a string overflow if no precision given. When checking for
precision exhaustion, use a check that cannot possibly have
integer overflow. (Bug#8675)
* character.h (lisp_string_width): Adjust to new signature.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 9 | ||||
| -rw-r--r-- | src/character.c | 21 | ||||
| -rw-r--r-- | src/character.h | 2 |
3 files changed, 26 insertions, 6 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 178ebf78932..944a5dfbecb 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,14 @@ | |||
| 1 | 2011-05-16 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2011-05-16 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | * character.c (lisp_string_width): Check for string overflow. | ||
| 4 | Use EMACS_INT, not int, for string indexes and lengths; in | ||
| 5 | particular, 2nd arg is now EMACS_INT, not int. Do not crash if | ||
| 6 | the resulting string length overflows an EMACS_INT; instead, | ||
| 7 | report a string overflow if no precision given. When checking for | ||
| 8 | precision exhaustion, use a check that cannot possibly have | ||
| 9 | integer overflow. (Bug#8675) | ||
| 10 | * character.h (lisp_string_width): Adjust to new signature. | ||
| 11 | |||
| 3 | * alloc.c (string_overflow): New function. | 12 | * alloc.c (string_overflow): New function. |
| 4 | (Fmake_string): Use it. This doesn't change behavior, but saves | 13 | (Fmake_string): Use it. This doesn't change behavior, but saves |
| 5 | a few bytes and will simplify future changes. | 14 | a few bytes and will simplify future changes. |
diff --git a/src/character.c b/src/character.c index 6a8b86d5d87..a03c081a716 100644 --- a/src/character.c +++ b/src/character.c | |||
| @@ -35,6 +35,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 35 | 35 | ||
| 36 | #include <sys/types.h> | 36 | #include <sys/types.h> |
| 37 | #include <setjmp.h> | 37 | #include <setjmp.h> |
| 38 | #include <intprops.h> | ||
| 38 | #include "lisp.h" | 39 | #include "lisp.h" |
| 39 | #include "character.h" | 40 | #include "character.h" |
| 40 | #include "buffer.h" | 41 | #include "buffer.h" |
| @@ -404,7 +405,7 @@ strwidth (const char *str, EMACS_INT len) | |||
| 404 | in *NCHARS and *NBYTES respectively. */ | 405 | in *NCHARS and *NBYTES respectively. */ |
| 405 | 406 | ||
| 406 | EMACS_INT | 407 | EMACS_INT |
| 407 | lisp_string_width (Lisp_Object string, int precision, | 408 | lisp_string_width (Lisp_Object string, EMACS_INT precision, |
| 408 | EMACS_INT *nchars, EMACS_INT *nbytes) | 409 | EMACS_INT *nchars, EMACS_INT *nbytes) |
| 409 | { | 410 | { |
| 410 | EMACS_INT len = SCHARS (string); | 411 | EMACS_INT len = SCHARS (string); |
| @@ -419,7 +420,7 @@ lisp_string_width (Lisp_Object string, int precision, | |||
| 419 | 420 | ||
| 420 | while (i < len) | 421 | while (i < len) |
| 421 | { | 422 | { |
| 422 | int chars, bytes, thiswidth; | 423 | EMACS_INT chars, bytes, thiswidth; |
| 423 | Lisp_Object val; | 424 | Lisp_Object val; |
| 424 | int cmp_id; | 425 | int cmp_id; |
| 425 | EMACS_INT ignore, end; | 426 | EMACS_INT ignore, end; |
| @@ -437,7 +438,11 @@ lisp_string_width (Lisp_Object string, int precision, | |||
| 437 | int c; | 438 | int c; |
| 438 | 439 | ||
| 439 | if (multibyte) | 440 | if (multibyte) |
| 440 | c = STRING_CHAR_AND_LENGTH (str + i_byte, bytes); | 441 | { |
| 442 | int cbytes; | ||
| 443 | c = STRING_CHAR_AND_LENGTH (str + i_byte, cbytes); | ||
| 444 | bytes = cbytes; | ||
| 445 | } | ||
| 441 | else | 446 | else |
| 442 | c = str[i_byte], bytes = 1; | 447 | c = str[i_byte], bytes = 1; |
| 443 | chars = 1; | 448 | chars = 1; |
| @@ -455,8 +460,14 @@ lisp_string_width (Lisp_Object string, int precision, | |||
| 455 | } | 460 | } |
| 456 | } | 461 | } |
| 457 | 462 | ||
| 458 | if (precision > 0 | 463 | if (precision <= 0) |
| 459 | && (width + thiswidth > precision)) | 464 | { |
| 465 | #ifdef emacs | ||
| 466 | if (INT_ADD_OVERFLOW (width, thiswidth)) | ||
| 467 | string_overflow (); | ||
| 468 | #endif | ||
| 469 | } | ||
| 470 | else if (precision - width < thiswidth) | ||
| 460 | { | 471 | { |
| 461 | *nchars = i; | 472 | *nchars = i; |
| 462 | *nbytes = i_byte; | 473 | *nbytes = i_byte; |
diff --git a/src/character.h b/src/character.h index 864882db7f6..5877d145d9e 100644 --- a/src/character.h +++ b/src/character.h | |||
| @@ -612,7 +612,7 @@ extern EMACS_INT str_to_unibyte (const unsigned char *, unsigned char *, | |||
| 612 | extern EMACS_INT strwidth (const char *, EMACS_INT); | 612 | extern EMACS_INT strwidth (const char *, EMACS_INT); |
| 613 | extern EMACS_INT c_string_width (const unsigned char *, EMACS_INT, int, | 613 | extern EMACS_INT c_string_width (const unsigned char *, EMACS_INT, int, |
| 614 | EMACS_INT *, EMACS_INT *); | 614 | EMACS_INT *, EMACS_INT *); |
| 615 | extern EMACS_INT lisp_string_width (Lisp_Object, int, | 615 | extern EMACS_INT lisp_string_width (Lisp_Object, EMACS_INT, |
| 616 | EMACS_INT *, EMACS_INT *); | 616 | EMACS_INT *, EMACS_INT *); |
| 617 | 617 | ||
| 618 | extern Lisp_Object Qcharacterp; | 618 | extern Lisp_Object Qcharacterp; |