mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-01 12:19:28 +00:00
output_data(), output_datalen() and netflush() didn't actually guarantee
to do what they are supposed to: under some circumstances output data would be truncated, or the buffer would not actually be flushed (possibly leading to overflows when the caller assumes the operation succeeded). Change the semantics so that these functions ensure they complete the operation before returning. Comment out diagnostic code enabled by '-D reports' which causes an infinite recursion and an eventual crash. Patch developed with assistance from ru and assar.
This commit is contained in:
parent
27daeab3ec
commit
a2a887b56a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=80224
@ -190,7 +190,7 @@ extern void
|
||||
wontoption P((int));
|
||||
|
||||
int output_data __P((const char *, ...)) __printflike(1, 2);
|
||||
int output_datalen __P((const char *, size_t));
|
||||
void output_datalen __P((const char *, int));
|
||||
|
||||
#ifdef ENCRYPTION
|
||||
extern void (*encrypt_output) P((unsigned char *, int));
|
||||
|
@ -176,7 +176,6 @@ end_slc(bufp)
|
||||
register unsigned char **bufp;
|
||||
{
|
||||
register int len;
|
||||
void netflush();
|
||||
|
||||
/*
|
||||
* If a change has occured, store the new terminal control
|
||||
|
@ -1615,40 +1615,46 @@ send_status()
|
||||
|
||||
/*
|
||||
* This function appends data to nfrontp and advances nfrontp.
|
||||
* Returns the number of characters written altogether (the
|
||||
* buffer may have been flushed in the process).
|
||||
*/
|
||||
|
||||
int
|
||||
output_data(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
size_t remaining, ret;
|
||||
int len;
|
||||
char *buf;
|
||||
|
||||
va_start(args, format);
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
/* try a netflush() if the room is too low */
|
||||
if (strlen(format) > remaining || BUFSIZ / 4 > remaining) {
|
||||
netflush();
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
}
|
||||
ret = vsnprintf(nfrontp, remaining, format, args);
|
||||
nfrontp += (ret < remaining) ? ret : remaining;
|
||||
if ((len = vasprintf(&buf, format, args)) == -1)
|
||||
return -1;
|
||||
output_datalen(buf, len);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
output_datalen(const char *buf, size_t len)
|
||||
{
|
||||
size_t remaining;
|
||||
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
if (remaining < len) {
|
||||
netflush();
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
if (remaining < len)
|
||||
return -1;
|
||||
}
|
||||
memmove(nfrontp, buf, len);
|
||||
nfrontp += len;
|
||||
free(buf);
|
||||
return (len);
|
||||
}
|
||||
|
||||
void
|
||||
output_datalen(const char *buf, int len)
|
||||
{
|
||||
int remaining, copied;
|
||||
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
while (len > 0) {
|
||||
/* Free up enough space if the room is too low*/
|
||||
if ((len > BUFSIZ ? BUFSIZ : len) > remaining) {
|
||||
netflush();
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
}
|
||||
|
||||
/* Copy out as much as will fit */
|
||||
copied = remaining > len ? len : remaining;
|
||||
memmove(nfrontp, buf, copied);
|
||||
nfrontp += copied;
|
||||
len -= copied;
|
||||
remaining -= copied;
|
||||
buf += copied;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -952,7 +952,6 @@ telnet(f, p, host)
|
||||
char *HE;
|
||||
char *HN;
|
||||
char *IM;
|
||||
void netflush();
|
||||
int nfd;
|
||||
|
||||
/*
|
||||
|
@ -140,7 +140,6 @@ int newmap = 1; /* nonzero if \n maps to ^M^J */
|
||||
void
|
||||
localstat()
|
||||
{
|
||||
void netflush();
|
||||
int need_will_echo = 0;
|
||||
|
||||
#if defined(CRAY2) && defined(UNICOS5)
|
||||
@ -404,7 +403,6 @@ flowstat()
|
||||
clientstat(code, parm1, parm2)
|
||||
register int code, parm1, parm2;
|
||||
{
|
||||
void netflush();
|
||||
|
||||
/*
|
||||
* Get a copy of terminal characteristics.
|
||||
|
@ -69,10 +69,9 @@ static const char rcsid[] =
|
||||
void
|
||||
ttloop()
|
||||
{
|
||||
void netflush();
|
||||
|
||||
DIAG(TD_REPORT, output_data("td: ttloop\r\n"));
|
||||
if (nfrontp-nbackp) {
|
||||
if (nfrontp - nbackp > 0) {
|
||||
netflush();
|
||||
}
|
||||
ncc = read(net, netibuf, sizeof netibuf);
|
||||
@ -257,10 +256,13 @@ netflush()
|
||||
int n;
|
||||
extern int not42;
|
||||
|
||||
if ((n = nfrontp - nbackp) > 0) {
|
||||
while ((n = nfrontp - nbackp) > 0) {
|
||||
#if 0
|
||||
/* XXX This causes output_data() to recurse and die */
|
||||
DIAG(TD_REPORT, {
|
||||
n += output_data("td: netflush %d chars\r\n", n);
|
||||
});
|
||||
#endif
|
||||
#ifdef ENCRYPTION
|
||||
if (encrypt_output) {
|
||||
char *s = nclearto ? nclearto : nbackp;
|
||||
@ -293,25 +295,26 @@ netflush()
|
||||
n = send(net, nbackp, n, MSG_OOB); /* URGENT data */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (n < 0) {
|
||||
if (errno == EWOULDBLOCK || errno == EINTR)
|
||||
return;
|
||||
cleanup(0);
|
||||
}
|
||||
nbackp += n;
|
||||
if (n == -1) {
|
||||
if (errno == EWOULDBLOCK || errno == EINTR)
|
||||
continue;
|
||||
cleanup(0);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
nbackp += n;
|
||||
#ifdef ENCRYPTION
|
||||
if (nbackp > nclearto)
|
||||
nclearto = 0;
|
||||
if (nbackp > nclearto)
|
||||
nclearto = 0;
|
||||
#endif /* ENCRYPTION */
|
||||
if (nbackp >= neturg) {
|
||||
neturg = 0;
|
||||
}
|
||||
if (nbackp == nfrontp) {
|
||||
nbackp = nfrontp = netobuf;
|
||||
if (nbackp >= neturg) {
|
||||
neturg = 0;
|
||||
}
|
||||
if (nbackp == nfrontp) {
|
||||
nbackp = nfrontp = netobuf;
|
||||
#ifdef ENCRYPTION
|
||||
nclearto = 0;
|
||||
nclearto = 0;
|
||||
#endif /* ENCRYPTION */
|
||||
}
|
||||
}
|
||||
return;
|
||||
} /* end of netflush */
|
||||
|
@ -190,7 +190,7 @@ extern void
|
||||
wontoption P((int));
|
||||
|
||||
int output_data __P((const char *, ...)) __printflike(1, 2);
|
||||
int output_datalen __P((const char *, size_t));
|
||||
void output_datalen __P((const char *, int));
|
||||
|
||||
#ifdef ENCRYPTION
|
||||
extern void (*encrypt_output) P((unsigned char *, int));
|
||||
|
@ -176,7 +176,6 @@ end_slc(bufp)
|
||||
register unsigned char **bufp;
|
||||
{
|
||||
register int len;
|
||||
void netflush();
|
||||
|
||||
/*
|
||||
* If a change has occured, store the new terminal control
|
||||
|
@ -1615,40 +1615,46 @@ send_status()
|
||||
|
||||
/*
|
||||
* This function appends data to nfrontp and advances nfrontp.
|
||||
* Returns the number of characters written altogether (the
|
||||
* buffer may have been flushed in the process).
|
||||
*/
|
||||
|
||||
int
|
||||
output_data(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
size_t remaining, ret;
|
||||
int len;
|
||||
char *buf;
|
||||
|
||||
va_start(args, format);
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
/* try a netflush() if the room is too low */
|
||||
if (strlen(format) > remaining || BUFSIZ / 4 > remaining) {
|
||||
netflush();
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
}
|
||||
ret = vsnprintf(nfrontp, remaining, format, args);
|
||||
nfrontp += (ret < remaining) ? ret : remaining;
|
||||
if ((len = vasprintf(&buf, format, args)) == -1)
|
||||
return -1;
|
||||
output_datalen(buf, len);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
output_datalen(const char *buf, size_t len)
|
||||
{
|
||||
size_t remaining;
|
||||
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
if (remaining < len) {
|
||||
netflush();
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
if (remaining < len)
|
||||
return -1;
|
||||
}
|
||||
memmove(nfrontp, buf, len);
|
||||
nfrontp += len;
|
||||
free(buf);
|
||||
return (len);
|
||||
}
|
||||
|
||||
void
|
||||
output_datalen(const char *buf, int len)
|
||||
{
|
||||
int remaining, copied;
|
||||
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
while (len > 0) {
|
||||
/* Free up enough space if the room is too low*/
|
||||
if ((len > BUFSIZ ? BUFSIZ : len) > remaining) {
|
||||
netflush();
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
}
|
||||
|
||||
/* Copy out as much as will fit */
|
||||
copied = remaining > len ? len : remaining;
|
||||
memmove(nfrontp, buf, copied);
|
||||
nfrontp += copied;
|
||||
len -= copied;
|
||||
remaining -= copied;
|
||||
buf += copied;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -952,7 +952,6 @@ telnet(f, p, host)
|
||||
char *HE;
|
||||
char *HN;
|
||||
char *IM;
|
||||
void netflush();
|
||||
int nfd;
|
||||
|
||||
/*
|
||||
|
@ -140,7 +140,6 @@ int newmap = 1; /* nonzero if \n maps to ^M^J */
|
||||
void
|
||||
localstat()
|
||||
{
|
||||
void netflush();
|
||||
int need_will_echo = 0;
|
||||
|
||||
#if defined(CRAY2) && defined(UNICOS5)
|
||||
@ -404,7 +403,6 @@ flowstat()
|
||||
clientstat(code, parm1, parm2)
|
||||
register int code, parm1, parm2;
|
||||
{
|
||||
void netflush();
|
||||
|
||||
/*
|
||||
* Get a copy of terminal characteristics.
|
||||
|
@ -69,10 +69,9 @@ static const char rcsid[] =
|
||||
void
|
||||
ttloop()
|
||||
{
|
||||
void netflush();
|
||||
|
||||
DIAG(TD_REPORT, output_data("td: ttloop\r\n"));
|
||||
if (nfrontp-nbackp) {
|
||||
if (nfrontp - nbackp > 0) {
|
||||
netflush();
|
||||
}
|
||||
ncc = read(net, netibuf, sizeof netibuf);
|
||||
@ -257,10 +256,13 @@ netflush()
|
||||
int n;
|
||||
extern int not42;
|
||||
|
||||
if ((n = nfrontp - nbackp) > 0) {
|
||||
while ((n = nfrontp - nbackp) > 0) {
|
||||
#if 0
|
||||
/* XXX This causes output_data() to recurse and die */
|
||||
DIAG(TD_REPORT, {
|
||||
n += output_data("td: netflush %d chars\r\n", n);
|
||||
});
|
||||
#endif
|
||||
#ifdef ENCRYPTION
|
||||
if (encrypt_output) {
|
||||
char *s = nclearto ? nclearto : nbackp;
|
||||
@ -293,25 +295,26 @@ netflush()
|
||||
n = send(net, nbackp, n, MSG_OOB); /* URGENT data */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (n < 0) {
|
||||
if (errno == EWOULDBLOCK || errno == EINTR)
|
||||
return;
|
||||
cleanup(0);
|
||||
}
|
||||
nbackp += n;
|
||||
if (n == -1) {
|
||||
if (errno == EWOULDBLOCK || errno == EINTR)
|
||||
continue;
|
||||
cleanup(0);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
nbackp += n;
|
||||
#ifdef ENCRYPTION
|
||||
if (nbackp > nclearto)
|
||||
nclearto = 0;
|
||||
if (nbackp > nclearto)
|
||||
nclearto = 0;
|
||||
#endif /* ENCRYPTION */
|
||||
if (nbackp >= neturg) {
|
||||
neturg = 0;
|
||||
}
|
||||
if (nbackp == nfrontp) {
|
||||
nbackp = nfrontp = netobuf;
|
||||
if (nbackp >= neturg) {
|
||||
neturg = 0;
|
||||
}
|
||||
if (nbackp == nfrontp) {
|
||||
nbackp = nfrontp = netobuf;
|
||||
#ifdef ENCRYPTION
|
||||
nclearto = 0;
|
||||
nclearto = 0;
|
||||
#endif /* ENCRYPTION */
|
||||
}
|
||||
}
|
||||
return;
|
||||
} /* end of netflush */
|
||||
|
Loading…
Reference in New Issue
Block a user