From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Philipp Stephani
> From: Phili= pp <p.stephan= i2@gmail.com>
> Date: Sat, 06 Jan 2018 12:39:43 +0100
>
> (call-interactively (lambda (a b) (interactive "sa\0b\ns")))=
>
> the prompt is only "a" and a `wrong-number-of-argument' = signal is
> raised.=C2=A0 This is because `call-interactively' copies the inte= ractive
> specification to a C string, ignoring embedded nulls.
No, it copies the spec in its entirety, including embedded null bytes,
but then _processes_ the result as a C string, taking the first null
byte as the end of the string.
Does the patch below look right, and give good results?
diff --git a/src/callint.c b/src/callint.c
index 2253cdf..3d2ed00 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -288,7 +288,8 @@ invoke it.=C2=A0 If KEYS is omitted or nil, the return = value of
=C2=A0 =C2=A0ptrdiff_t next_event;
=C2=A0 =C2=A0Lisp_Object prefix_arg;
-=C2=A0 char *string;
+=C2=A0 char *string, *string_end;
+=C2=A0 ptrdiff_t string_len;
=C2=A0 =C2=A0const char *tem;
=C2=A0 =C2=A0/* If varies[i] > 0, the i'th argument shouldn't ju= st have its value
@@ -396,6 +397,8 @@ invoke it.=C2=A0 If KEYS is omitted or nil, the return = value of
=C2=A0 =C2=A0/* SPECS is set to a string; use it as an interactive prompt.<= br> =C2=A0 =C2=A0 =C2=A0 Copy it so that STRING will be valid even if a GC relo= cates SPECS.=C2=A0 */
=C2=A0 =C2=A0SAFE_ALLOCA_STRING (string, specs);
+=C2=A0 string_len =3D SBYTES (specs);
+=C2=A0 string_end =3D string + string_len;
=C2=A0 =C2=A0/* Here if function specifies a string to control parsing the = defaults.=C2=A0 */
@@ -418,7 +421,7 @@ invoke it.=C2=A0 If KEYS is omitted or nil, the return = value of
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (!NILP (record_flag)) =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 char *p =3D = string;
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0while (*p) +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0while (p <= ; string_end)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 if (! (*p =3D=3D 'r' || *p =3D=3D 'p' || *p =3D=3D '= ;P'
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|| *p =3D=3D '\n'))
@@ -469,7 +472,7 @@ invoke it.=C2=A0 If KEYS is omitted or nil, the return = value of
=C2=A0 =C2=A0 =C2=A0 `funcall-interactively') plus the number of argume= nts the interactive spec
=C2=A0 =C2=A0 =C2=A0 would have us give to the function.=C2=A0 */
=C2=A0 =C2=A0tem =3D string;
-=C2=A0 for (nargs =3D 2; *tem; )
+=C2=A0 for (nargs =3D 2; tem < string_end; )
=C2=A0 =C2=A0 =C2=A0{
=C2=A0 =C2=A0 =C2=A0 =C2=A0/* 'r' specifications ("point and m= ark as 2 numeric args")
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0produce *two* arguments.=C2=A0 */
@@ -477,7 +480,7 @@ invoke it.=C2=A0 If KEYS is omitted or nil, the return = value of
=C2=A0 =C2=A0 =C2=A0 =C2=A0 nargs +=3D 2;
=C2=A0 =C2=A0 =C2=A0 =C2=A0else
=C2=A0 =C2=A0 =C2=A0 =C2=A0 nargs++;
-=C2=A0 =C2=A0 =C2=A0 tem =3D strchr (tem, '\n');
+=C2=A0 =C2=A0 =C2=A0 tem =3D memchr (tem, '\n', string_len - (tem = - string));
=C2=A0 =C2=A0 =C2=A0 =C2=A0if (tem)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ++tem;
=C2=A0 =C2=A0 =C2=A0 =C2=A0else
@@ -503,9 +506,12 @@ invoke it.=C2=A0 If KEYS is omitted or nil, the return= value of
=C2=A0 =C2=A0 =C2=A0specbind (Qenable_recursive_minibuffers, Qt);
=C2=A0 =C2=A0tem =3D string;
-=C2=A0 for (i =3D 2; *tem; i++)
+=C2=A0 for (i =3D 2; tem < string_end; i++)
=C2=A0 =C2=A0 =C2=A0{
-=C2=A0 =C2=A0 =C2=A0 visargs[1] =3D make_string (tem + 1, strcspn (tem + 1= , "\n"));
+=C2=A0 =C2=A0 =C2=A0 char *pnl =3D memchr (tem + 1, '\n', string_l= en - (tem + 1 - string));
+=C2=A0 =C2=A0 =C2=A0 ptrdiff_t sz =3D pnl ? pnl - (tem + 1) : string_end -= (tem + 1);
+
+=C2=A0 =C2=A0 =C2=A0 visargs[1] =3D make_string (tem + 1, sz);
=C2=A0 =C2=A0 =C2=A0 =C2=A0callint_message =3D Fformat_message (i - 1, visa= rgs + 1);
=C2=A0 =C2=A0 =C2=A0 =C2=A0switch (*tem)
@@ -781,7 +787,7 @@ invoke it.=C2=A0 If KEYS is omitted or nil, the return = value of
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* How many bytes are left unproc= essed in the specs string?
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(Note that this excl= udes the trailing null byte.)=C2=A0 */
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ptrdiff_t bytes_left =3D SBYTES (= specs) - (tem - string);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ptrdiff_t bytes_left =3D string_l= en - (tem - string);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 unsigned letter;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* If we have enough bytes left t= o treat the sequence as a
@@ -803,9 +809,9 @@ invoke it.=C2=A0 If KEYS is omitted or nil, the return = value of
=C2=A0 =C2=A0 =C2=A0 =C2=A0if (NILP (visargs[i]) && STRINGP (args[i= ]))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 visargs[i] =3D args[i];
-=C2=A0 =C2=A0 =C2=A0 tem =3D strchr (tem, '\n');
+=C2=A0 =C2=A0 =C2=A0 tem =3D memchr (tem, '\n', string_len - (tem = - string));
=C2=A0 =C2=A0 =C2=A0 =C2=A0if (tem) tem++;
-=C2=A0 =C2=A0 =C2=A0 else tem =3D "";
+=C2=A0 =C2=A0 =C2=A0 else tem =3D string_end;
=C2=A0 =C2=A0 =C2=A0}
=C2=A0 =C2=A0unbind_to (speccount, Qnil);