Bug Summary

File:c:\siege\siege/src/siege/audio/buffer.c
Location:line 160, column 16
Description:Potential leak of memory pointed to by 'buffer'

Annotated Source Code

1/*
2 * Copyright (c) 2007 SIEGE Development Team
3 * All rights reserved.
4 *
5 * This file is part of libSIEGE.
6 *
7 * This software is copyrighted work licensed under the terms of the
8 * 2-clause BSD license. Please consult the file "COPYING.txt" for
9 * details.
10 *
11 * If you did not recieve the file with this program, please email
12 * Tim Chas <darkuranium@gmail.com>.
13 */
14
15#define SG_BUILD_LIBRARY
16#include <siege/audio/buffer.h>
17
18#include <stdlib.h>
19#include <string.h>
20
21#include <al.h>
22#include <alc.h>
23
24#include "../internal/stb/stb_vorbis.h"
25
26// TODO: Streaming audio, proper error handling for loading
27#define ALBUF(x)(*(ALuint*)(x)->handle) (*(ALuint*)(x)->handle)
28
29// TODO: Move this to an util library; clean it up.
30static void* toStereo(SGuint channels, void* data, size_t* datalen, ALuint* alformat)
31{
32 void* odata = data;
33 if(channels == 2)
34 {
35 if(*alformat == AL_FORMAT_MONO80x1100)
36 *alformat = AL_FORMAT_STEREO80x1102;
37 else
38 *alformat = AL_FORMAT_STEREO160x1103;
39 }
40 else if(channels > 2)
41 {
42 SGuint chan;
43 SGuint i;
44 long double sum1;
45 long double sum2;
46 int num1;
47 int num2;
48 if(*alformat == AL_FORMAT_MONO80x1100)
49 {
50 odata = malloc(*datalen * sizeof(SGubyte));
51 memcpy(odata, data, *datalen * sizeof(SGubyte));
52
53 *alformat = AL_FORMAT_STEREO80x1102;
54 SGubyte* bdata = (SGubyte*) odata;
55
56 for(i = 0; i < *datalen; i += channels)
57 {
58 sum1 = 0;
59 num1 = 0;
60 sum2 = 0;
61 num2 = 0;
62
63 if(channels % 2 != 0)
64 {
65 chan = 1;
66 sum1 += bdata[i / channels] * 0.5L; // 1/2 because we put this on both chans
67 num1++;
68 sum2 += bdata[i / channels] * 0.5L;
69 num2++;
70 }
71 else
72 chan = 0;
73 for(; chan < channels; chan++)
74 {
75 if(chan % 2 == 0)
76 {
77 sum1 += bdata[i + chan];
78 num1++;
79 }
80 else
81 {
82 sum2 += bdata[i + chan];
83 num2++;
84 }
85 }
86 bdata[i / channels ] = (SGubyte)(sum1 / num1);
87 bdata[i / channels + 1] = (SGubyte)(sum2 / num2);
88 }
89 }
90 else
91 {
92 odata = malloc(*datalen * sizeof(SGushort));
93 memcpy(odata, data, *datalen * sizeof(SGushort));
94
95 *alformat = AL_FORMAT_STEREO160x1103;
96 SGshort* sdata = (SGshort*) odata;
97
98 for(i = 0; i < *datalen / 2; i += channels)
99 {
100 sum1 = 0;
101 num1 = 0;
102 sum2 = 0;
103 num2 = 0;
104
105 if(channels % 2 != 0)
106 {
107 chan = 1;
108 sum1 += sdata[i / channels] * 0.5L; // 1/2 because we put this on both chans
109 num1++;
110 sum2 += sdata[i / channels] * 0.5L;
111 num2++;
112 }
113 else
114 chan = 0;
115 for(; chan < channels; chan++)
116 {
117 if(chan % 2 == 0)
118 {
119 sum1 += sdata[i + chan];
120 num1++;
121 }
122 else
123 {
124 sum2 += sdata[i + chan];
125 num2++;
126 }
127 }
128 sdata[i / channels ] = (SGushort)(sum1 / num1);
129 sdata[i / channels + 1] = (SGushort)(sum2 / num2);
130 }
131 }
132 *datalen = *datalen / channels * 2;
133 }
134 return odata;
135}
136
137SGAudioBuffer* SG_CALL__cdecl sgAudioBufferCreateStream(SGStream* stream, SGbool delstream)
138{
139 SGAudioBuffer* buffer = malloc(sizeof(SGAudioBuffer));
2
Memory is allocated
140
141 buffer->stream = stream;
142 buffer->del = delstream;
143
144 buffer->handle = malloc(sizeof(ALuint));
145 alGenBuffers(1, buffer->handle);
146
147 SGuint channels;
148 SGuint format;
149 SGuint frequency;
150 void* data = NULL((void*)0);
151 SGuint datalen;
152 SGuint nsamples;
153
154 void* buf = NULL((void*)0);
155 int error = 0;
156 stb_vorbis* stb = NULL((void*)0);
157 stb_vorbis_info info;
158
159 if(!stream || !stream->read || !stream->seek || !stream->tell)
3
Assuming 'stream' is null
160 return NULL((void*)0);
4
Within the expansion of the macro 'NULL':
a
Potential leak of memory pointed to by 'buffer'
161
162 SGlong pos = sgStreamTell(stream);
163 SGlong size = sgStreamTellSize(stream);
164 size -= pos;
165 if(pos < 0 || size < 0)
166 goto lderr;
167
168 buf = malloc(size);
169 if(sgStreamRead(stream, buf, 1, size) != size)
170 goto lderr;
171
172 stb = stb_vorbis_open_memory(buf, size, &error, NULL((void*)0));
173 if(!stb) goto lderr;
174
175 info = stb_vorbis_get_info(stb);
176 channels = info.channels;
177 frequency = info.sample_rate;
178 format = SG_AUDIO_FORMAT_S160x02; // or SG_AUDIO_FORMAT_F
179
180 nsamples = stb_vorbis_stream_length_in_samples(stb);
181 datalen = 2 * nsamples * channels;
182 data = malloc(datalen);
183
184 datalen = 2 * stb_vorbis_get_samples_short_interleaved(stb, info.channels, data, datalen / 2);
185
186 sgAudioBufferSetData(buffer, channels, format, frequency, data, datalen);
187 free(data);
188
189lderr:
190 if(stb)
191 stb_vorbis_close(stb);
192 if(buf)
193 free(buf);
194
195 return buffer;
196}
197SGAudioBuffer* SG_CALL__cdecl sgAudioBufferCreateFile(const char* fname)
198{
199 return sgAudioBufferCreateStream(sgStreamCreateFile(fname, "r"), SG_TRUE1);
1
Calling 'sgAudioBufferCreateStream'
200}
201void SG_CALL__cdecl sgAudioBufferDestroy(SGAudioBuffer* buffer)
202{
203 if(buffer == NULL((void*)0))
204 return;
205
206 alDeleteBuffers(1, buffer->handle);
207 free(buffer->handle);
208 if(buffer->del)
209 sgStreamDestroy(buffer->stream);
210 free(buffer);
211}
212
213void SG_CALL__cdecl sgAudioBufferSetData(SGAudioBuffer* buffer, SGuint channels, SGuint format, SGuint frequency, void* data, size_t datalen)
214{
215 //AL_FORMAT_[MONO, STEREO][8, 16]
216 ALuint alformat;
217
218 SGuint i;
219 SGubyte* bdata = (SGubyte*)data;
220 SGshort* scur;
221 SGint* icur;
222 SGfloat* fcur;
223 SGdouble* dcur;
224 switch(format)
225 {
226 case SG_AUDIO_FORMAT_S80x01:
227 alformat = AL_FORMAT_MONO80x1100;
228 for(i = 0; i < datalen; i++)
229 bdata[i] = bdata[i] + 0x80;
230 break;
231 case SG_AUDIO_FORMAT_S160x02:
232 alformat = AL_FORMAT_MONO160x1101;
233 break;
234 case SG_AUDIO_FORMAT_S240x03:
235 alformat = AL_FORMAT_MONO160x1101;
236 for(i = 0; i < datalen; i += 3)
237 {
238 icur = (SGint*)&bdata[i];
239 scur = (SGshort*)&bdata[i / 3 * 2];
240 *scur = (SGshort)((*icur >> 8) / 256.0L);
241 }
242 datalen = datalen / 3 * 2;
243 break;
244 case SG_AUDIO_FORMAT_S320x04:
245 alformat = AL_FORMAT_MONO160x1101;
246 for(i = 0; i < datalen; i += 4)
247 {
248 icur = (SGint*)&bdata[i];
249 scur = (SGshort*)&bdata[i / 4 * 2];
250 *scur = (SGshort)(*icur / 65536.0L);
251 }
252 datalen = datalen / 4 * 2;
253 break;
254
255 case SG_AUDIO_FORMAT_U80x05:
256 alformat = AL_FORMAT_MONO80x1100;
257 break;
258 case SG_AUDIO_FORMAT_U160x06:
259 alformat = AL_FORMAT_MONO160x1101;
260 for(i = 0; i < datalen; i += 2)
261 {
262 scur = (SGshort*)&bdata[i];
263 *scur = *scur - 0x7FFF;
264 }
265 break;
266 case SG_AUDIO_FORMAT_U240x07:
267 alformat = AL_FORMAT_MONO160x1101;
268 for(i = 0; i < datalen; i += 3)
269 {
270 icur = (SGint*)&bdata[i];
271 scur = (SGshort*)&bdata[i / 3 * 2];
272 *scur = (SGshort)((*icur >> 8) / 256.0L) - 0x7FFF;
273 }
274 datalen = datalen / 3 * 2;
275 break;
276 case SG_AUDIO_FORMAT_U320x08:
277 alformat = AL_FORMAT_MONO160x1101;
278 for(i = 0; i < datalen; i += 4)
279 {
280 icur = (SGint*)&bdata[i];
281 scur = (SGshort*)&bdata[i / 4 * 2];
282 *scur = (SGshort)(*icur / 65536.0L) - 0x7FFF;
283 }
284 datalen = datalen / 4 * 2;
285 break;
286
287 case SG_AUDIO_FORMAT_F0x0A:
288 alformat = AL_FORMAT_MONO160x1101;
289 for(i = 0; i < datalen; i += 4)
290 {
291 fcur = (SGfloat*)&bdata[i];
292 scur = (SGshort*)&bdata[i / 4 * 2];
293 *scur = (SGshort)(*fcur * 0xFFFF);
294 }
295 datalen = datalen / 4 * 2;
296 break;
297 case SG_AUDIO_FORMAT_D0x0B:
298 alformat = AL_FORMAT_MONO160x1101;
299 for(i = 0; i < datalen; i += 8)
300 {
301 dcur = (SGdouble*)&bdata[i];
302 scur = (SGshort*)&bdata[i / 8 * 2];
303 *scur = (SGshort)(*dcur * 0xFFFF);
304 }
305 datalen = datalen / 8 * 2;
306 break;
307 default:
308 return; // ERROR
309 }
310 void* odata = toStereo(channels, data, &datalen, &alformat);
311 alBufferData(ALBUF(buffer)(*(ALuint*)(buffer)->handle), alformat, odata, datalen, frequency);
312 if(data != odata)
313 free(odata);
314}