Check for out of memory error on open_memstream's FILE operation

Viewed 138
  1. Does POSIX guarantees the ferror is set on open_memstream's FILE write operations?
  2. How do I check for out of memory condition on FILE operation if the FILE is created with open_memstream?

I used to assume that error should be set on the stream if the internal realloc fails and the error condition could be obtained with ferror, but the following test with glibc 2.31 shows it doesn't do so (Linux overcommit_memory is disabled):

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

static char chunk[1024] = {1};

int main(void) {
    size_t sz = 0;
    char *s = NULL;
    FILE *sf = open_memstream(&s, &sz);
    if (!sf) {
        fprintf(stderr, "%d: ERROR open_memstream failed: %s", (int)__LINE__, strerror(errno));
        return -1;
    }

    for (;;) {
        size_t new_n = fwrite(chunk, sizeof chunk, 1, sf);
        if (ferror(sf))
            fprintf(stderr, "%d: ERROR ferror(sf): %s\n", (int)__LINE__, strerror(errno));
        if (new_n == 0)
            break;
    }

    if (fflush(sf))
        fprintf(stderr, "%d: ERROR fflush(sf)\n", (int)__LINE__);
    if (ferror(sf))
        fprintf(stderr, "%d: ERROR ferror(sf)\n", (int)__LINE__);
        
    fprintf(stderr, "%d: writing done %zu\n", (int)__LINE__, sz);
    fclose(sf);
    free(s);
    return 0;
}

user@ws:~$ ./a.out 
30: writing done 4347395995

glibc ticket for the issue: https://sourceware.org/bugzilla/show_bug.cgi?id=26573

2 Answers

Does POSIX guarantees the ferror is set on open_memstream's FILE write operations?

To my suprise, no, I see nothing in open_memstream nor in ferror.

Browsing glibc, in glibc/memstream.c it does not set _IO_ERR_SEEN in flags, so ferror will not output.

How do I check for out of memory condition on FILE operation if the FILE is created with open_memstream?

Check if sz got incremented. Check errno.

The buffer is only observable after fflush, and

Upon successful completion, fflush() shall return 0; otherwise, it shall set the error indicator for the stream, return EOF, and set errno to indicate the error.

This imposes a requirement to set the error indicator.

Related