Document CVE-2024-2961
[glibc.git] / libio / obprintf.c
blob491d14fbaec0a577bac25480308aec65e0123670
1 /* Print output of stream to given obstack.
2 Copyright (C) 1996-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <assert.h>
20 #include <math_ldbl_opt.h>
21 #include <obstack.h>
22 #include <printf.h>
23 #include <stdarg.h>
24 #include <printf_buffer.h>
26 struct __printf_buffer_obstack
28 struct __printf_buffer base;
29 struct obstack *obstack;
31 /* obstack_1grow is called for compatibility reasons. This needs
32 one extra character, and this is the backing store for it. */
33 char ch;
36 void
37 __printf_buffer_flush_obstack (struct __printf_buffer_obstack *buf)
39 /* About to switch buffers, so record the bytes written so far. */
40 buf->base.written += buf->base.write_ptr - buf->base.write_base;
42 if (buf->base.write_ptr == &buf->ch + 1)
44 /* Errors are reported via a callback mechanism (presumably for
45 process termination). */
46 obstack_1grow (buf->obstack, buf->ch);
47 buf->base.write_base = obstack_next_free (buf->obstack);
48 buf->base.write_ptr = buf->base.write_base;
49 size_t size = obstack_room (buf->obstack);
50 buf->base.write_end = buf->base.write_ptr + size;
51 /* Reserve the space on the obstack size. */
52 obstack_blank_fast (buf->obstack, size);
54 else
56 /* Obtain the extra character. */
57 buf->base.write_base = &buf->ch;
58 buf->base.write_ptr = &buf->ch;
59 buf->base.write_end = &buf->ch + 1;
63 int
64 __obstack_vprintf_internal (struct obstack *obstack, const char *format,
65 va_list args, unsigned int mode_flags)
67 /* Legacy setup code for compatibility. */
68 size_t room = obstack_room (obstack);
69 size_t size = obstack_object_size (obstack) + room;
70 if (size == 0)
72 /* Get more memory. */
73 obstack_make_room (obstack, 64);
75 /* Recompute how much room we have. */
76 room = obstack_room (obstack);
77 size = room;
79 assert (size != 0);
82 struct __printf_buffer_obstack buf;
84 /* The obstack write location might be in the middle of an object. */
85 char *ptr = obstack_next_free (obstack);
86 char *end = obstack_base (obstack) + size;
87 __printf_buffer_init (&buf.base, ptr, end - ptr,
88 __printf_buffer_mode_obstack);
90 buf.obstack = obstack;
92 /* Now allocate the rest of the current chunk. */
93 obstack_blank_fast (obstack, room);
95 __printf_buffer (&buf.base, format, args, mode_flags);
97 if (buf.base.write_ptr == &buf.ch + 1)
98 /* buf.ch is in use. Put it into the obstack. */
99 obstack_1grow (buf.obstack, buf.ch);
100 else if (buf.base.write_ptr != &buf.ch)
101 /* Shrink the buffer to the space we really currently need. */
102 obstack_blank_fast (buf.obstack, buf.base.write_ptr - buf.base.write_end);
104 return __printf_buffer_done (&buf.base);
108 __obstack_vprintf (struct obstack *obstack, const char *format, va_list ap)
110 return __obstack_vprintf_internal (obstack, format, ap, 0);
112 ldbl_weak_alias (__obstack_vprintf, obstack_vprintf)
115 __obstack_printf (struct obstack *obstack, const char *format, ...)
117 int result;
118 va_list ap;
119 va_start (ap, format);
120 result = __obstack_vprintf_internal (obstack, format, ap, 0);
121 va_end (ap);
122 return result;
124 ldbl_weak_alias (__obstack_printf, obstack_printf)