diff options
| author | Paul Eggert | 2020-05-18 17:17:46 -0700 |
|---|---|---|
| committer | Paul Eggert | 2020-05-18 17:24:35 -0700 |
| commit | c5eafccc9d2a32ef422060e50533b36292bdcc01 (patch) | |
| tree | 895fdec0566fea0f1b94ac54dc2051f65eae925c | |
| parent | 06fe322c8d7123edea0759a7aa12051f4e676376 (diff) | |
| download | emacs-c5eafccc9d2a32ef422060e50533b36292bdcc01.tar.gz emacs-c5eafccc9d2a32ef422060e50533b36292bdcc01.zip | |
Reject attempts to clear pure strings
* src/fns.c (Ffillarray, Fclear_string):
Add CHECK_IMPURE here, to be consistent with Faset etc.
(Ffillarray): Prefer memset when the fill is a single byte.
| -rw-r--r-- | src/fns.c | 51 |
1 files changed, 32 insertions, 19 deletions
| @@ -2508,26 +2508,36 @@ ARRAY is a vector, string, char-table, or bool-vector. */) | |||
| 2508 | } | 2508 | } |
| 2509 | else if (STRINGP (array)) | 2509 | else if (STRINGP (array)) |
| 2510 | { | 2510 | { |
| 2511 | register unsigned char *p = SDATA (array); | 2511 | unsigned char *p = SDATA (array); |
| 2512 | int charval; | ||
| 2513 | CHECK_CHARACTER (item); | 2512 | CHECK_CHARACTER (item); |
| 2514 | charval = XFIXNAT (item); | 2513 | int charval = XFIXNAT (item); |
| 2515 | size = SCHARS (array); | 2514 | size = SCHARS (array); |
| 2516 | if (STRING_MULTIBYTE (array)) | 2515 | if (size != 0) |
| 2517 | { | 2516 | { |
| 2517 | CHECK_IMPURE (array, XSTRING (array)); | ||
| 2518 | unsigned char str[MAX_MULTIBYTE_LENGTH]; | 2518 | unsigned char str[MAX_MULTIBYTE_LENGTH]; |
| 2519 | int len = CHAR_STRING (charval, str); | 2519 | int len; |
| 2520 | ptrdiff_t size_byte = SBYTES (array); | 2520 | if (STRING_MULTIBYTE (array)) |
| 2521 | ptrdiff_t product; | 2521 | len = CHAR_STRING (charval, str); |
| 2522 | else | ||
| 2523 | { | ||
| 2524 | str[0] = charval; | ||
| 2525 | len = 1; | ||
| 2526 | } | ||
| 2522 | 2527 | ||
| 2523 | if (INT_MULTIPLY_WRAPV (size, len, &product) || product != size_byte) | 2528 | ptrdiff_t size_byte = SBYTES (array); |
| 2524 | error ("Attempt to change byte length of a string"); | 2529 | if (len == 1 && size == size_byte) |
| 2525 | for (idx = 0; idx < size_byte; idx++) | 2530 | memset (p, str[0], size); |
| 2526 | *p++ = str[idx % len]; | 2531 | else |
| 2532 | { | ||
| 2533 | ptrdiff_t product; | ||
| 2534 | if (INT_MULTIPLY_WRAPV (size, len, &product) | ||
| 2535 | || product != size_byte) | ||
| 2536 | error ("Attempt to change byte length of a string"); | ||
| 2537 | for (idx = 0; idx < size_byte; idx++) | ||
| 2538 | *p++ = str[idx % len]; | ||
| 2539 | } | ||
| 2527 | } | 2540 | } |
| 2528 | else | ||
| 2529 | for (idx = 0; idx < size; idx++) | ||
| 2530 | p[idx] = charval; | ||
| 2531 | } | 2541 | } |
| 2532 | else if (BOOL_VECTOR_P (array)) | 2542 | else if (BOOL_VECTOR_P (array)) |
| 2533 | return bool_vector_fill (array, item); | 2543 | return bool_vector_fill (array, item); |
| @@ -2542,12 +2552,15 @@ DEFUN ("clear-string", Fclear_string, Sclear_string, | |||
| 2542 | This makes STRING unibyte and may change its length. */) | 2552 | This makes STRING unibyte and may change its length. */) |
| 2543 | (Lisp_Object string) | 2553 | (Lisp_Object string) |
| 2544 | { | 2554 | { |
| 2545 | ptrdiff_t len; | ||
| 2546 | CHECK_STRING (string); | 2555 | CHECK_STRING (string); |
| 2547 | len = SBYTES (string); | 2556 | ptrdiff_t len = SBYTES (string); |
| 2548 | memset (SDATA (string), 0, len); | 2557 | if (len != 0 || STRING_MULTIBYTE (string)) |
| 2549 | STRING_SET_CHARS (string, len); | 2558 | { |
| 2550 | STRING_SET_UNIBYTE (string); | 2559 | CHECK_IMPURE (string, XSTRING (string)); |
| 2560 | memset (SDATA (string), 0, len); | ||
| 2561 | STRING_SET_CHARS (string, len); | ||
| 2562 | STRING_SET_UNIBYTE (string); | ||
| 2563 | } | ||
| 2551 | return Qnil; | 2564 | return Qnil; |
| 2552 | } | 2565 | } |
| 2553 | 2566 | ||