emacsclient receiving long-line fixes
Do not mishandle long lines, or lines containing NUL, when receiving data. * lib-src/emacsclient.c (check_socket_timeout, main): Use ssize_t for return values from recv, since in theory the value could exceed INT_MAX now. (main): Do not use a fixed-size buffer for receiving data; instead, grow the buffer as needed (admittedly unlikely). When a partial line is received via recv, do not discard its data; instead, keep reading, possibly with a grown buffer. Do not ignore received data after a null byte is received. Add a comment about when received data is ignored due to a goto.
This commit is contained in:
@@ -1975,7 +1975,7 @@ set_socket_timeout (HSOCKET socket, int seconds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
check_socket_timeout (int rl)
|
check_socket_timeout (ssize_t rl)
|
||||||
{
|
{
|
||||||
#ifndef WINDOWSNT
|
#ifndef WINDOWSNT
|
||||||
return (rl == -1)
|
return (rl == -1)
|
||||||
@@ -1994,9 +1994,11 @@ main (int argc, char **argv)
|
|||||||
main_argv = argv;
|
main_argv = argv;
|
||||||
progname = argv[0] ? argv[0] : "emacsclient";
|
progname = argv[0] ? argv[0] : "emacsclient";
|
||||||
|
|
||||||
int rl = 0;
|
ssize_t rl = 0;
|
||||||
bool skiplf = true;
|
bool skiplf = true;
|
||||||
char string[BUFSIZ + 1];
|
char *recv_buf = NULL;
|
||||||
|
ptrdiff_t recv_bufsize = 0;
|
||||||
|
|
||||||
int exit_status = EXIT_SUCCESS;
|
int exit_status = EXIT_SUCCESS;
|
||||||
|
|
||||||
#ifdef HAVE_NTGUI
|
#ifdef HAVE_NTGUI
|
||||||
@@ -2208,6 +2210,8 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
set_socket_timeout (emacs_socket, timeout > 0 ? timeout : DEFAULT_TIMEOUT);
|
set_socket_timeout (emacs_socket, timeout > 0 ? timeout : DEFAULT_TIMEOUT);
|
||||||
bool saw_response = false;
|
bool saw_response = false;
|
||||||
|
ptrdiff_t nrecv = 0;
|
||||||
|
|
||||||
/* Now, wait for an answer and print any messages. */
|
/* Now, wait for an answer and print any messages. */
|
||||||
while (exit_status == EXIT_SUCCESS)
|
while (exit_status == EXIT_SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -2216,7 +2220,14 @@ main (int argc, char **argv)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
act_on_signals (emacs_socket);
|
act_on_signals (emacs_socket);
|
||||||
rl = recv (emacs_socket, string, BUFSIZ, 0);
|
if (nrecv == recv_bufsize)
|
||||||
|
{
|
||||||
|
enum { DEFAULT_RECV_BUFSIZE = 4096 };
|
||||||
|
recv_bufsize = (recv_bufsize + (recv_bufsize >> 1)
|
||||||
|
+ DEFAULT_RECV_BUFSIZE);
|
||||||
|
recv_buf = xrealloc (recv_buf, recv_bufsize);
|
||||||
|
}
|
||||||
|
rl = recv (emacs_socket, recv_buf + nrecv, recv_bufsize - nrecv, 0);
|
||||||
retry = check_socket_timeout (rl);
|
retry = check_socket_timeout (rl);
|
||||||
if (retry && !saw_response)
|
if (retry && !saw_response)
|
||||||
{
|
{
|
||||||
@@ -2239,16 +2250,17 @@ main (int argc, char **argv)
|
|||||||
if (rl <= 0)
|
if (rl <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
nrecv += rl;
|
||||||
saw_response = true;
|
saw_response = true;
|
||||||
string[rl] = '\0';
|
|
||||||
|
|
||||||
/* Loop over all NL-terminated messages. */
|
/* Loop over all NL-terminated messages. */
|
||||||
char *p = string;
|
char *p = recv_buf;
|
||||||
for (char *end_p = p; end_p && *end_p != '\0'; p = end_p)
|
for (char *end_p = p; end_p < recv_buf + nrecv; p = end_p)
|
||||||
{
|
{
|
||||||
end_p = strchr (p, '\n');
|
end_p = memchr (p, '\n', recv_buf + nrecv - p);
|
||||||
if (end_p != NULL)
|
if (!end_p)
|
||||||
*end_p++ = '\0';
|
break;
|
||||||
|
*end_p++ = '\0';
|
||||||
|
|
||||||
if (strprefix ("-emacs-pid ", p))
|
if (strprefix ("-emacs-pid ", p))
|
||||||
{
|
{
|
||||||
@@ -2271,6 +2283,7 @@ main (int argc, char **argv)
|
|||||||
tty = true;
|
tty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This discards any remaining data in recv_buf. */
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
else if (strprefix ("-print ", p))
|
else if (strprefix ("-print ", p))
|
||||||
@@ -2324,6 +2337,9 @@ main (int argc, char **argv)
|
|||||||
skiplf = true;
|
skiplf = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nrecv -= p - recv_buf;
|
||||||
|
memmove (recv_buf, p, nrecv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skiplf && 0 <= process_grouping ())
|
if (!skiplf && 0 <= process_grouping ())
|
||||||
|
|||||||
Reference in New Issue
Block a user