diff options
| author | Eli Zaretskii | 2018-01-23 17:48:08 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2018-01-23 17:48:08 +0200 |
| commit | 6d836771da7e9a6a67fcd18e52dd16de1cdc154e (patch) | |
| tree | eba6486f1f95de4ac3e244f0ed7969458905a7a6 /src | |
| parent | 0a75af915653bd8927f92be420603725a7e3c744 (diff) | |
| download | emacs-6d836771da7e9a6a67fcd18e52dd16de1cdc154e.tar.gz emacs-6d836771da7e9a6a67fcd18e52dd16de1cdc154e.zip | |
Support null characters in interactive specs
* src/callint.c (Fcall_interactively): Support 'interactive'
specifications with embedded null characters. (Bug#30005)
Diffstat (limited to 'src')
| -rw-r--r-- | src/callint.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/src/callint.c b/src/callint.c index 2253cdf3b44..3d2ed0016cc 100644 --- a/src/callint.c +++ b/src/callint.c | |||
| @@ -288,7 +288,8 @@ invoke it. If KEYS is omitted or nil, the return value of | |||
| 288 | ptrdiff_t next_event; | 288 | ptrdiff_t next_event; |
| 289 | 289 | ||
| 290 | Lisp_Object prefix_arg; | 290 | Lisp_Object prefix_arg; |
| 291 | char *string; | 291 | char *string, *string_end; |
| 292 | ptrdiff_t string_len; | ||
| 292 | const char *tem; | 293 | const char *tem; |
| 293 | 294 | ||
| 294 | /* If varies[i] > 0, the i'th argument shouldn't just have its value | 295 | /* If varies[i] > 0, the i'th argument shouldn't just have its value |
| @@ -396,6 +397,8 @@ invoke it. If KEYS is omitted or nil, the return value of | |||
| 396 | /* SPECS is set to a string; use it as an interactive prompt. | 397 | /* SPECS is set to a string; use it as an interactive prompt. |
| 397 | Copy it so that STRING will be valid even if a GC relocates SPECS. */ | 398 | Copy it so that STRING will be valid even if a GC relocates SPECS. */ |
| 398 | SAFE_ALLOCA_STRING (string, specs); | 399 | SAFE_ALLOCA_STRING (string, specs); |
| 400 | string_len = SBYTES (specs); | ||
| 401 | string_end = string + string_len; | ||
| 399 | 402 | ||
| 400 | /* Here if function specifies a string to control parsing the defaults. */ | 403 | /* Here if function specifies a string to control parsing the defaults. */ |
| 401 | 404 | ||
| @@ -418,7 +421,7 @@ invoke it. If KEYS is omitted or nil, the return value of | |||
| 418 | if (!NILP (record_flag)) | 421 | if (!NILP (record_flag)) |
| 419 | { | 422 | { |
| 420 | char *p = string; | 423 | char *p = string; |
| 421 | while (*p) | 424 | while (p < string_end) |
| 422 | { | 425 | { |
| 423 | if (! (*p == 'r' || *p == 'p' || *p == 'P' | 426 | if (! (*p == 'r' || *p == 'p' || *p == 'P' |
| 424 | || *p == '\n')) | 427 | || *p == '\n')) |
| @@ -469,7 +472,7 @@ invoke it. If KEYS is omitted or nil, the return value of | |||
| 469 | `funcall-interactively') plus the number of arguments the interactive spec | 472 | `funcall-interactively') plus the number of arguments the interactive spec |
| 470 | would have us give to the function. */ | 473 | would have us give to the function. */ |
| 471 | tem = string; | 474 | tem = string; |
| 472 | for (nargs = 2; *tem; ) | 475 | for (nargs = 2; tem < string_end; ) |
| 473 | { | 476 | { |
| 474 | /* 'r' specifications ("point and mark as 2 numeric args") | 477 | /* 'r' specifications ("point and mark as 2 numeric args") |
| 475 | produce *two* arguments. */ | 478 | produce *two* arguments. */ |
| @@ -477,7 +480,7 @@ invoke it. If KEYS is omitted or nil, the return value of | |||
| 477 | nargs += 2; | 480 | nargs += 2; |
| 478 | else | 481 | else |
| 479 | nargs++; | 482 | nargs++; |
| 480 | tem = strchr (tem, '\n'); | 483 | tem = memchr (tem, '\n', string_len - (tem - string)); |
| 481 | if (tem) | 484 | if (tem) |
| 482 | ++tem; | 485 | ++tem; |
| 483 | else | 486 | else |
| @@ -503,9 +506,12 @@ invoke it. If KEYS is omitted or nil, the return value of | |||
| 503 | specbind (Qenable_recursive_minibuffers, Qt); | 506 | specbind (Qenable_recursive_minibuffers, Qt); |
| 504 | 507 | ||
| 505 | tem = string; | 508 | tem = string; |
| 506 | for (i = 2; *tem; i++) | 509 | for (i = 2; tem < string_end; i++) |
| 507 | { | 510 | { |
| 508 | visargs[1] = make_string (tem + 1, strcspn (tem + 1, "\n")); | 511 | char *pnl = memchr (tem + 1, '\n', string_len - (tem + 1 - string)); |
| 512 | ptrdiff_t sz = pnl ? pnl - (tem + 1) : string_end - (tem + 1); | ||
| 513 | |||
| 514 | visargs[1] = make_string (tem + 1, sz); | ||
| 509 | callint_message = Fformat_message (i - 1, visargs + 1); | 515 | callint_message = Fformat_message (i - 1, visargs + 1); |
| 510 | 516 | ||
| 511 | switch (*tem) | 517 | switch (*tem) |
| @@ -781,7 +787,7 @@ invoke it. If KEYS is omitted or nil, the return value of | |||
| 781 | { | 787 | { |
| 782 | /* How many bytes are left unprocessed in the specs string? | 788 | /* How many bytes are left unprocessed in the specs string? |
| 783 | (Note that this excludes the trailing null byte.) */ | 789 | (Note that this excludes the trailing null byte.) */ |
| 784 | ptrdiff_t bytes_left = SBYTES (specs) - (tem - string); | 790 | ptrdiff_t bytes_left = string_len - (tem - string); |
| 785 | unsigned letter; | 791 | unsigned letter; |
| 786 | 792 | ||
| 787 | /* If we have enough bytes left to treat the sequence as a | 793 | /* If we have enough bytes left to treat the sequence as a |
| @@ -803,9 +809,9 @@ invoke it. If KEYS is omitted or nil, the return value of | |||
| 803 | if (NILP (visargs[i]) && STRINGP (args[i])) | 809 | if (NILP (visargs[i]) && STRINGP (args[i])) |
| 804 | visargs[i] = args[i]; | 810 | visargs[i] = args[i]; |
| 805 | 811 | ||
| 806 | tem = strchr (tem, '\n'); | 812 | tem = memchr (tem, '\n', string_len - (tem - string)); |
| 807 | if (tem) tem++; | 813 | if (tem) tem++; |
| 808 | else tem = ""; | 814 | else tem = string_end; |
| 809 | } | 815 | } |
| 810 | unbind_to (speccount, Qnil); | 816 | unbind_to (speccount, Qnil); |
| 811 | 817 | ||