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:
Kris Kennaway 2001-07-23 21:52:26 +00:00
parent 27daeab3ec
commit a2a887b56a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=80224
12 changed files with 108 additions and 98 deletions

View File

@ -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));

View File

@ -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

View File

@ -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;
}

View File

@ -952,7 +952,6 @@ telnet(f, p, host)
char *HE;
char *HN;
char *IM;
void netflush();
int nfd;
/*

View File

@ -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.

View File

@ -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 */

View File

@ -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));

View File

@ -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

View File

@ -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;
}

View File

@ -952,7 +952,6 @@ telnet(f, p, host)
char *HE;
char *HN;
char *IM;
void netflush();
int nfd;
/*

View File

@ -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.

View File

@ -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 */