open_memstream() ‒ NUL injected on seek/write that doesn't bump the size, I think it can't be per POSIX (and other implementations don't)
наб
nabijaczleweli@nabijaczleweli.xyz
Wed Sep 18 21:31:45 GMT 2024
Hi!
I've found what I think is a discrepancy between glibc and POSIX,
and is definitely a difference between glibc and other libcs,
in how open_memstream() treats seeking into the middle.
Behold the test program:
#include <stdio.h>
int main() {
char *dt;
size_t s;
FILE * f = open_memstream(&dt, &s);
1 fputs("gaming", f);
2 fputs("tereftalan", f);
3 fseek(f, 6, SEEK_SET);
4 fputc('Q', f);
fclose(f);
puts(dt);
printf("%zu\n", s);
}
This yields "gamingQereftalan", 7 on musl and the illumos gate,
and "gamingQ", 7 on glibc.
POSIX.1-2024 defers to C, and says
51164 The stream shall maintain a current position in the allocated buffer and a current buffer length.
51165 The position shall be initially set to zero (the start of the buffer). Each write to the stream shall
51166 start at the current position and move this position by the number of successfully written bytes
51167 for open_memstream( )
51168 The length shall be initially set to zero. If a write moves the position to a
51169 value larger than the current length, the current length shall be set to this position. In this case a
51170 null character for open_memstream( ) shall be
51171 appended to the current buffer. The terminating null is not included in the
51172 calculation of the buffer length.
51173 After a successful fflush( ) or fclose( ), the pointer referenced by bufp shall contain the address of
51174 the buffer, and the variable pointed to by sizep shall contain the smaller of the current buffer
51175 length and the number of bytes for open_memstream( ),
51176 between the beginning of the buffer and the current file position indicator.
51177 The fseek( ) and fseeko( ) functions can be used to set the file position beyond the current buffer
51178 length. [this example doesn't trigger this]
51182 If fseek( ) or fseeko( ) is called
51183 with SEEK_END as the whence argument [this example doesn't]
Thus, if fflush(f) was called after:
1: [dt, dt + s] = "gaming\0"
2: [dt, dt + s] = "gamingtereftalan\0"
3: [dt, dt + s] = "gamingt"
4: [dt, dt + s] = "gamingQe"
because, per ll. 51168-51171,
only 1 and 2 move the cursor beyond the length.
Right?
Best,
наб
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20240918/e85380b1/attachment.sig>
More information about the Libc-alpha
mailing list