Bug Summary

File:player/player.c
Location:line 157, column 51
Description:Access to field 'nfiles' results in a dereference of a null pointer (loaded from field 'queue')

Annotated Source Code

1/*
2 * Copyright (c) 2010, 2011, 2012 Ryan Flannery <ryan.flannery@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "player.h"
18
19/* globals */
20player_backend_t player;
21player_info_t player_info;
22
23
24/* callbacks */
25static void callback_playnext() { player_skip_song(1); }
26
27static void
28callback_fatal(char *fmt, ...)
29{
30 va_list ap;
31
32 ui_destroy();
33
34 fprintf(stderr(&__sF[2]),"The player-backend '%s' has experienced a fatal error:\n",
35 player.name);
36
37 va_start(ap, fmt)__builtin_va_start(ap, fmt);
38 vfprintf(stderr(&__sF[2]), fmt, ap);
39 va_end(ap)__builtin_va_end(ap);
40
41 fflush(stderr(&__sF[2]));
42
43 VSIG_QUIT = 1;
44 exit(1);
45}
46
47
48/* definition of backends */
49const player_backend_t PlayerBackends[] = {
50 {
51 BACKEND_MPLAYER, "mplayer", false0, NULL((void *)0),
52 mplayer_start,
53 mplayer_finish,
54 mplayer_sigchld,
55 mplayer_play,
56 mplayer_stop,
57 mplayer_pause,
58 mplayer_seek,
59 mplayer_volume_step,
60 mplayer_get_position,
61 mplayer_get_volume,
62 mplayer_is_playing,
63 mplayer_is_paused,
64 mplayer_set_callback_playnext,
65 mplayer_set_callback_notice,
66 mplayer_set_callback_error,
67 mplayer_set_callback_fatal,
68 mplayer_monitor
69 },
70# if defined(ENABLE_GSTREAMER)
71 {
72 BACKEND_GSTREAMER, "gst", false0, NULL((void *)0),
73 gstplayer_init,
74 gstplayer_cleanup,
75 NULL((void *)0),
76 gstplayer_play,
77 gstplayer_stop,
78 gstplayer_pause,
79 gstplayer_seek,
80 gstplayer_volume_step,
81 gstplayer_get_position,
82 gstplayer_get_volume,
83 gstplayer_is_playing,
84 gstplayer_is_paused,
85 gstplayer_set_callback_playnext,
86 gstplayer_set_callback_notice,
87 gstplayer_set_callback_error,
88 gstplayer_set_callback_fatal,
89 gstplayer_monitor,
90 },
91# endif
92 { 0, "", false0, NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
93 NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0) }
94};
95const size_t PlayerBackendsSize = sizeof(PlayerBackends) / sizeof(player_backend_t);
96
97
98/* setup/destroy functions */
99void
100player_init(const char *backend,
101 void (message_handler)(char *fmt, ...),
102 void (error_handler)(char *fmt, ...))
103{
104 bool_Bool found;
105 size_t i;
106
107 player_info.mode = MODE_LINEAR;
108 player_info.queue = NULL((void *)0);
109 player_info.qidx = -1;
110
111 player_info.rseed = time(0);
112 srand(player_info.rseed);
113
114 /* find the player backend */
115 found = false0;
116 for (i = 0; i < PlayerBackendsSize && !found; i++) {
117 if (!strcasecmp(backend, PlayerBackends[i].name)) {
118 player = PlayerBackends[i];
119 found = true1;
120 }
121 }
122
123 if (!found)
124 errx(1, "media backend '%s' is unknown", backend);
125
126 if (player.dynamic) {
127 ui_destroy();
128 errx(1, "dynamically loaded backends not yet supported");
129 }
130
131 player.set_callback_playnext(callback_playnext);
132 player.set_callback_notice(message_handler);
133 player.set_callback_error(error_handler);
134 player.set_callback_fatal(callback_fatal);
135 player.start();
136}
137
138void
139player_destroy()
140{
141 player.finish();
142}
143
144void
145player_set_queue(playlist *queue, int pos)
146{
147 player_info.queue = queue;
148 player_info.qidx = pos;
149}
150
151void
152player_play()
153{
154 if (player_info.queue == NULL((void *)0))
9
Assuming pointer value is null
10
Taking true branch
155 errx(1, "player_play: bad queue/qidx");
156
157 if (player_info.qidx < 0 || player_info.qidx > player_info.queue->nfiles)
11
Access to field 'nfiles' results in a dereference of a null pointer (loaded from field 'queue')
158 errx(1, "player_play: qidx %i out-of-range", player_info.qidx);
159
160 player.play(player_info.queue->files[player_info.qidx]->filename);
161
162}
163
164void
165player_stop()
166{
167 player.stop();
168}
169
170void
171player_pause()
172{
173 if (!player.playing())
174 return;
175
176 player.pause();
177}
178
179void
180player_seek(int seconds)
181{
182 if (!player.playing())
183 return;
184
185 player.seek(seconds);
186}
187
188/* TODO merge this with the player_play_prev_song into player_skip_song */
189void
190player_play_next_song(int skip)
191{
192 if (!player.playing())
193 return;
194
195 switch (player_info.mode) {
196 case MODE_LINEAR:
197 player_info.qidx += skip;
198 if (player_info.qidx >= player_info.queue->nfiles) {
199 player_info.qidx = 0;
200 player_stop();
201 } else
202 player_play();
203
204 break;
205
206 case MODE_LOOP:
207 player_info.qidx += skip;
208 if (player_info.qidx >= player_info.queue->nfiles)
209 player_info.qidx %= player_info.queue->nfiles;
210
211 player_play();
212 break;
213
214 case MODE_RANDOM:
215 player_info.qidx = rand() % player_info.queue->nfiles;
216 player_play();
217 break;
218 }
219}
220
221/* TODO (see comment for player_play_next_song) */
222void
223player_play_prev_song(int skip)
224{
225 if (!player.playing())
4
Value assigned to 'player_info.queue'
5
Taking false branch
226 return;
227
228 switch (player_info.mode) {
6
Control jumps to 'case MODE_LINEAR:' at line 229
229 case MODE_LINEAR:
230 player_info.qidx -= skip;
231 if (player_info.qidx < 0) {
7
Taking false branch
232 player_info.qidx = 0;
233 player_stop();
234 } else
235 player_play();
8
Calling 'player_play'
236
237 break;
238
239 case MODE_LOOP:
240 skip %= player_info.queue->nfiles;
241 if (skip <= player_info.qidx)
242 player_info.qidx -= skip;
243 else
244 player_info.qidx = player_info.queue->nfiles - (skip + player_info.qidx);
245
246 player_play();
247 break;
248
249 case MODE_RANDOM:
250 player_info.qidx = rand() % player_info.queue->nfiles;
251 player_play();
252 break;
253 }
254}
255
256/* TODO merge with above... wtf didn't i do it that way!? */
257void
258player_skip_song(int num)
259{
260 if (num >= 0)
1
Assuming 'num' is < 0
2
Taking false branch
261 player_play_next_song(num);
262 else
263 player_play_prev_song(num * -1);
3
Calling 'player_play_prev_song'
264}
265
266void
267player_volume_step(float percent)
268{
269 if (!player.playing())
270 return;
271
272 player.volume_step(percent);
273}
274
275void
276player_monitor(void)
277{
278 player.monitor();
279}
280