Bug Summary

File:root/firefox-clang/media/ffvpx/libavutil/bprint.c
Warning:line 199, column 22
Although the value stored to 'l' is used in the enclosing expression, the value is never actually read from 'l'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name bprint.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavutil -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavutil -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -include libavutil_visibility.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D HAVE_AV_CONFIG_H -D ASSERT_LEVEL=2 -I /root/firefox-clang/media/ffvpx/libavutil -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavutil -I /root/firefox-clang/third_party/khronos/vulkan-headers/include -I /root/firefox-clang/media/mozva -I /root/firefox-clang/media/ffvpx -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -Wno-parentheses -Wno-pointer-sign -Wno-sign-compare -Wno-switch -Wno-type-limits -Wno-unused-function -Wno-deprecated-declarations -Wno-absolute-value -Wno-incompatible-pointer-types -Wno-string-conversion -Wno-visibility -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c /root/firefox-clang/media/ffvpx/libavutil/bprint.c
1/*
2 * Copyright (c) 2012 Nicolas George
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <limits.h>
22#include <stdarg.h>
23#include <stdio.h>
24#include <string.h>
25#include <time.h>
26#include "avstring.h"
27#include "bprint.h"
28#include "compat/va_copy.h"
29#include "error.h"
30#include "macros.h"
31#include "mem.h"
32
33#define av_bprint_room(buf)((buf)->size - (((buf)->len) > ((buf)->size) ? ((
buf)->size) : ((buf)->len)))
((buf)->size - FFMIN((buf)->len, (buf)->size)(((buf)->len) > ((buf)->size) ? ((buf)->size) : (
(buf)->len))
)
34#define av_bprint_is_allocated(buf)((buf)->str != (buf)->reserved_internal_buffer) ((buf)->str != (buf)->reserved_internal_buffer)
35
36static int av_bprint_alloc(AVBPrint *buf, unsigned room)
37{
38 char *old_str, *new_str;
39 unsigned min_size, new_size;
40
41 if (buf->size == buf->size_max)
42 return AVERROR(EIO)(-(5));
43 if (!av_bprint_is_complete(buf))
44 return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | ((
unsigned)('A') << 24)))
; /* it is already truncated anyway */
45 min_size = buf->len + 1 + FFMIN(UINT_MAX - buf->len - 1, room)(((2147483647 *2U +1U) - buf->len - 1) > (room) ? (room
) : ((2147483647 *2U +1U) - buf->len - 1))
;
46 new_size = buf->size > buf->size_max / 2 ? buf->size_max : buf->size * 2;
47 if (new_size < min_size)
48 new_size = FFMIN(buf->size_max, min_size)((buf->size_max) > (min_size) ? (min_size) : (buf->size_max
))
;
49 old_str = av_bprint_is_allocated(buf)((buf)->str != (buf)->reserved_internal_buffer) ? buf->str : NULL((void*)0);
50 new_str = av_realloc(old_str, new_size);
51 if (!new_str)
52 return AVERROR(ENOMEM)(-(12));
53 if (!old_str)
54 memcpy(new_str, buf->str, buf->len + 1);
55 buf->str = new_str;
56 buf->size = new_size;
57 return 0;
58}
59
60static void av_bprint_grow(AVBPrint *buf, unsigned extra_len)
61{
62 /* arbitrary margin to avoid small overflows */
63 extra_len = FFMIN(extra_len, UINT_MAX - 5 - buf->len)((extra_len) > ((2147483647 *2U +1U) - 5 - buf->len) ? (
(2147483647 *2U +1U) - 5 - buf->len) : (extra_len))
;
64 buf->len += extra_len;
65 if (buf->size)
66 buf->str[FFMIN(buf->len, buf->size - 1)((buf->len) > (buf->size - 1) ? (buf->size - 1) :
(buf->len))
] = 0;
67}
68
69void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
70{
71 unsigned size_auto = (char *)buf + sizeof(*buf) -
72 buf->reserved_internal_buffer;
73
74 if (size_max == AV_BPRINT_SIZE_AUTOMATIC1)
75 size_max = size_auto;
76 buf->str = buf->reserved_internal_buffer;
77 buf->len = 0;
78 buf->size = FFMIN(size_auto, size_max)((size_auto) > (size_max) ? (size_max) : (size_auto));
79 buf->size_max = size_max;
80 *buf->str = 0;
81 if (size_init > buf->size)
82 av_bprint_alloc(buf, size_init - 1);
83}
84
85void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size)
86{
87 if (size == 0) {
88 av_bprint_init(buf, 0, AV_BPRINT_SIZE_COUNT_ONLY0);
89 return;
90 }
91
92 buf->str = buffer;
93 buf->len = 0;
94 buf->size = size;
95 buf->size_max = size;
96 *buf->str = 0;
97}
98
99void av_vbprintf(AVBPrint *buf, const char *fmt, va_list vl_arg)
100{
101 unsigned room;
102 char *dst;
103 int extra_len;
104 va_list vl;
105
106 while (1) {
107 room = av_bprint_room(buf)((buf)->size - (((buf)->len) > ((buf)->size) ? ((
buf)->size) : ((buf)->len)))
;
108 dst = room ? buf->str + buf->len : NULL((void*)0);
109 va_copy(vl, vl_arg)__builtin_va_copy(vl, vl_arg);
110 extra_len = vsnprintf(dst, room, fmt, vl);
111 va_end(vl)__builtin_va_end(vl);
112 if (extra_len <= 0)
113 return;
114 if (extra_len < room)
115 break;
116 if (av_bprint_alloc(buf, extra_len))
117 break;
118 }
119 av_bprint_grow(buf, extra_len);
120}
121
122void av_bprintf(AVBPrint *buf, const char *fmt, ...)
123{
124 va_list vl;
125 va_start(vl, fmt)__builtin_va_start(vl, fmt);
126 av_vbprintf(buf, fmt, vl);
127 va_end(vl)__builtin_va_end(vl);
128}
129
130void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
131{
132 unsigned room, real_n;
133
134 while (1) {
135 room = av_bprint_room(buf)((buf)->size - (((buf)->len) > ((buf)->size) ? ((
buf)->size) : ((buf)->len)))
;
136 if (n < room)
137 break;
138 if (av_bprint_alloc(buf, n))
139 break;
140 }
141 if (room) {
142 real_n = FFMIN(n, room - 1)((n) > (room - 1) ? (room - 1) : (n));
143 memset(buf->str + buf->len, c, real_n);
144 }
145 av_bprint_grow(buf, n);
146}
147
148void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
149{
150 unsigned room, real_n;
151
152 while (1) {
153 room = av_bprint_room(buf)((buf)->size - (((buf)->len) > ((buf)->size) ? ((
buf)->size) : ((buf)->len)))
;
154 if (size < room)
155 break;
156 if (av_bprint_alloc(buf, size))
157 break;
158 }
159 if (room) {
160 real_n = FFMIN(size, room - 1)((size) > (room - 1) ? (room - 1) : (size));
161 memcpy(buf->str + buf->len, data, real_n);
162 }
163 av_bprint_grow(buf, size);
164}
165
166void av_bprint_strftime(AVBPrint *buf, const char *fmt, const struct tm *tm)
167{
168 unsigned room;
169 size_t l;
170 size_t fmt_len = strlen(fmt);
171
172 if (!*fmt)
173 return;
174 while (1) {
175 room = av_bprint_room(buf)((buf)->size - (((buf)->len) > ((buf)->size) ? ((
buf)->size) : ((buf)->len)))
;
176 if (room && (l = strftime(buf->str + buf->len, room, fmt, tm)))
177 break;
178
179 /* Due to the limitations of strftime() it is not possible to know if
180 * the output buffer is too small or the output is empty.
181 * However, a 256x output space requirement compared to the format
182 * string length is so unlikely we can safely assume empty output. This
183 * allows supporting possibly empty format strings like "%p". */
184 if (room >> 8 > fmt_len)
185 break;
186
187 /* strftime does not tell us how much room it would need: let us
188 retry with twice as much until the buffer is large enough */
189 room = !room ? fmt_len + 1 :
190 room <= INT_MAX2147483647 / 2 ? room * 2 : INT_MAX2147483647;
191 if (av_bprint_alloc(buf, room)) {
192 /* impossible to grow, try to manage something useful anyway */
193 room = av_bprint_room(buf)((buf)->size - (((buf)->len) > ((buf)->size) ? ((
buf)->size) : ((buf)->len)))
;
194 if (room < 1024) {
195 /* if strftime fails because the buffer has (almost) reached
196 its maximum size, let us try in a local buffer; 1k should
197 be enough to format any real date+time string */
198 char buf2[1024];
199 if ((l = strftime(buf2, sizeof(buf2), fmt, tm))) {
Although the value stored to 'l' is used in the enclosing expression, the value is never actually read from 'l'
200 av_bprintf(buf, "%s", buf2);
201 return;
202 }
203 }
204 if (room) {
205 /* if anything else failed and the buffer is not already
206 truncated, let us add a stock string and force truncation */
207 static const char txt[] = "[truncated strftime output]";
208 memset(buf->str + buf->len, '!', room);
209 memcpy(buf->str + buf->len, txt, FFMIN(sizeof(txt) - 1, room)((sizeof(txt) - 1) > (room) ? (room) : (sizeof(txt) - 1)));
210 av_bprint_grow(buf, room); /* force truncation */
211 }
212 return;
213 }
214 }
215 av_bprint_grow(buf, l);
216}
217
218void av_bprint_get_buffer(AVBPrint *buf, unsigned size,
219 unsigned char **mem, unsigned *actual_size)
220{
221 if (size > av_bprint_room(buf)((buf)->size - (((buf)->len) > ((buf)->size) ? ((
buf)->size) : ((buf)->len)))
)
222 av_bprint_alloc(buf, size);
223 *actual_size = av_bprint_room(buf)((buf)->size - (((buf)->len) > ((buf)->size) ? ((
buf)->size) : ((buf)->len)))
;
224 *mem = *actual_size ? buf->str + buf->len : NULL((void*)0);
225}
226
227void av_bprint_clear(AVBPrint *buf)
228{
229 if (buf->len) {
230 *buf->str = 0;
231 buf->len = 0;
232 }
233}
234
235int av_bprint_finalize(AVBPrint *buf, char **ret_str)
236{
237 unsigned real_size = FFMIN(buf->len + 1, buf->size)((buf->len + 1) > (buf->size) ? (buf->size) : (buf
->len + 1))
;
238 char *str;
239 int ret = 0;
240
241 if (ret_str) {
242 if (av_bprint_is_allocated(buf)((buf)->str != (buf)->reserved_internal_buffer)) {
243 str = av_realloc(buf->str, real_size);
244 if (!str)
245 str = buf->str;
246 buf->str = NULL((void*)0);
247 } else {
248 str = av_memdup(buf->str, real_size);
249 if (!str)
250 ret = AVERROR(ENOMEM)(-(12));
251 }
252 *ret_str = str;
253 } else {
254 if (av_bprint_is_allocated(buf)((buf)->str != (buf)->reserved_internal_buffer))
255 av_freep(&buf->str);
256 }
257 buf->size = real_size;
258 return ret;
259}
260
261#define WHITESPACES" \n\t\r" " \n\t\r"
262
263void av_bprint_escape(AVBPrint *dstbuf, const char *src, const char *special_chars,
264 enum AVEscapeMode mode, int flags)
265{
266 const char *src0 = src;
267
268 if (mode == AV_ESCAPE_MODE_AUTO)
269 mode = AV_ESCAPE_MODE_BACKSLASH; /* TODO: implement a heuristic */
270
271 switch (mode) {
272 case AV_ESCAPE_MODE_QUOTE:
273 /* enclose the string between '' */
274 av_bprint_chars(dstbuf, '\'', 1);
275 for (; *src; src++) {
276 if (*src == '\'')
277 av_bprintf(dstbuf, "'\\''");
278 else
279 av_bprint_chars(dstbuf, *src, 1);
280 }
281 av_bprint_chars(dstbuf, '\'', 1);
282 break;
283
284 case AV_ESCAPE_MODE_XML:
285 /* escape XML non-markup character data as per 2.4 by default: */
286 /* [^<&]* - ([^<&]* ']]>' [^<&]*) */
287
288 /* additionally, given one of the AV_ESCAPE_FLAG_XML_* flags, */
289 /* escape those specific characters as required. */
290 for (; *src; src++) {
291 switch (*src) {
292 case '&' : av_bprintf(dstbuf, "%s", "&amp;"); break;
293 case '<' : av_bprintf(dstbuf, "%s", "&lt;"); break;
294 case '>' : av_bprintf(dstbuf, "%s", "&gt;"); break;
295 case '\'':
296 if (!(flags & AV_ESCAPE_FLAG_XML_SINGLE_QUOTES(1 << 2)))
297 goto XML_DEFAULT_HANDLING;
298
299 av_bprintf(dstbuf, "%s", "&apos;");
300 break;
301 case '"' :
302 if (!(flags & AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES(1 << 3)))
303 goto XML_DEFAULT_HANDLING;
304
305 av_bprintf(dstbuf, "%s", "&quot;");
306 break;
307XML_DEFAULT_HANDLING:
308 default: av_bprint_chars(dstbuf, *src, 1);
309 }
310 }
311 break;
312
313 /* case AV_ESCAPE_MODE_BACKSLASH or unknown mode */
314 default:
315 /* \-escape characters */
316 for (; *src; src++) {
317 int is_first_last = src == src0 || !*(src+1);
318 int is_ws = !!strchr(WHITESPACES" \n\t\r", *src);
319 int is_strictly_special = special_chars && strchr(special_chars, *src);
320 int is_special =
321 is_strictly_special || strchr("'\\", *src) ||
322 (is_ws && (flags & AV_ESCAPE_FLAG_WHITESPACE(1 << 0)));
323
324 if (is_strictly_special ||
325 (!(flags & AV_ESCAPE_FLAG_STRICT(1 << 1)) &&
326 (is_special || (is_ws && is_first_last))))
327 av_bprint_chars(dstbuf, '\\', 1);
328 av_bprint_chars(dstbuf, *src, 1);
329 }
330 break;
331 }
332}