static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) { StdoutStream *s = userdata; size_t limit; ssize_t l; int r; assert(s); if ((revents|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) { log_error("Got invalid event from epoll for stdout stream: %"PRIx32, revents); goto terminate; } /* If the buffer is full already (discounting the extra NUL we need), add room for another 1K */ if (s->length + 1 >= s->allocated) { if (!GREEDY_REALLOC(s->buffer, s->allocated, s->length + 1 + 1024)) { log_oom(); goto terminate; } } /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also, * always leave room for a terminating NUL we might need to add. */ limit = MIN(s->allocated - 1, s->server->line_max); l = read(s->fd, s->buffer + s->length, limit - s->length); if (l < 0) { if (errno == EAGAIN) return 0; log_warning_errno(errno, "Failed to read from stream: %m"); goto terminate; } if (l == 0) { stdout_stream_scan(s, true); goto terminate; } s->length += l; r = stdout_stream_scan(s, false); if (r < 0) goto terminate; return 1; terminate: stdout_stream_destroy(s); return 0; }
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { Server s; StdoutStream *stream; int v; if (size == 0 || size > 65536) return 0; if (!getenv("SYSTEMD_LOG_LEVEL")) log_set_max_level(LOG_CRIT); assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0, stream_fds) >= 0); dummy_server_init(&s, NULL, 0); assert_se(stdout_stream_install(&s, stream_fds[0], &stream) >= 0); assert_se(write(stream_fds[1], data, size) == (ssize_t) size); while (ioctl(stream_fds[0], SIOCINQ, &v) == 0 && v) sd_event_run(s.event, (uint64_t) -1); if (s.n_stdout_streams) stdout_stream_destroy(stream); server_done(&s); stream_fds[1] = safe_close(stream_fds[1]); return 0; }