Bug Summary

File:root/firefox-clang/media/libjpeg/src/jdatadst.c
Warning:line 134, column 3
Null pointer passed to 1st parameter expecting 'nonnull'

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 jdatadst.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/libjpeg -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libjpeg -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_WITH_SIMD=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/media/libjpeg -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libjpeg -I /root/firefox-clang/media/libjpeg -I /root/firefox-clang/media/libjpeg/src -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 -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/libjpeg/src/jdatadst.c
1/*
2 * jdatadst.c
3 *
4 * This file was part of the Independent JPEG Group's software:
5 * Copyright (C) 1994-1996, Thomas G. Lane.
6 * Modified 2009-2012 by Guido Vollbeding.
7 * libjpeg-turbo Modifications:
8 * Copyright (C) 2013, 2016, 2022, D. R. Commander.
9 * For conditions of distribution and use, see the accompanying README.ijg
10 * file.
11 *
12 * This file contains compression data destination routines for the case of
13 * emitting JPEG data to memory or to a file (or any stdio stream).
14 * While these routines are sufficient for most applications,
15 * some will want to use a different destination manager.
16 * IMPORTANT: we assume that fwrite() will correctly transcribe an array of
17 * JOCTETs into 8-bit-wide elements on external storage. If char is wider
18 * than 8 bits on your machine, you may need to do some tweaking.
19 */
20
21/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
22#include "jinclude.h"
23#include "jpeglib.h"
24#include "jerror.h"
25
26
27/* Expanded data destination object for stdio output */
28
29typedef struct {
30 struct jpeg_destination_mgr pub; /* public fields */
31
32 FILE *outfile; /* target stream */
33 JOCTET *buffer; /* start of buffer */
34} my_destination_mgr;
35
36typedef my_destination_mgr *my_dest_ptr;
37
38#define OUTPUT_BUF_SIZE4096 4096 /* choose an efficiently fwrite'able size */
39
40
41/* Expanded data destination object for memory output */
42
43typedef struct {
44 struct jpeg_destination_mgr pub; /* public fields */
45
46 unsigned char **outbuffer; /* target buffer */
47 unsigned long *outsize;
48 unsigned char *newbuffer; /* newly allocated buffer */
49 JOCTET *buffer; /* start of buffer */
50 size_t bufsize;
51} my_mem_destination_mgr;
52
53typedef my_mem_destination_mgr *my_mem_dest_ptr;
54
55
56/*
57 * Initialize destination --- called by jpeg_start_compress
58 * before any data is actually written.
59 */
60
61METHODDEF(void)static void
62init_destination(j_compress_ptr cinfo)
63{
64 my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
65
66 /* Allocate the output buffer --- it will be released when done with image */
67 dest->buffer = (JOCTET *)
68 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE1,
69 OUTPUT_BUF_SIZE4096 * sizeof(JOCTET));
70
71 dest->pub.next_output_byte = dest->buffer;
72 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE4096;
73}
74
75METHODDEF(void)static void
76init_mem_destination(j_compress_ptr cinfo)
77{
78 /* no work necessary here */
79}
80
81
82/*
83 * Empty the output buffer --- called whenever buffer fills up.
84 *
85 * In typical applications, this should write the entire output buffer
86 * (ignoring the current state of next_output_byte & free_in_buffer),
87 * reset the pointer & count to the start of the buffer, and return TRUE
88 * indicating that the buffer has been dumped.
89 *
90 * In applications that need to be able to suspend compression due to output
91 * overrun, a FALSE return indicates that the buffer cannot be emptied now.
92 * In this situation, the compressor will return to its caller (possibly with
93 * an indication that it has not accepted all the supplied scanlines). The
94 * application should resume compression after it has made more room in the
95 * output buffer. Note that there are substantial restrictions on the use of
96 * suspension --- see the documentation.
97 *
98 * When suspending, the compressor will back up to a convenient restart point
99 * (typically the start of the current MCU). next_output_byte & free_in_buffer
100 * indicate where the restart point will be if the current call returns FALSE.
101 * Data beyond this point will be regenerated after resumption, so do not
102 * write it out when emptying the buffer externally.
103 */
104
105METHODDEF(boolean)static boolean
106empty_output_buffer(j_compress_ptr cinfo)
107{
108 my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
109
110 if (fwrite(dest->buffer, 1, OUTPUT_BUF_SIZE4096, dest->outfile) !=
111 (size_t)OUTPUT_BUF_SIZE4096)
112 ERREXIT(cinfo, JERR_FILE_WRITE)((cinfo)->err->msg_code = (JERR_FILE_WRITE), (*(cinfo)->
err->error_exit) ((j_common_ptr)(cinfo)))
;
113
114 dest->pub.next_output_byte = dest->buffer;
115 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE4096;
116
117 return TRUE1;
118}
119
120METHODDEF(boolean)static boolean
121empty_mem_output_buffer(j_compress_ptr cinfo)
122{
123 size_t nextsize;
124 JOCTET *nextbuffer;
125 my_mem_dest_ptr dest = (my_mem_dest_ptr)cinfo->dest;
126
127 /* Try to allocate new buffer with double size */
128 nextsize = dest->bufsize * 2;
129 nextbuffer = (JOCTET *)malloc(nextsize);
1
Value assigned to 'nextbuffer'
130
131 if (nextbuffer == NULL((void*)0))
2
Assuming 'nextbuffer' is equal to NULL
3
Taking true branch
132 ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10)((cinfo)->err->msg_code = (JERR_OUT_OF_MEMORY), (cinfo)
->err->msg_parm.i[0] = (10), (*(cinfo)->err->error_exit
) ((j_common_ptr)(cinfo)))
;
133
134 memcpy(nextbuffer, dest->buffer, dest->bufsize);
4
Null pointer passed to 1st parameter expecting 'nonnull'
135
136 free(dest->newbuffer);
137
138 dest->newbuffer = nextbuffer;
139
140 dest->pub.next_output_byte = nextbuffer + dest->bufsize;
141 dest->pub.free_in_buffer = dest->bufsize;
142
143 dest->buffer = nextbuffer;
144 dest->bufsize = nextsize;
145
146 return TRUE1;
147}
148
149
150/*
151 * Terminate destination --- called by jpeg_finish_compress
152 * after all data has been written. Usually needs to flush buffer.
153 *
154 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
155 * application must deal with any cleanup that should happen even
156 * for error exit.
157 */
158
159METHODDEF(void)static void
160term_destination(j_compress_ptr cinfo)
161{
162 my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
163 size_t datacount = OUTPUT_BUF_SIZE4096 - dest->pub.free_in_buffer;
164
165 /* Write any data remaining in the buffer */
166 if (datacount > 0) {
167 if (fwrite(dest->buffer, 1, datacount, dest->outfile) != datacount)
168 ERREXIT(cinfo, JERR_FILE_WRITE)((cinfo)->err->msg_code = (JERR_FILE_WRITE), (*(cinfo)->
err->error_exit) ((j_common_ptr)(cinfo)))
;
169 }
170 fflush(dest->outfile);
171 /* Make sure we wrote the output file OK */
172 if (ferror(dest->outfile))
173 ERREXIT(cinfo, JERR_FILE_WRITE)((cinfo)->err->msg_code = (JERR_FILE_WRITE), (*(cinfo)->
err->error_exit) ((j_common_ptr)(cinfo)))
;
174}
175
176METHODDEF(void)static void
177term_mem_destination(j_compress_ptr cinfo)
178{
179 my_mem_dest_ptr dest = (my_mem_dest_ptr)cinfo->dest;
180
181 *dest->outbuffer = dest->buffer;
182 *dest->outsize = (unsigned long)(dest->bufsize - dest->pub.free_in_buffer);
183}
184
185
186/*
187 * Prepare for output to a stdio stream.
188 * The caller must have already opened the stream, and is responsible
189 * for closing it after finishing compression.
190 */
191
192GLOBAL(void)void
193jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile)
194{
195 my_dest_ptr dest;
196
197 /* The destination object is made permanent so that multiple JPEG images
198 * can be written to the same file without re-executing jpeg_stdio_dest.
199 */
200 if (cinfo->dest == NULL((void*)0)) { /* first time for this JPEG object? */
201 cinfo->dest = (struct jpeg_destination_mgr *)
202 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT0,
203 sizeof(my_destination_mgr));
204 } else if (cinfo->dest->init_destination != init_destination) {
205 /* It is unsafe to reuse the existing destination manager unless it was
206 * created by this function. Otherwise, there is no guarantee that the
207 * opaque structure is the right size. Note that we could just create a
208 * new structure, but the old structure would not be freed until
209 * jpeg_destroy_compress() was called.
210 */
211 ERREXIT(cinfo, JERR_BUFFER_SIZE)((cinfo)->err->msg_code = (JERR_BUFFER_SIZE), (*(cinfo)
->err->error_exit) ((j_common_ptr)(cinfo)))
;
212 }
213
214 dest = (my_dest_ptr)cinfo->dest;
215 dest->pub.init_destination = init_destination;
216 dest->pub.empty_output_buffer = empty_output_buffer;
217 dest->pub.term_destination = term_destination;
218 dest->outfile = outfile;
219}
220
221
222/*
223 * Prepare for output to a memory buffer.
224 * The caller may supply an own initial buffer with appropriate size.
225 * Otherwise, or when the actual data output exceeds the given size,
226 * the library adapts the buffer size as necessary.
227 * The standard library functions malloc/free are used for allocating
228 * larger memory, so the buffer is available to the application after
229 * finishing compression, and then the application is responsible for
230 * freeing the requested memory.
231 * Note: An initial buffer supplied by the caller is expected to be
232 * managed by the application. The library does not free such buffer
233 * when allocating a larger buffer.
234 */
235
236GLOBAL(void)void
237jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer,
238 unsigned long *outsize)
239{
240 my_mem_dest_ptr dest;
241
242 if (outbuffer == NULL((void*)0) || outsize == NULL((void*)0)) /* sanity check */
243 ERREXIT(cinfo, JERR_BUFFER_SIZE)((cinfo)->err->msg_code = (JERR_BUFFER_SIZE), (*(cinfo)
->err->error_exit) ((j_common_ptr)(cinfo)))
;
244
245 /* The destination object is made permanent so that multiple JPEG images
246 * can be written to the same buffer without re-executing jpeg_mem_dest.
247 */
248 if (cinfo->dest == NULL((void*)0)) { /* first time for this JPEG object? */
249 cinfo->dest = (struct jpeg_destination_mgr *)
250 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT0,
251 sizeof(my_mem_destination_mgr));
252 } else if (cinfo->dest->init_destination != init_mem_destination) {
253 /* It is unsafe to reuse the existing destination manager unless it was
254 * created by this function.
255 */
256 ERREXIT(cinfo, JERR_BUFFER_SIZE)((cinfo)->err->msg_code = (JERR_BUFFER_SIZE), (*(cinfo)
->err->error_exit) ((j_common_ptr)(cinfo)))
;
257 }
258
259 dest = (my_mem_dest_ptr)cinfo->dest;
260 dest->pub.init_destination = init_mem_destination;
261 dest->pub.empty_output_buffer = empty_mem_output_buffer;
262 dest->pub.term_destination = term_mem_destination;
263 dest->outbuffer = outbuffer;
264 dest->outsize = outsize;
265 dest->newbuffer = NULL((void*)0);
266
267 if (*outbuffer == NULL((void*)0) || *outsize == 0) {
268 /* Allocate initial buffer */
269 dest->newbuffer = *outbuffer = (unsigned char *)malloc(OUTPUT_BUF_SIZE4096);
270 if (dest->newbuffer == NULL((void*)0))
271 ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10)((cinfo)->err->msg_code = (JERR_OUT_OF_MEMORY), (cinfo)
->err->msg_parm.i[0] = (10), (*(cinfo)->err->error_exit
) ((j_common_ptr)(cinfo)))
;
272 *outsize = OUTPUT_BUF_SIZE4096;
273 }
274
275 dest->pub.next_output_byte = dest->buffer = *outbuffer;
276 dest->pub.free_in_buffer = dest->bufsize = *outsize;
277}