mirror of
git://git.musl-libc.org/musl
synced 2024-11-23 18:14:19 +08:00
fix multiple stdio functions' behavior on zero-length operations
previously, fgets, fputs, fread, and fwrite completely omitted locking and access to the FILE object when their arguments yielded a zero length read or write operation independent of the FILE state. this optimization was invalid; it wrongly skipped marking the stream as byte-oriented (a C conformance bug) and exposed observably missing synchronization (a POSIX conformance bug) where one of these functions could wrongly complete despite another thread provably holding the lock.
This commit is contained in:
parent
402611c3ba
commit
6e2bb7acf4
@ -10,14 +10,16 @@ char *fgets(char *restrict s, int n, FILE *restrict f)
|
||||
size_t k;
|
||||
int c;
|
||||
|
||||
FLOCK(f);
|
||||
|
||||
if (n--<=1) {
|
||||
f->mode |= f->mode-1;
|
||||
FUNLOCK(f);
|
||||
if (n) return 0;
|
||||
*s = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
FLOCK(f);
|
||||
|
||||
while (n) {
|
||||
z = memchr(f->rpos, '\n', f->rend - f->rpos);
|
||||
k = z ? z - f->rpos + 1 : f->rend - f->rpos;
|
||||
|
@ -3,9 +3,7 @@
|
||||
|
||||
int fputs(const char *restrict s, FILE *restrict f)
|
||||
{
|
||||
size_t l = strlen(s);
|
||||
if (!l) return 0;
|
||||
return (int)fwrite(s, l, 1, f) - 1;
|
||||
return (int)fwrite(s, strlen(s), 1, f) - 1;
|
||||
}
|
||||
|
||||
weak_alias(fputs, fputs_unlocked);
|
||||
|
@ -8,11 +8,10 @@ size_t fread(void *restrict destv, size_t size, size_t nmemb, FILE *restrict f)
|
||||
unsigned char *dest = destv;
|
||||
size_t len = size*nmemb, l = len, k;
|
||||
|
||||
/* Never touch the file if length is zero.. */
|
||||
if (!l) return 0;
|
||||
|
||||
FLOCK(f);
|
||||
|
||||
f->mode |= f->mode-1;
|
||||
|
||||
if (f->rend - f->rpos > 0) {
|
||||
/* First exhaust the buffer. */
|
||||
k = MIN(f->rend - f->rpos, l);
|
||||
|
@ -28,7 +28,6 @@ size_t __fwritex(const unsigned char *restrict s, size_t l, FILE *restrict f)
|
||||
size_t fwrite(const void *restrict src, size_t size, size_t nmemb, FILE *restrict f)
|
||||
{
|
||||
size_t k, l = size*nmemb;
|
||||
if (!l) return l;
|
||||
FLOCK(f);
|
||||
k = __fwritex(src, l, f);
|
||||
FUNLOCK(f);
|
||||
|
Loading…
Reference in New Issue
Block a user