From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 7006F385222A for ; Fri, 16 Dec 2022 17:51:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7006F385222A Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1671213115; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=Yey+RxED8mtXBR4X/4JO4A9tM+4+zt+uls1QSiowflQ=; b=RrWPrYQ9HeH48cl37PWDcVuaOhsbQGkjI5VKI6ulz4R/kdqUUAifi7zNNl55B9XyuBzCZT vBXKbJgZV0/K1XtcuhosDoKNFMwX+Z1kiazcT3jKgeyi/3g55vF9JU2E7O7eUIXIJgzB/z g6lzuuxtj+CEW8/aGlumjXs+g1fPmVY= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-278-KaFzhe-3Mp-08rLPGnXdWg-1; Fri, 16 Dec 2022 12:51:51 -0500 X-MC-Unique: KaFzhe-3Mp-08rLPGnXdWg-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 93E531C0898A; Fri, 16 Dec 2022 17:51:51 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.2.16.61]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8A575C15BA0; Fri, 16 Dec 2022 17:51:50 +0000 (UTC) From: Florian Weimer To: Adhemerval Zanella Netto Cc: libc-alpha@sourceware.org Subject: Re: [PATCH v5 02/11] stdio-common: Introduce buffers for implementing printf References: <9e6084af5260c144509be67a906696db99dc5ddf.1670858473.git.fweimer@redhat.com> Date: Fri, 16 Dec 2022 18:51:48 +0100 In-Reply-To: (Adhemerval Zanella Netto's message of "Wed, 14 Dec 2022 11:10:23 -0300") Message-ID: <877cyrtex7.fsf@oldenburg.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.1 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: * Adhemerval Zanella Netto: >> +/* Writes COUNT repeats of CH to BUF. */ >> +void __printf_buffer_pad_1 (struct __printf_buffer *buf, >> + char ch, size_t count) attribute_hidden; >> + >> +/* __printf_buffer_pad with fast path for no padding. COUNT is a >> + long int, to accomodate signed uses in printf and elsewhere. */ > > Wouldn't ssize works better here than long int? I'm going to test the change. >> +static inline void >> +__printf_buffer_pad (struct __printf_buffer *buf, char ch, long int count) >> +{ >> + if (count > 0) >> + __printf_buffer_pad_1 (buf, ch, count); >> +} >> + >> +/* Write COUNT bytes starting at S to BUF. S must not overlap with >> + the internal buffer. */ >> +void __printf_buffer_write (struct __printf_buffer *buf, const char *s, >> + size_t count) attribute_hidden; >> + >> +/* Write S to BUF. S must not overlap with the internal buffer. */ >> +void __printf_buffer_puts_1 (struct __printf_buffer *buf, const char *s) >> + attribute_hidden; > > Maybe a space here? Added an empty line. >> +static inline void >> +__printf_buffer_puts (struct __printf_buffer *buf, const char *s) >> +{ >> + if (__builtin_constant_p (__builtin_strlen (s))) >> + __printf_buffer_write (buf, s, __builtin_strlen (s)); >> + else >> + __printf_buffer_puts_1 (buf, s); >> +} >> + >> +/* Returns the number of bytes written through the buffer, or -1 if >> + there was an error (that is, __printf_buffer_has_failed (BUF) is true). >> + >> + The number of written bytes includes pending bytes in the buffer >> + (between BUF->write_base and BUF->write_ptr). >> + >> + If the number is larger than INT_MAX, returns -1 and sets errno to >> + EOVERFLOW. This function does not flush the buffer. If the caller >> + needs the side effect of flushing, it has to do this >> + separately. */ >> +int __printf_buffer_done (struct __printf_buffer *buf) attribute_hidden; > > Wouldn't ssize_t work better for return type? No, it's really for use in printf etc., and those return int (incorrectly, too late to fix now), so we have to check against INT_MAX. >> +int >> +Xprintf_buffer_done (struct Xprintf_buffer *buf) >> +{ >> + if (Xprintf_buffer_has_failed (buf)) >> + return -1; >> + >> + /* Use uintptr_t here because for sprintf, the buffer range may >> + cover more than half of the address space. */ >> + uintptr_t written_current = buf->write_ptr - buf->write_base; > > Is this really a valid case? Working with buffer ranges larger than half > of address space is not valid for malloc buffer anyway, are you handling > some iffy case for mmap case? It's not really supported, but I wanted to mention it. >> +void >> +Xprintf (buffer_puts_1) (struct Xprintf_buffer *buf, const CHAR_T *s) >> +{ >> + if (__glibc_unlikely (Xprintf_buffer_has_failed (buf))) >> + return; >> + >> + while (*s != 0) > > Maybe use NULL here? No, *s is CHAR_T. >> +static const struct _IO_jump_t _IO_printf_buffer_as_file_jumps libio_vtable = >> +{ >> + JUMP_INIT_DUMMY, >> + JUMP_INIT(finish, NULL), >> + JUMP_INIT(overflow, __printf_buffer_as_file_overflow), >> + JUMP_INIT(underflow, NULL), >> + JUMP_INIT(uflow, NULL), >> + JUMP_INIT(pbackfail, NULL), >> + JUMP_INIT(xsputn, __printf_buffer_as_file_xsputn), >> + JUMP_INIT(xsgetn, NULL), >> + JUMP_INIT(seekoff, NULL), >> + JUMP_INIT(seekpos, NULL), >> + JUMP_INIT(setbuf, NULL), >> + JUMP_INIT(sync, NULL), >> + JUMP_INIT(doallocate, NULL), >> + JUMP_INIT(read, NULL), >> + JUMP_INIT(write, NULL), >> + JUMP_INIT(seek, NULL), >> + JUMP_INIT(close, NULL), >> + JUMP_INIT(stat, NULL), >> + JUMP_INIT(showmanyc, NULL), >> + JUMP_INIT(imbue, NULL) >> +}; > > The _IO_printf_buffer_as_file_jumps should be added on > tst-relro-symbols.py required list. Done. >> diff --git a/stdio-common/printf_buffer_to_file.h b/stdio-common/printf_buffer_to_file.h >> new file mode 100644 >> index 0000000000..97ec1d6d95 >> --- /dev/null >> +++ b/stdio-common/printf_buffer_to_file.h >> @@ -0,0 +1,57 @@ >> +/* Multibyte and wide printf buffers writing data to a FILE * stream. >> + Copyright (C) 2022 Free Software Foundation, Inc. >> + This file is part of the GNU C Library. >> + >> + The GNU C Library is free software; you can redistribute it and/or >> + modify it under the terms of the GNU Lesser General Public >> + License as published by the Free Software Foundation; either >> + version 2.1 of the License, or (at your option) any later version. >> + >> + The GNU C Library is distributed in the hope that it will be useful, >> + but WITHOUT ANY WARRANTY; without even the implied warranty of >> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> + Lesser General Public License for more details. >> + >> + You should have received a copy of the GNU Lesser General Public >> + License along with the GNU C Library; if not, see >> + . */ >> + >> +#ifndef PRINTF_BUFFER_TO_FILE_H >> +#define PRINTF_BUFFER_TO_FILE_H >> + >> +#include >> +#include >> + >> +struct __printf_buffer_to_file >> +{ >> + struct __printf_buffer base; >> + FILE *fp; >> + >> + /* Staging buffer. All data goes through this buffer before >> + reaching the fp stream. (Any buffer in fp is not yet used.) */ >> + char stage[128]; >> +}; > > Out of curiosity, why 128? Few lines are longer than 128, and this path is used for line-buffered streams (among others). >> +static const struct _IO_jump_t _IO_wprintf_buffer_as_file_jumps libio_vtable = >> +{ >> + JUMP_INIT_DUMMY, >> + JUMP_INIT(finish, NULL), >> + JUMP_INIT(overflow, (_IO_overflow_t) __wprintf_buffer_as_file_overflow), >> + JUMP_INIT(underflow, NULL), >> + JUMP_INIT(uflow, NULL), >> + JUMP_INIT(pbackfail, NULL), >> + JUMP_INIT(xsputn, __wprintf_buffer_as_file_xsputn), >> + JUMP_INIT(xsgetn, NULL), >> + JUMP_INIT(seekoff, NULL), >> + JUMP_INIT(seekpos, NULL), >> + JUMP_INIT(setbuf, NULL), >> + JUMP_INIT(sync, NULL), >> + JUMP_INIT(doallocate, NULL), >> + JUMP_INIT(read, NULL), >> + JUMP_INIT(write, NULL), >> + JUMP_INIT(seek, NULL), >> + JUMP_INIT(close, NULL), >> + JUMP_INIT(stat, NULL), >> + JUMP_INIT(showmanyc, NULL), >> + JUMP_INIT(imbue, NULL) >> +}; >> + > > As for _IO_printf_buffer_as_file_jumps, > _IO_wprintf_buffer_as_file_jumps also should be added on > tst-relro-symbols.py required list. Done. Thanks, Florian