Bug Summary

File:_build/../thumbnailer/gnome-thumbnailer-skeleton.c
Warning:line 265, column 16
This statement is never executed

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 gnome-thumbnailer-skeleton.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 -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/_build -fcoverage-compilation-dir=/rootdir/_build -resource-dir /usr/lib/llvm-21/lib/clang/21 -I thumbnailer/cdk-pixbuf-thumbnailer.p -I thumbnailer -I ../thumbnailer -I . -I .. -I cdk-pixbuf -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/libmount -I /usr/include/blkid -D _FILE_OFFSET_BITS=64 -D _POSIX_C_SOURCE=200809L -D _DEFAULT_SOURCE -D _XOPEN_SOURCE=700 -D HAVE_CONFIG_H=1 -D THUMBNAILER_RETURNS_PIXBUF -D THUMBNAILER_USAGE="Thumbnail images" -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-int-conversion -Wno-uninitialized -Wno-discarded-qualifiers -std=gnu99 -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker security.ArrayBound -analyzer-checker unix.cstring.NotNullTerminated -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2026-06-03-092842-8532-1 -x c ../thumbnailer/gnome-thumbnailer-skeleton.c
1/*
2 * Copyright (C) 2013 Bastien Nocera <hadess@hadess.net>
3 *
4 * Authors: Bastien Nocera <hadess@hadess.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22#include <string.h>
23#include <glib.h>
24#include <gio/gio.h>
25#include <cdk-pixbuf/cdk-pixbuf.h>
26
27#include <locale.h>
28#include <math.h>
29#include <stdlib.h>
30
31#include "gnome-thumbnailer-skeleton.h"
32
33#ifndef THUMBNAILER_USAGE"Thumbnail images"
34#error "THUMBNAILER_USAGE must be set"
35#endif
36
37static int output_size = 256;
38static gboolean g_fatal_warnings = FALSE(0);
39static char **filenames = NULL((void*)0);
40
41#if !CDK_PIXBUF_CHECK_VERSION(2,36,5)((2) > (2) || ((2) == (2) && (45) > (36)) || ((
2) == (2) && (45) == (36) && (0) >= (5)))
42/**
43 * gnome_desktop_thumbnail_scale_down_pixbuf:
44 * @pixbuf: a #CdkPixbuf
45 * @dest_width: the desired new width
46 * @dest_height: the desired new height
47 *
48 * Scales the pixbuf to the desired size. This function
49 * is a lot faster than cdk-pixbuf when scaling down by
50 * large amounts.
51 *
52 * Return value: (transfer full): a scaled pixbuf
53 *
54 * Since: 2.2
55 **/
56CdkPixbuf *
57gnome_desktop_thumbnail_scale_down_pixbuf (CdkPixbuf *pixbuf,
58 int dest_width,
59 int dest_height)
60{
61 int source_width, source_height;
62 int s_x1, s_y1, s_x2, s_y2;
63 int s_xfrac, s_yfrac;
64 int dx, dx_frac, dy, dy_frac;
65 div_t ddx, ddy;
66 int x, y;
67 int r, g, b, a;
68 int n_pixels;
69 gboolean has_alpha;
70 guchar *dest, *src, *xsrc, *src_pixels;
71 CdkPixbuf *dest_pixbuf;
72 int pixel_stride;
73 int source_rowstride, dest_rowstride;
74
75 if (dest_width == 0 || dest_height == 0) {
76 return NULL((void*)0);
77 }
78
79 source_width = cdk_pixbuf_get_width (pixbuf);
80 source_height = cdk_pixbuf_get_height (pixbuf);
81
82 g_assert (source_width >= dest_width)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_10
= 0; if (source_width >= dest_width) _g_boolean_var_10 = 1
; _g_boolean_var_10; }), 1)) ; else g_assertion_message_expr (
((gchar*) 0), "../thumbnailer/gnome-thumbnailer-skeleton.c", 82
, ((const char*) (__func__)), "source_width >= dest_width"
); } while (0)
;
83 g_assert (source_height >= dest_height)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_11
= 0; if (source_height >= dest_height) _g_boolean_var_11 =
1; _g_boolean_var_11; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "../thumbnailer/gnome-thumbnailer-skeleton.c"
, 83, ((const char*) (__func__)), "source_height >= dest_height"
); } while (0)
;
84
85 ddx = div (source_width, dest_width);
86 dx = ddx.quot;
87 dx_frac = ddx.rem;
88
89 ddy = div (source_height, dest_height);
90 dy = ddy.quot;
91 dy_frac = ddy.rem;
92
93 g_assert (dx >= 1)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_12
= 0; if (dx >= 1) _g_boolean_var_12 = 1; _g_boolean_var_12
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "../thumbnailer/gnome-thumbnailer-skeleton.c"
, 93, ((const char*) (__func__)), "dx >= 1"); } while (0)
;
94 g_assert (dy >= 1)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_13
= 0; if (dy >= 1) _g_boolean_var_13 = 1; _g_boolean_var_13
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "../thumbnailer/gnome-thumbnailer-skeleton.c"
, 94, ((const char*) (__func__)), "dy >= 1"); } while (0)
;
95
96 has_alpha = cdk_pixbuf_get_has_alpha (pixbuf);
97 source_rowstride = cdk_pixbuf_get_rowstride (pixbuf);
98 src_pixels = cdk_pixbuf_get_pixels (pixbuf);
99
100 dest_pixbuf = cdk_pixbuf_new (CDK_COLORSPACE_RGB, has_alpha, 8,
101 dest_width, dest_height);
102 dest = cdk_pixbuf_get_pixels (dest_pixbuf);
103 dest_rowstride = cdk_pixbuf_get_rowstride (dest_pixbuf);
104
105 pixel_stride = (has_alpha)?4:3;
106
107 s_y1 = 0;
108 s_yfrac = -dest_height/2;
109 while (s_y1 < source_height) {
110 s_y2 = s_y1 + dy;
111 s_yfrac += dy_frac;
112 if (s_yfrac > 0) {
113 s_y2++;
114 s_yfrac -= dest_height;
115 }
116
117 s_x1 = 0;
118 s_xfrac = -dest_width/2;
119 while (s_x1 < source_width) {
120 s_x2 = s_x1 + dx;
121 s_xfrac += dx_frac;
122 if (s_xfrac > 0) {
123 s_x2++;
124 s_xfrac -= dest_width;
125 }
126
127 /* Average block of [x1,x2[ x [y1,y2[ and store in dest */
128 r = g = b = a = 0;
129 n_pixels = 0;
130
131 src = src_pixels + s_y1 * source_rowstride + s_x1 * pixel_stride;
132 for (y = s_y1; y < s_y2; y++) {
133 xsrc = src;
134 if (has_alpha) {
135 for (x = 0; x < s_x2-s_x1; x++) {
136 n_pixels++;
137
138 r += xsrc[3] * xsrc[0];
139 g += xsrc[3] * xsrc[1];
140 b += xsrc[3] * xsrc[2];
141 a += xsrc[3];
142 xsrc += 4;
143 }
144 } else {
145 for (x = 0; x < s_x2-s_x1; x++) {
146 n_pixels++;
147 r += *xsrc++;
148 g += *xsrc++;
149 b += *xsrc++;
150 }
151 }
152 src += source_rowstride;
153 }
154
155 g_assert (n_pixels > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_14
= 0; if (n_pixels > 0) _g_boolean_var_14 = 1; _g_boolean_var_14
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "../thumbnailer/gnome-thumbnailer-skeleton.c"
, 155, ((const char*) (__func__)), "n_pixels > 0"); } while
(0)
;
156
157 if (has_alpha) {
158 if (a != 0) {
159 *dest++ = r / a;
160 *dest++ = g / a;
161 *dest++ = b / a;
162 *dest++ = a / n_pixels;
163 } else {
164 *dest++ = 0;
165 *dest++ = 0;
166 *dest++ = 0;
167 *dest++ = 0;
168 }
169 } else {
170 *dest++ = r / n_pixels;
171 *dest++ = g / n_pixels;
172 *dest++ = b / n_pixels;
173 }
174
175 s_x1 = s_x2;
176 }
177 s_y1 = s_y2;
178 dest += dest_rowstride - dest_width * pixel_stride;
179 }
180
181 return dest_pixbuf;
182}
183#endif
184
185static char *
186get_target_uri (GFile *file)
187{
188 GFileInfo *info;
189 char *target;
190
191 info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI"standard::target-uri", G_FILE_QUERY_INFO_NONE, NULL((void*)0), NULL((void*)0));
192 if (info == NULL((void*)0))
193 return NULL((void*)0);
194 target = g_strdup (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI))g_strdup_inline (g_file_info_get_attribute_string (info, "standard::target-uri"
))
;
195 g_object_unref (info);
196
197 return target;
198}
199
200static char *
201get_target_path (GFile *input)
202{
203 if (g_file_has_uri_scheme (input, "trash") != FALSE(0) ||
204 g_file_has_uri_scheme (input, "recent") != FALSE(0)) {
205 GFile *file;
206 char *input_uri;
207 char *input_path;
208
209 input_uri = get_target_uri (input);
210 file = g_file_new_for_uri (input_uri);
211 g_free (input_uri);
212 input_path = g_file_get_path (file);
213 g_object_unref (file);
214 return input_path;
215 }
216 return g_file_get_path (input);
217}
218
219static const GOptionEntry entries[] = {
220 { "size", 's', 0, G_OPTION_ARG_INT, &output_size, "Size of the thumbnail in pixels", NULL((void*)0) },
221 {"g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, "Make all warnings fatal", NULL((void*)0)},
222 { G_OPTION_REMAINING"", '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL((void*)0), "[INPUT FILE] [OUTPUT FILE]" },
223 { NULL((void*)0) }
224};
225
226int main (int argc, char **argv)
227{
228 char *input_filename;
229 CdkPixbuf *pixbuf;
230 GError *error = NULL((void*)0);
231 GOptionContext *context;
232 GFile *input;
233 const char *output;
234
235#ifdef THUMBNAILER_RETURNS_PIXBUF1
236 /* Nothing */
237#elif THUMBNAILER_RETURNS_DATA
238 char *data = NULL((void*)0);
239 gsize length;
240#endif
241
242 setlocale (LC_ALL6, "");
243
244#if !GLIB_CHECK_VERSION(2, 36, 0)(2 > (2) || (2 == (2) && 88 > (36)) || (2 == (2
) && 88 == (36) && 1 >= (0)))
245 g_type_init ();
246#endif
247
248 /* Options parsing */
249 context = g_option_context_new (THUMBNAILER_USAGE"Thumbnail images");
250 g_option_context_add_main_entries (context, entries, NULL((void*)0));
251
252 if (g_option_context_parse (context, &argc, &argv, &error) == FALSE(0)) {
253 g_warning ("Couldn't parse command-line options: %s", error->message);
254 g_error_free (error);
255 g_option_context_free (context);
256 return 1;
257 }
258
259 g_option_context_free (context);
260
261 /* Set fatal warnings if required */
262 if (g_fatal_warnings) {
263 GLogLevelFlags fatal_mask;
264
265 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK(G_LOG_FLAG_RECURSION | G_LOG_LEVEL_ERROR));
This statement is never executed
266 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
267 g_log_set_always_fatal (fatal_mask);
268 }
269
270 if (filenames == NULL((void*)0) || g_strv_length (filenames) != 2) {
271 g_print ("Expects an input and an output file\n");
272 return 1;
273 }
274
275 input = g_file_new_for_commandline_arg (filenames[0]);
276 input_filename = get_target_path (input);
277 g_object_unref (input);
278
279 if (input_filename == NULL((void*)0)) {
280 g_warning ("Could not get file path for %s", filenames[0]);
281 return 1;
282 }
283
284 output = filenames[1];
285
286#ifdef THUMBNAILER_RETURNS_PIXBUF1
287 pixbuf = file_to_pixbuf (input_filename, output_size, &error);
288 if (pixbuf != NULL((void*)0)) {
289 int width, height;
290
291 width = cdk_pixbuf_get_width (pixbuf);
292 height = cdk_pixbuf_get_height (pixbuf);
293
294 /* Handle naive thumbnailers that don't resize */
295 if (output_size != 0 &&
296 (height > output_size || width > output_size)) {
297 CdkPixbuf *scaled;
298 double scale;
299
300 scale = (double)output_size / MAX (width, height)(((width) > (height)) ? (width) : (height));
301
302#if !CDK_PIXBUF_CHECK_VERSION(2,36,5)((2) > (2) || ((2) == (2) && (45) > (36)) || ((
2) == (2) && (45) == (36) && (0) >= (5)))
303 scaled = gnome_desktop_thumbnail_scale_down_pixbuf (pixbuf,
304 floor (width * scale + 0.5),
305 floor (height * scale + 0.5));
306#else
307 scaled = cdk_pixbuf_scale_simple (pixbuf,
308 floor (width * scale + 0.5),
309 floor (height * scale + 0.5),
310 CDK_INTERP_BILINEAR);
311#endif
312 cdk_pixbuf_copy_options (pixbuf, scaled);
313 g_object_unref (pixbuf);
314 pixbuf = scaled;
315 }
316 }
317#elif THUMBNAILER_RETURNS_DATA
318 data = file_to_data (input_filename, &length, &error);
319 if (data) {
320 GInputStream *mem_stream;
321
322 mem_stream = g_memory_input_stream_new_from_data (data, length, g_free);
323 pixbuf = cdk_pixbuf_new_from_stream_at_scale (mem_stream, output_size, -1, TRUE(!(0)), NULL((void*)0), &error);
324 g_object_unref (mem_stream);
325 } else {
326 pixbuf = NULL((void*)0);
327 }
328#else
329#error "One of THUMBNAILER_RETURNS_PIXBUF or THUMBNAILER_RETURNS_DATA must be set"
330#endif
331 g_free (input_filename);
332
333 if (!pixbuf) {
334 g_warning ("Could not thumbnail '%s': %s", filenames[0],
335 error ? error->message : "Thumbnailer failed without returning an error");
336 g_clear_error (&error);
337 g_strfreev (filenames);
338 return 1;
339 }
340
341 if (cdk_pixbuf_save (pixbuf, output, "png", &error, NULL((void*)0)) == FALSE(0)) {
342 g_warning ("Couldn't save the thumbnail '%s' for file '%s': %s", output, filenames[0], error->message);
343 g_error_free (error);
344 return 1;
345 }
346
347 g_object_unref (pixbuf);
348
349 return 0;
350}