*sigh* this code is interesting: assume you want to output via shf to

a string buffer whose window size is currently 32 (initial), your data
is 96 bytes, this routine used to resize the buffer to 64, append your
first 64 bytes to it (no matter if there's already something in it)
and then writes the remaining bytes to stdio fd instead of the string…
if it doesn’t SIGABRT before

discovered by wbx@ – thanks – bug inherited from pdksh 5.2.14 (AD 1999)
This commit is contained in:
tg 2010-07-19 22:41:04 +00:00
parent f10186fedd
commit c6eedad976
3 changed files with 39 additions and 26 deletions

View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.382 2010/07/17 22:09:30 tg Exp $
# $MirOS: src/bin/mksh/check.t,v 1.383 2010/07/19 22:41:01 tg Exp $
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
@ -25,7 +25,7 @@
# http://www.research.att.com/~gsf/public/ifs.sh
expected-stdout:
@(#)MIRBSD KSH R39 2010/07/17
@(#)MIRBSD KSH R39 2010/07/19
description:
Check version of shell.
stdin:

4
sh.h
View File

@ -150,9 +150,9 @@
#endif
#ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.398 2010/07/17 22:09:38 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.399 2010/07/19 22:41:03 tg Exp $");
#endif
#define MKSH_VERSION "R39 2010/07/17"
#define MKSH_VERSION "R39 2010/07/19"
#ifndef MKSH_INCLUDES_ONLY

57
shf.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.35 2009/11/28 14:28:03 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.36 2010/07/19 22:41:04 tg Exp $");
/* flags to shf_emptybuf() */
#define EB_READSW 0x01 /* about to switch to reading */
@ -636,32 +636,45 @@ shf_write(const char *buf, int nbytes, struct shf *shf)
shf->wnleft -= ncopy;
}
if (nbytes > 0) {
/* Flush deals with strings and sticky errors */
if (shf_emptybuf(shf, EB_GROW) == EOF)
return (EOF);
if (nbytes > shf->wbsize) {
ncopy = nbytes;
if (shf->wbsize)
ncopy -= nbytes % shf->wbsize;
nbytes -= ncopy;
while (ncopy > 0) {
n = write(shf->fd, buf, ncopy);
if (n < 0) {
if (errno == EINTR &&
!(shf->flags & SHF_INTERRUPT))
continue;
shf->flags |= SHF_ERROR;
shf->errno_ = errno;
shf->wnleft = 0;
/* Note: fwrite(3S) returns 0 for
* errors - this doesn't */
if (shf->flags & SHF_STRING) {
/* resize buffer until there's enough space left */
while (nbytes > shf->wnleft)
if (shf_emptybuf(shf, EB_GROW) == EOF)
return (EOF);
/* then write everything into the buffer */
} else {
/* flush deals with sticky errors */
if (shf_emptybuf(shf, EB_GROW) == EOF)
return (EOF);
/* write chunks larger than window size directly */
if (nbytes > shf->wbsize) {
ncopy = nbytes;
if (shf->wbsize)
ncopy -= nbytes % shf->wbsize;
nbytes -= ncopy;
while (ncopy > 0) {
n = write(shf->fd, buf, ncopy);
if (n < 0) {
if (errno == EINTR &&
!(shf->flags & SHF_INTERRUPT))
continue;
shf->flags |= SHF_ERROR;
shf->errno_ = errno;
shf->wnleft = 0;
/*
* Note: fwrite(3) returns 0
* for errors - this doesn't
*/
return (EOF);
}
buf += n;
ncopy -= n;
}
buf += n;
ncopy -= n;
}
/* ... and buffer the rest */
}
if (nbytes > 0) {
/* write remaining bytes to buffer */
memcpy(shf->wp, buf, nbytes);
shf->wp += nbytes;
shf->wnleft -= nbytes;