Bug Summary

File:root/firefox-clang/third_party/aom/aom_dsp/grain_table.c
Warning:line 145, column 11
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name grain_table.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/libaom -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libaom -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D MOZ_HAS_MOZGLUE -I /root/firefox-clang/media/libaom -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libaom -I /root/firefox-clang/media/libaom/config/linux/x64 -I /root/firefox-clang/media/libaom/config -I /root/firefox-clang/third_party/aom -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-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -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-sign-compare -Wno-unused-function -Wno-unreachable-code -Wno-unneeded-internal-declaration -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 -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-27-100320-3286336-1 -x c /root/firefox-clang/third_party/aom/aom_dsp/grain_table.c
1/*
2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3 *
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 */
11
12/*!\file
13 * \brief This file has the implementation details of the grain table.
14 *
15 * The file format is an ascii representation for readability and
16 * editability. Array parameters are separated from the non-array
17 * parameters and prefixed with a few characters to make for easy
18 * localization with a parameter set. Each entry is prefixed with "E"
19 * and the other parameters are only specified if "update-parms" is
20 * non-zero.
21 *
22 * filmgrn1
23 * E <start-time> <end-time> <apply-grain> <random-seed> <update-parms>
24 * p <ar_coeff_lag> <ar_coeff_shift> <grain_scale_shift> ...
25 * sY <num_y_points> <point_0_x> <point_0_y> ...
26 * sCb <num_cb_points> <point_0_x> <point_0_y> ...
27 * sCr <num_cr_points> <point_0_x> <point_0_y> ...
28 * cY <ar_coeff_y_0> ....
29 * cCb <ar_coeff_cb_0> ....
30 * cCr <ar_coeff_cr_0> ....
31 * E <start-time> ...
32 */
33#include <string.h>
34#include <stdio.h>
35#include "aom_dsp/aom_dsp_common.h"
36#include "aom_dsp/grain_table.h"
37#include "aom_mem/aom_mem.h"
38
39static const char kFileMagic[8] = { 'f', 'i', 'l', 'm', 'g', 'r', 'n', '1' };
40
41static void grain_table_entry_read(FILE *file,
42 struct aom_internal_error_info *error_info,
43 aom_film_grain_table_entry_t *entry) {
44 aom_film_grain_t *pars = &entry->params;
45 int num_read =
46 fscanf(file, "E %" PRId64"l" "d" " %" PRId64"l" "d" " %d %hd %d\n", &entry->start_time,
47 &entry->end_time, &pars->apply_grain, &pars->random_seed,
48 &pars->update_parameters);
49 if (num_read == 0 && feof(file)) return;
8
Assuming 'num_read' is not equal to 0
50 if (num_read != 5) {
9
Assuming 'num_read' is equal to 5
10
Taking false branch
51 aom_internal_error(error_info, AOM_CODEC_ERROR,
52 "Unable to read entry header. Read %d != 5", num_read);
53 return;
54 }
55 if (pars->update_parameters) {
11
Assuming field 'update_parameters' is not equal to 0
12
Taking true branch
56 num_read = fscanf(file, "p %d %d %d %d %d %d %d %d %d %d %d %d\n",
57 &pars->ar_coeff_lag, &pars->ar_coeff_shift,
58 &pars->grain_scale_shift, &pars->scaling_shift,
59 &pars->chroma_scaling_from_luma, &pars->overlap_flag,
60 &pars->cb_mult, &pars->cb_luma_mult, &pars->cb_offset,
61 &pars->cr_mult, &pars->cr_luma_mult, &pars->cr_offset);
62 if (num_read != 12) {
13
Assuming 'num_read' is equal to 12
14
Taking false branch
63 aom_internal_error(error_info, AOM_CODEC_ERROR,
64 "Unable to read entry params. Read %d != 12",
65 num_read);
66 return;
67 }
68 if (!fscanf(file, "\tsY %d ", &pars->num_y_points)) {
15
Assuming this stream operation fails
16
Taking false branch
69 aom_internal_error(error_info, AOM_CODEC_ERROR,
70 "Unable to read num y points");
71 return;
72 }
73 for (int i = 0; i < pars->num_y_points; ++i) {
17
Assuming 'i' is >= field 'num_y_points'
18
Loop condition is false. Execution continues on line 81
74 if (2 != fscanf(file, "%d %d", &pars->scaling_points_y[i][0],
75 &pars->scaling_points_y[i][1])) {
76 aom_internal_error(error_info, AOM_CODEC_ERROR,
77 "Unable to read y scaling points");
78 return;
79 }
80 }
81 if (!fscanf(file, "\n\tsCb %d", &pars->num_cb_points)) {
19
Taking false branch
82 aom_internal_error(error_info, AOM_CODEC_ERROR,
83 "Unable to read num cb points");
84 return;
85 }
86 for (int i = 0; i < pars->num_cb_points; ++i) {
20
Assuming 'i' is >= field 'num_cb_points'
21
Loop condition is false. Execution continues on line 94
87 if (2 != fscanf(file, "%d %d", &pars->scaling_points_cb[i][0],
88 &pars->scaling_points_cb[i][1])) {
89 aom_internal_error(error_info, AOM_CODEC_ERROR,
90 "Unable to read cb scaling points");
91 return;
92 }
93 }
94 if (!fscanf(file, "\n\tsCr %d", &pars->num_cr_points)) {
22
Taking false branch
95 aom_internal_error(error_info, AOM_CODEC_ERROR,
96 "Unable to read num cr points");
97 return;
98 }
99 for (int i = 0; i < pars->num_cr_points; ++i) {
23
Assuming 'i' is >= field 'num_cr_points'
24
Loop condition is false. Execution continues on line 108
100 if (2 != fscanf(file, "%d %d", &pars->scaling_points_cr[i][0],
101 &pars->scaling_points_cr[i][1])) {
102 aom_internal_error(error_info, AOM_CODEC_ERROR,
103 "Unable to read cr scaling points");
104 return;
105 }
106 }
107
108 if (fscanf(file, "\n\tcY")) {
25
Assuming the condition is false
26
Taking false branch
109 aom_internal_error(error_info, AOM_CODEC_ERROR,
110 "Unable to read Y coeffs header (cY)");
111 return;
112 }
113 const int n = 2 * pars->ar_coeff_lag * (pars->ar_coeff_lag + 1);
114 for (int i = 0; i < n; ++i) {
27
Assuming 'i' is >= 'n'
28
Loop condition is false. Execution continues on line 121
115 if (1 != fscanf(file, "%d", &pars->ar_coeffs_y[i])) {
116 aom_internal_error(error_info, AOM_CODEC_ERROR,
117 "Unable to read Y coeffs");
118 return;
119 }
120 }
121 if (fscanf(file, "\n\tcCb")) {
29
Assuming the condition is false
30
Taking false branch
122 aom_internal_error(error_info, AOM_CODEC_ERROR,
123 "Unable to read Cb coeffs header (cCb)");
124 return;
125 }
126 for (int i = 0; i <= n; ++i) {
31
Assuming 'i' is > 'n'
32
Loop condition is false. Execution continues on line 133
127 if (1 != fscanf(file, "%d", &pars->ar_coeffs_cb[i])) {
128 aom_internal_error(error_info, AOM_CODEC_ERROR,
129 "Unable to read Cb coeffs");
130 return;
131 }
132 }
133 if (fscanf(file, "\n\tcCr")) {
33
Assuming the condition is false
34
Taking false branch
134 aom_internal_error(error_info, AOM_CODEC_ERROR,
135 "Unable read to Cr coeffs header (cCr)");
136 return;
137 }
138 for (int i = 0; i
34.1
'i' is > 'n'
<= n; ++i) {
35
Loop condition is false. Execution continues on line 145
139 if (1 != fscanf(file, "%d", &pars->ar_coeffs_cr[i])) {
140 aom_internal_error(error_info, AOM_CODEC_ERROR,
141 "Unable to read Cr coeffs");
142 return;
143 }
144 }
145 (void)fscanf(file, "\n");
36
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior
146 }
147}
148
149static void grain_table_entry_write(FILE *file,
150 aom_film_grain_table_entry_t *entry) {
151 const aom_film_grain_t *pars = &entry->params;
152 fprintf(file, "E %" PRId64"l" "d" " %" PRId64"l" "d" " %d %d %d\n", entry->start_time,
153 entry->end_time, pars->apply_grain, pars->random_seed,
154 pars->update_parameters);
155 if (pars->update_parameters) {
156 fprintf(file, "\tp %d %d %d %d %d %d %d %d %d %d %d %d\n",
157 pars->ar_coeff_lag, pars->ar_coeff_shift, pars->grain_scale_shift,
158 pars->scaling_shift, pars->chroma_scaling_from_luma,
159 pars->overlap_flag, pars->cb_mult, pars->cb_luma_mult,
160 pars->cb_offset, pars->cr_mult, pars->cr_luma_mult,
161 pars->cr_offset);
162 fprintf(file, "\tsY %d ", pars->num_y_points);
163 for (int i = 0; i < pars->num_y_points; ++i) {
164 fprintf(file, " %d %d", pars->scaling_points_y[i][0],
165 pars->scaling_points_y[i][1]);
166 }
167 fprintf(file, "\n\tsCb %d", pars->num_cb_points);
168 for (int i = 0; i < pars->num_cb_points; ++i) {
169 fprintf(file, " %d %d", pars->scaling_points_cb[i][0],
170 pars->scaling_points_cb[i][1]);
171 }
172 fprintf(file, "\n\tsCr %d", pars->num_cr_points);
173 for (int i = 0; i < pars->num_cr_points; ++i) {
174 fprintf(file, " %d %d", pars->scaling_points_cr[i][0],
175 pars->scaling_points_cr[i][1]);
176 }
177 fprintf(file, "\n\tcY");
178 const int n = 2 * pars->ar_coeff_lag * (pars->ar_coeff_lag + 1);
179 for (int i = 0; i < n; ++i) {
180 fprintf(file, " %d", pars->ar_coeffs_y[i]);
181 }
182 fprintf(file, "\n\tcCb");
183 for (int i = 0; i <= n; ++i) {
184 fprintf(file, " %d", pars->ar_coeffs_cb[i]);
185 }
186 fprintf(file, "\n\tcCr");
187 for (int i = 0; i <= n; ++i) {
188 fprintf(file, " %d", pars->ar_coeffs_cr[i]);
189 }
190 fprintf(file, "\n");
191 }
192}
193
194// TODO(https://crbug.com/aomedia/3228): Update this function to return an
195// integer status.
196void aom_film_grain_table_append(aom_film_grain_table_t *t, int64_t time_stamp,
197 int64_t end_time,
198 const aom_film_grain_t *grain) {
199 if (!t->tail || memcmp(grain, &t->tail->params, sizeof(*grain))) {
200 aom_film_grain_table_entry_t *new_tail = aom_malloc(sizeof(*new_tail));
201 if (!new_tail) return;
202 memset(new_tail, 0, sizeof(*new_tail));
203 if (t->tail) t->tail->next = new_tail;
204 if (!t->head) t->head = new_tail;
205 t->tail = new_tail;
206
207 new_tail->start_time = time_stamp;
208 new_tail->end_time = end_time;
209 new_tail->params = *grain;
210 } else {
211 t->tail->end_time = AOMMAX(t->tail->end_time, end_time)(((t->tail->end_time) > (end_time)) ? (t->tail->
end_time) : (end_time))
;
212 t->tail->start_time = AOMMIN(t->tail->start_time, time_stamp)(((t->tail->start_time) < (time_stamp)) ? (t->tail
->start_time) : (time_stamp))
;
213 }
214}
215
216int aom_film_grain_table_lookup(aom_film_grain_table_t *t, int64_t time_stamp,
217 int64_t end_time, int erase,
218 aom_film_grain_t *grain) {
219 aom_film_grain_table_entry_t *entry = t->head;
220 aom_film_grain_table_entry_t *prev_entry = NULL((void*)0);
221 uint16_t random_seed = grain ? grain->random_seed : 0;
222 if (grain) memset(grain, 0, sizeof(*grain));
223
224 while (entry) {
225 aom_film_grain_table_entry_t *next = entry->next;
226 if (time_stamp >= entry->start_time && time_stamp < entry->end_time) {
227 if (grain) {
228 *grain = entry->params;
229 if (time_stamp != 0) grain->random_seed = random_seed;
230 }
231 if (!erase) return 1;
232
233 const int64_t entry_end_time = entry->end_time;
234 if (time_stamp <= entry->start_time && end_time >= entry->end_time) {
235 if (t->tail == entry) t->tail = prev_entry;
236 if (prev_entry) {
237 prev_entry->next = entry->next;
238 } else {
239 t->head = entry->next;
240 }
241 aom_free(entry);
242 } else if (time_stamp <= entry->start_time &&
243 end_time < entry->end_time) {
244 entry->start_time = end_time;
245 } else if (time_stamp > entry->start_time &&
246 end_time >= entry->end_time) {
247 entry->end_time = time_stamp;
248 } else {
249 aom_film_grain_table_entry_t *new_entry =
250 aom_malloc(sizeof(*new_entry));
251 if (!new_entry) return 0;
252 new_entry->next = entry->next;
253 new_entry->start_time = end_time;
254 new_entry->end_time = entry->end_time;
255 new_entry->params = entry->params;
256 entry->next = new_entry;
257 entry->end_time = time_stamp;
258 if (t->tail == entry) t->tail = new_entry;
259 }
260 // If segments aren't aligned, delete from the beginning of subsequent
261 // segments
262 if (end_time > entry_end_time) {
263 // Ignoring the return value here is safe since we're erasing from the
264 // beginning of subsequent entries.
265 aom_film_grain_table_lookup(t, entry_end_time, end_time, /*erase=*/1,
266 NULL((void*)0));
267 }
268 return 1;
269 }
270 prev_entry = entry;
271 entry = next;
272 }
273 return 0;
274}
275
276aom_codec_err_t aom_film_grain_table_read(
277 aom_film_grain_table_t *t, const char *filename,
278 struct aom_internal_error_info *error_info) {
279 FILE *file = fopen(filename, "rb");
280 if (!file
0.1
'file' is non-null
) {
1
Taking false branch
281 aom_internal_error(error_info, AOM_CODEC_ERROR, "Unable to open %s",
282 filename);
283 return error_info->error_code;
284 }
285 error_info->error_code = AOM_CODEC_OK;
286
287 // Read in one extra character as there should be white space after
288 // the header.
289 char magic[9];
290 if (!fread(magic, 9, 1, file) || memcmp(magic, kFileMagic, 8)) {
2
Assuming the condition is false
3
Taking false branch
291 aom_internal_error(error_info, AOM_CODEC_ERROR,
292 "Unable to read (or invalid) file magic");
293 fclose(file);
294 return error_info->error_code;
295 }
296
297 aom_film_grain_table_entry_t *prev_entry = NULL((void*)0);
298 while (!feof(file)) {
4
Loop condition is true. Entering loop body
299 aom_film_grain_table_entry_t *entry = aom_malloc(sizeof(*entry));
300 if (!entry) {
5
Assuming 'entry' is non-null
6
Taking false branch
301 aom_internal_error(error_info, AOM_CODEC_MEM_ERROR,
302 "Unable to allocate grain table entry");
303 break;
304 }
305 memset(entry, 0, sizeof(*entry));
306 grain_table_entry_read(file, error_info, entry);
7
Calling 'grain_table_entry_read'
307 entry->next = NULL((void*)0);
308
309 if (prev_entry) prev_entry->next = entry;
310 if (!t->head) t->head = entry;
311 t->tail = entry;
312 prev_entry = entry;
313
314 if (error_info->error_code != AOM_CODEC_OK) break;
315 }
316
317 fclose(file);
318 return error_info->error_code;
319}
320
321aom_codec_err_t aom_film_grain_table_write(
322 const aom_film_grain_table_t *t, const char *filename,
323 struct aom_internal_error_info *error_info) {
324 error_info->error_code = AOM_CODEC_OK;
325
326 FILE *file = fopen(filename, "wb");
327 if (!file) {
328 aom_internal_error(error_info, AOM_CODEC_ERROR, "Unable to open file %s",
329 filename);
330 return error_info->error_code;
331 }
332
333 if (!fwrite(kFileMagic, 8, 1, file)) {
334 aom_internal_error(error_info, AOM_CODEC_ERROR,
335 "Unable to write file magic");
336 fclose(file);
337 return error_info->error_code;
338 }
339
340 fprintf(file, "\n");
341 aom_film_grain_table_entry_t *entry = t->head;
342 while (entry) {
343 grain_table_entry_write(file, entry);
344 entry = entry->next;
345 }
346 fclose(file);
347 return error_info->error_code;
348}
349
350void aom_film_grain_table_free(aom_film_grain_table_t *t) {
351 aom_film_grain_table_entry_t *entry = t->head;
352 while (entry) {
353 aom_film_grain_table_entry_t *next = entry->next;
354 aom_free(entry);
355 entry = next;
356 }
357 memset(t, 0, sizeof(*t));
358}