Bug Summary

File:./io/_ccv_io_bmp.inc
Warning:line 13, column 10
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-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ccv_io.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 -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -menable-no-infs -menable-no-nans -fapprox-func -funsafe-math-optimizations -fno-signed-zeros -mreassociate -freciprocal-math -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -complex-range=basic -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +sse2 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/liu/actions-runner/_work/ccv/ccv/lib -fcoverage-compilation-dir=/home/liu/actions-runner/_work/ccv/ccv/lib -resource-dir /usr/local/lib/clang/19 -I . -I /usr/local/cuda/include -D HAVE_CBLAS -D HAVE_LIBPNG -D HAVE_LIBJPEG -D HAVE_FFTW3 -D HAVE_PTHREAD -D HAVE_LIBLINEAR -D HAVE_TESSERACT -D HAVE_AVCODEC -D HAVE_AVFORMAT -D HAVE_AVUTIL -D HAVE_SWSCALE -D HAVE_SSE2 -D HAVE_GSL -D HAVE_CUDA -D HAVE_CUDNN -D HAVE_NCCL -D USE_SYSTEM_CUB -I /usr/local/include -internal-isystem /usr/local/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/liu/actions-runner/_work/ccv/ccv/_analyze/2024-10-29-232120-439362-1 -x c ccv_io.c

ccv_io.c

1#include "ccv.h"
2#include "ccv_internal.h"
3#ifdef HAVE_LIBPNG1
4#ifdef __APPLE__
5#include "TargetConditionals.h"
6#if TARGET_OS_IPHONE
7// iOS
8#elif TARGET_IPHONE_SIMULATOR
9// iOS Simulator
10#elif TARGET_OS_MAC
11#include <zlib.h>
12#include <png.h>
13#else
14// Unsupported platform
15#endif
16#else
17#include <zlib.h>
18#include <png.h>
19#endif
20#include "io/_ccv_io_libpng.inc"
21#endif
22#ifdef HAVE_LIBJPEG1
23#include <jpeglib.h>
24#include "io/_ccv_io_libjpeg.inc"
25#endif
26#if defined(__unix__1) || (defined(__APPLE__) && defined(__MACH__))
27#include <sys/param.h>
28#endif
29#include "io/_ccv_io_bmp.inc"
30#include "io/_ccv_io_binary.inc"
31#include "io/_ccv_io_raw.inc"
32
33static int _ccv_read_and_close_fd(FILE* fd, ccv_dense_matrix_t** x, int type)
34{
35 int ctype = (type & 0xF00) ? CCV_8U | ((type & 0xF00) >> 8) : 0;
9
Assuming the condition is false
10
'?' condition is false
36 if ((type & 0XFF) == CCV_IO_ANY_FILE)
11
Assuming the condition is false
12
Taking false branch
37 {
38 unsigned char sig[8];
39 (void) fread(sig, 1, 8, fd);
40 if (memcmp(sig, "\x89\x50\x4e\x47\xd\xa\x1a\xa", 8) == 0)
41 type = CCV_IO_PNG_FILE;
42 else if (memcmp(sig, "\xff\xd8\xff", 3) == 0)
43 type = CCV_IO_JPEG_FILE;
44 else if (memcmp(sig, "BM", 2) == 0)
45 type = CCV_IO_BMP_FILE;
46 else if (memcmp(sig, "CCVBINDM", 8) == 0)
47 type = CCV_IO_BINARY_FILE;
48 fseek(fd, 0, SEEK_SET0);
49 }
50 switch (type & 0XFF)
13
Control jumps to 'case CCV_IO_BMP_FILE:' at line 62
51 {
52#ifdef HAVE_LIBJPEG1
53 case CCV_IO_JPEG_FILE:
54 _ccv_read_jpeg_fd(fd, x, ctype);
55 break;
56#endif
57#ifdef HAVE_LIBPNG1
58 case CCV_IO_PNG_FILE:
59 _ccv_read_png_fd(fd, x, ctype);
60 break;
61#endif
62 case CCV_IO_BMP_FILE:
63 _ccv_read_bmp_fd(fd, x, ctype);
14
Calling '_ccv_read_bmp_fd'
64 break;
65 case CCV_IO_BINARY_FILE:
66 _ccv_read_binary_fd(fd, x, ctype);
67 }
68 if (*x != 0)
69 ccv_make_matrix_immutable(*x);
70 if (type & CCV_IO_ANY_FILE)
71 fclose(fd);
72 return CCV_IO_FINAL;
73}
74
75static int _ccv_read_raw(ccv_dense_matrix_t** x, void* data, int type, int rows, int cols, int scanline)
76{
77 assert(rows > 0 && cols > 0 && scanline > 0)((void) sizeof ((rows > 0 && cols > 0 &&
scanline > 0) ? 1 : 0), __extension__ ({ if (rows > 0 &&
cols > 0 && scanline > 0) ; else __assert_fail
("rows > 0 && cols > 0 && scanline > 0"
, "ccv_io.c", 77, __extension__ __PRETTY_FUNCTION__); }))
;
78 if (type & CCV_IO_NO_COPY)
79 {
80 // there is no conversion that we can apply if it is NO_COPY mode
81 // NO_COPY mode generate an "unreusable" matrix, which requires you to
82 // manually release its data block (which is, in fact the same data
83 // block you passed in)
84 int ctype = CCV_8U | CCV_C1;
85 switch (type & 0xFF)
86 {
87 case CCV_IO_RGB_RAW:
88 case CCV_IO_BGR_RAW:
89 ctype = CCV_8U | CCV_C3;
90 break;
91 case CCV_IO_RGBA_RAW:
92 case CCV_IO_ARGB_RAW:
93 case CCV_IO_BGRA_RAW:
94 case CCV_IO_ABGR_RAW:
95 ctype = CCV_8U | CCV_C4;
96 break;
97 case CCV_IO_GRAY_RAW:
98 default:
99 /* default one */
100 break;
101 }
102 *x = ccv_dense_matrix_new(rows, cols, ctype | CCV_NO_DATA_ALLOC, data, 0);
103 (*x)->step = scanline;
104 } else {
105 switch (type & 0xFF)
106 {
107 case CCV_IO_RGB_RAW:
108 _ccv_read_rgb_raw(x, data, type, rows, cols, scanline);
109 break;
110 case CCV_IO_RGBA_RAW:
111 _ccv_read_rgba_raw(x, data, type, rows, cols, scanline);
112 break;
113 case CCV_IO_ARGB_RAW:
114 _ccv_read_argb_raw(x, data, type, rows, cols, scanline);
115 break;
116 case CCV_IO_BGR_RAW:
117 _ccv_read_bgr_raw(x, data, type, rows, cols, scanline);
118 break;
119 case CCV_IO_BGRA_RAW:
120 _ccv_read_bgra_raw(x, data, type, rows, cols, scanline);
121 break;
122 case CCV_IO_ABGR_RAW:
123 _ccv_read_abgr_raw(x, data, type, rows, cols, scanline);
124 break;
125 case CCV_IO_GRAY_RAW:
126 _ccv_read_gray_raw(x, data, type, rows, cols, scanline);
127 break;
128 }
129 }
130 if (*x != 0)
131 ccv_make_matrix_immutable(*x);
132 return CCV_IO_FINAL;
133}
134
135#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
136
137typedef struct {
138 char* buffer;
139 off_t pos;
140 size_t size;
141} ccv_io_mem_t;
142
143static int readfn(void* context, char* buf, int size)
144{
145 ccv_io_mem_t* mem = (ccv_io_mem_t*)context;
146 if (size + mem->pos > mem->size)
147 size = mem->size - mem->pos;
148 memcpy(buf, mem->buffer + mem->pos, size);
149 mem->pos += size;
150 return size;
151}
152
153static off_t seekfn(void* context, off_t off, int whence)
154{
155 ccv_io_mem_t* mem = (ccv_io_mem_t*)context;
156 off_t pos;
157 switch (whence)
158 {
159 case SEEK_SET0:
160 pos = off;
161 break;
162 case SEEK_CUR1:
163 pos = mem->pos + off;
164 break;
165 case SEEK_END2:
166 pos = mem->size + off;
167 break;
168 }
169 if (pos >= mem->size)
170 return -1;
171 mem->pos = pos;
172 return pos;
173}
174
175static int writefn(void* context, const char* buf, int size)
176{
177 ccv_io_mem_t* mem = (ccv_io_mem_t*)context;
178 if (size + mem->pos > mem->size)
179 return -1;
180 memcpy(mem->buffer + mem->pos, buf, size);
181 mem->pos += size;
182 return size;
183}
184#endif
185
186int ccv_read_impl(const void* in, ccv_dense_matrix_t** x, int type, int rows, int cols, int scanline)
187{
188 FILE* fd = 0;
189 if (type & CCV_IO_ANY_FILE)
1
Assuming the condition is true
2
Taking true branch
190 {
191 assert(rows == 0 && cols == 0 && scanline == 0)((void) sizeof ((rows == 0 && cols == 0 && scanline
== 0) ? 1 : 0), __extension__ ({ if (rows == 0 && cols
== 0 && scanline == 0) ; else __assert_fail ("rows == 0 && cols == 0 && scanline == 0"
, "ccv_io.c", 191, __extension__ __PRETTY_FUNCTION__); }))
;
3
Assuming 'rows' is equal to 0
4
Assuming 'cols' is equal to 0
5
Assuming 'scanline' is equal to 0
6
Taking true branch
192 fd = fopen((const char*)in, "rb");
193 if (!fd
6.1
'fd' is non-null
6.1
'fd' is non-null
)
7
Taking false branch
194 return CCV_IO_ERROR;
195 return _ccv_read_and_close_fd(fd, x, type);
8
Calling '_ccv_read_and_close_fd'
196 } else if (type & CCV_IO_ANY_STREAM) {
197 assert(rows > 8 && cols == 0 && scanline == 0)((void) sizeof ((rows > 8 && cols == 0 && scanline
== 0) ? 1 : 0), __extension__ ({ if (rows > 8 && cols
== 0 && scanline == 0) ; else __assert_fail ("rows > 8 && cols == 0 && scanline == 0"
, "ccv_io.c", 197, __extension__ __PRETTY_FUNCTION__); }))
;
198 assert((type & 0xFF) != CCV_IO_DEFLATE_STREAM)((void) sizeof (((type & 0xFF) != CCV_IO_DEFLATE_STREAM) ?
1 : 0), __extension__ ({ if ((type & 0xFF) != CCV_IO_DEFLATE_STREAM
) ; else __assert_fail ("(type & 0xFF) != CCV_IO_DEFLATE_STREAM"
, "ccv_io.c", 198, __extension__ __PRETTY_FUNCTION__); }))
; // deflate stream (compressed stream) is not supported yet
199#if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE200809L >= 200809L || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
200 // this is only supported by glibc
201#if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE200809L >= 200809L
202 fd = fmemopen((void*)in, (size_t)rows, "rb");
203#else
204 ccv_io_mem_t mem = {
205 .size = rows,
206 .pos = 0,
207 .buffer = (char*)in,
208 };
209 fd = funopen(&mem, readfn, 0, seekfn, 0);
210#endif
211 if (!fd)
212 return CCV_IO_ERROR;
213 // mimicking itself as a "file"
214 type = (type & ~0x10) | 0x20;
215 return _ccv_read_and_close_fd(fd, x, type);
216#endif
217 } else if (type & CCV_IO_ANY_RAW) {
218 return _ccv_read_raw(x, (void*)in /* it can be modifiable if it is NO_COPY mode */, type, rows, cols, scanline);
219 }
220 return CCV_IO_UNKNOWN;
221}
222
223int ccv_write(ccv_dense_matrix_t* mat, char* const out, size_t* const len, int type, void* conf)
224{
225 FILE* fd = 0;
226#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
227 ccv_io_mem_t mem = {0};
228#endif
229 if (type & CCV_IO_ANY_FILE)
230 {
231 fd = fopen(out, "wb");
232 if (!fd)
233 return CCV_IO_ERROR;
234 } else if ((type & CCV_IO_ANY_STREAM) && type != CCV_IO_PLAIN_STREAM) {
235 assert(len)((void) sizeof ((len) ? 1 : 0), __extension__ ({ if (len) ; else
__assert_fail ("len", "ccv_io.c", 235, __extension__ __PRETTY_FUNCTION__
); }))
;
236 assert((type & 0xFF) != CCV_IO_DEFLATE_STREAM)((void) sizeof (((type & 0xFF) != CCV_IO_DEFLATE_STREAM) ?
1 : 0), __extension__ ({ if ((type & 0xFF) != CCV_IO_DEFLATE_STREAM
) ; else __assert_fail ("(type & 0xFF) != CCV_IO_DEFLATE_STREAM"
, "ccv_io.c", 236, __extension__ __PRETTY_FUNCTION__); }))
; // deflate stream (compressed stream) is not supported yet
237#if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE200809L >= 200809L || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
238 // this is only supported by glibc
239#if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE200809L >= 200809L
240 fd = fmemopen((void*)out, *len, "wb");
241#else
242 mem.size = *len;
243 mem.buffer = out;
244 fd = funopen(&mem, 0, writefn, seekfn, 0);
245#endif
246#endif
247 }
248 int err = 0;
249 switch (type)
250 {
251 case CCV_IO_JPEG_FILE:
252#ifdef HAVE_LIBJPEG1
253 err = _ccv_write_jpeg_fd(mat, fd, conf);
254 if (len != 0)
255 *len = 0;
256#else
257 assert(0 && "ccv_write requires libjpeg support for JPEG format")((void) sizeof ((0 && "ccv_write requires libjpeg support for JPEG format"
) ? 1 : 0), __extension__ ({ if (0 && "ccv_write requires libjpeg support for JPEG format"
) ; else __assert_fail ("0 && \"ccv_write requires libjpeg support for JPEG format\""
, "ccv_io.c", 257, __extension__ __PRETTY_FUNCTION__); }))
;
258#endif
259 break;
260 case CCV_IO_PNG_FILE:
261#ifdef HAVE_LIBPNG1
262 err = _ccv_write_png_fd(mat, fd, conf);
263 if (len != 0)
264 *len = 0;
265#else
266 assert(0 && "ccv_write requires libpng support for PNG format")((void) sizeof ((0 && "ccv_write requires libpng support for PNG format"
) ? 1 : 0), __extension__ ({ if (0 && "ccv_write requires libpng support for PNG format"
) ; else __assert_fail ("0 && \"ccv_write requires libpng support for PNG format\""
, "ccv_io.c", 266, __extension__ __PRETTY_FUNCTION__); }))
;
267#endif
268 break;
269 case CCV_IO_BINARY_FILE:
270 _ccv_write_binary_fd(mat, fd, conf);
271 if (len != 0)
272 *len = 0;
273 break;
274 case CCV_IO_JPEG_STREAM:
275#ifdef HAVE_LIBJPEG1
276 err = _ccv_write_jpeg_fd(mat, fd, conf);
277#else
278 assert(0 && "ccv_write requires libjpeg support for JPEG format")((void) sizeof ((0 && "ccv_write requires libjpeg support for JPEG format"
) ? 1 : 0), __extension__ ({ if (0 && "ccv_write requires libjpeg support for JPEG format"
) ; else __assert_fail ("0 && \"ccv_write requires libjpeg support for JPEG format\""
, "ccv_io.c", 278, __extension__ __PRETTY_FUNCTION__); }))
;
279#endif
280 break;
281 case CCV_IO_PNG_STREAM:
282#ifdef HAVE_LIBPNG1
283 err = _ccv_write_png_fd(mat, fd, conf);
284#else
285 assert(0 && "ccv_write requires libpng support for PNG format")((void) sizeof ((0 && "ccv_write requires libpng support for PNG format"
) ? 1 : 0), __extension__ ({ if (0 && "ccv_write requires libpng support for PNG format"
) ; else __assert_fail ("0 && \"ccv_write requires libpng support for PNG format\""
, "ccv_io.c", 285, __extension__ __PRETTY_FUNCTION__); }))
;
286#endif
287 break;
288 case CCV_IO_PLAIN_STREAM:
289 err = _ccv_write_plain_stream(mat, out, *len);
290 *len = 20 + mat->step * mat->rows;
291 break;
292 }
293 if ((type & CCV_IO_ANY_STREAM) && type != CCV_IO_PLAIN_STREAM)
294 *len = (size_t)ftell(fd);
295 if (fd)
296 fclose(fd);
297 return err != 0 ? CCV_IO_ERROR : CCV_IO_FINAL;
298}

./io/_ccv_io_bmp.inc

1static void _ccv_read_bmp_fd(FILE* in, ccv_dense_matrix_t** x, int type)
2{
3 fseek(in, 10, SEEK_SET0);
4 int offset;
5 (void) fread(&offset, 4, 1, in);
6 int size;
7 (void) fread(&size, 4, 1, in);
8 int width = 0, height = 0, bpp = 0, rle_code = 0, clrused = 0;
9 if (size >= 36)
15
Assuming 'size' is >= 36
16
Taking true branch
10 {
11 (void) fread(&width, 4, 1, in);
12 (void) fread(&height, 4, 1, in);
17
Assuming this stream operation fails
13 (void) fread(&bpp, 4, 1, in);
18
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior
14 bpp = bpp >> 16;
15 (void) fread(&rle_code, 4, 1, in);
16 fseek(in, 12, SEEK_CUR1);
17 (void) fread(&clrused, 4, 1, in);
18 fseek(in, size - 36, SEEK_CUR1);
19 /* only support 24-bit bmp */
20 } else if (size == 12) {
21 (void) fread(&width, 4, 1, in);
22 (void) fread(&height, 4, 1, in);
23 (void) fread(&bpp, 4, 1, in);
24 bpp = bpp >> 16;
25 /* TODO: not finished */
26 }
27 if (width == 0 || height == 0 || bpp == 0)
28 return;
29 ccv_dense_matrix_t* im = *x;
30 if (im == 0)
31 *x = im = ccv_dense_matrix_new(height, width, (type) ? type : CCV_8U | ((bpp > 8) ? CCV_C3 : CCV_C1), 0, 0);
32 fseek(in, offset, SEEK_SET0);
33 int i, j;
34 unsigned char* ptr = im->data.u8 + (im->rows - 1) * im->step;
35 if ((bpp == 8 && CCV_GET_CHANNEL(im->type)((im->type) & 0xFFF) == CCV_C1) || (bpp == 24 && CCV_GET_CHANNEL(im->type)((im->type) & 0xFFF) == CCV_C3))
36 {
37 if (CCV_GET_CHANNEL(im->type)((im->type) & 0xFFF) == CCV_C1)
38 {
39 for (i = 0; i < im->rows; i++)
40 {
41 (void) fread(ptr, 1, im->step, in);
42 ptr -= im->step;
43 }
44 } else {
45 for (i = 0; i < im->rows; i++)
46 {
47 (void) fread(ptr, 1, im->step, in);
48 for (j = 0; j < im->cols * 3; j += 3)
49 {
50 unsigned char t = ptr[j];
51 ptr[j] = ptr[j + 2];
52 ptr[j + 2] = t;
53 }
54 ptr -= im->step;
55 }
56 }
57 } else {
58 if (bpp == 24 && CCV_GET_CHANNEL(im->type)((im->type) & 0xFFF) == CCV_C1)
59 {
60 int bufstep = (im->cols * 3 + 3) & -4;
61 unsigned char* buffer = (unsigned char*)alloca(bufstep)__builtin_alloca (bufstep);
62 for (i = 0; i < im->rows; i++)
63 {
64 (void) fread(buffer, 1, bufstep, in);
65 unsigned char* rgb = buffer;
66 unsigned char* g = ptr;
67 for(j = 0; j < im->cols; j++, rgb += 3, g++)
68 *g = (unsigned char)((rgb[2] * 6969 + rgb[1] * 23434 + rgb[0] * 2365) >> 15);
69 ptr -= im->step;
70 }
71 } else if (bpp == 8 && CCV_GET_CHANNEL(im->type)((im->type) & 0xFFF) == CCV_C3) {
72 int bufstep = (im->cols + 3) & -4;
73 unsigned char* buffer = (unsigned char*)alloca(bufstep)__builtin_alloca (bufstep);
74 for (i = 0; i < im->rows; i++)
75 {
76 (void) fread(buffer, 1, bufstep, in);
77 unsigned char* g = buffer;
78 unsigned char* rgb = ptr;
79 for(j = 0; j < im->cols; j++, rgb += 3, g++)
80 rgb[2] = rgb[1] = rgb[0] = *g;
81 ptr -= im->step;
82 }
83 }
84 }
85}