Bug Summary

File:c:\siege\siege/src/siege/graphics/atlas.c
Location:line 63, column 8
Description:Access to field 'reserved' results in a dereference of a null pointer (loaded from variable 'node')

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/graphics/atlas.h>
17#include <siege/graphics/draw.h>
18#include <siege/util/vector.h>
19
20#include <stdlib.h>
21#include <stdio.h>
22#include <math.h>
23
24static SGbool _sgAtlasNodeIsLeaf(SGAtlasNode* node)
25{
26 return !node->child[0] && !node->child[1];
27}
28static SGAtlasNode* _sgAtlasNodeCreate(SGushort x, SGushort y, SGushort w, SGushort h, size_t index)
29{
30 SGAtlasNode* node = malloc(sizeof(SGAtlasNode));
31 if(!node) return NULL((void*)0);
32
33 node->child[0] = NULL((void*)0);
34 node->child[1] = NULL((void*)0);
35
36 node->area.x = x;
37 node->area.y = y;
38 node->area.w = w;
39 node->area.h = h;
40 node->area.index = index;
41
42 node->reserved = SG_FALSE0;
43
44 return node;
45}
46static void _sgAtlasNodeDestroy(SGAtlasNode* node)
47{
48 if(!node) return;
49 _sgAtlasNodeDestroy(node->child[0]);
50 _sgAtlasNodeDestroy(node->child[1]);
51 free(node);
52}
53static SGAtlasNode* _sgAtlasNodeInsert(SGAtlasNode* node, SGushort w, SGushort h, size_t index)
54{
55 SGAtlasNode* nnode;
56 if(!_sgAtlasNodeIsLeaf(node))
7
Taking false branch
12
Taking false branch
18
Taking false branch
25
Taking false branch
57 {
58 nnode = _sgAtlasNodeInsert(node->child[0], w, h, index);
59 if(nnode) return nnode;
60
61 return _sgAtlasNodeInsert(node->child[1], w, h, index);
62 }
63 if(node->reserved) return NULL((void*)0);
8
Taking false branch
13
Taking false branch
19
Taking false branch
26
Access to field 'reserved' results in a dereference of a null pointer (loaded from variable 'node')
64 if(node->area.w < w || node->area.h < h) return NULL((void*)0);
9
Taking false branch
14
Taking false branch
20
Taking false branch
65 if(node->area.w == w && node->area.h == h)
66 {
67 node->reserved = SG_TRUE1;
68 return node;
69 }
70
71 SGushort dw = node->area.w - w;
72 SGushort dh = node->area.h - h;
73
74 if(dw > dh)
10
Taking false branch
15
Assuming 'dw' is <= 'dh'
16
Taking false branch
21
Assuming 'dw' is <= 'dh'
22
Taking false branch
75 {
76 node->child[0] = _sgAtlasNodeCreate(node->area.x , node->area.y, w, node->area.h, index);
77 node->child[1] = _sgAtlasNodeCreate(node->area.x + w, node->area.y, dw, node->area.h, index);
78 }
79 else
80 {
81 node->child[0] = _sgAtlasNodeCreate(node->area.x, node->area.y , node->area.w, h, index);
82 node->child[1] = _sgAtlasNodeCreate(node->area.x, node->area.y + h, node->area.w, dh, index);
83 }
84
85 return _sgAtlasNodeInsert(node->child[0], w, h, index);
11
Calling '_sgAtlasNodeInsert'
17
Calling '_sgAtlasNodeInsert'
23
Passing null pointer value via 1st parameter 'node'
24
Calling '_sgAtlasNodeInsert'
86}
87
88static void SG_CALL__cdecl _sgAtlasNodeDrawDBG(SGAtlasNode* node, float x, float y)
89{
90 if(!node) return;
91 _sgAtlasNodeDrawDBG(node->child[0], x, y);
92 _sgAtlasNodeDrawDBG(node->child[1], x, y);
93
94 /*sgDrawRectangleWH(node->x + x - BORDER, node->y + y - BORDER, node->w, BORDER, SG_TRUE);
95 sgDrawRectangleWH(node->x + x - BORDER, node->y + y - BORDER + node->h, node->w, BORDER, SG_TRUE);
96 sgDrawRectangleWH(node->x + x - BORDER, node->y + y - BORDER, BORDER, node->h, SG_TRUE);
97 sgDrawRectangleWH(node->x + x - BORDER + node->w, node->y + y - BORDER, BORDER, node->h, SG_TRUE);*/
98 sgDrawRectangleWH(node->area.x + x, node->area.y + y, node->area.w, node->area.h, SG_FALSE0);
99}
100
101static SGTexture* _sgAtlasAddTexture(SGAtlas* atlas, SGTexture* texture, SGbool owner)
102{
103 if(!texture) return NULL((void*)0);
104 atlas->textures = realloc(atlas->textures, (atlas->numtextures + 1) * sizeof(SGAtlasTexture));
105 atlas->textures[atlas->numtextures].texture = texture;
106 atlas->textures[atlas->numtextures].owner = owner;
107 atlas->textures[atlas->numtextures].root = _sgAtlasNodeCreate(0, 0, atlas->width, atlas->height, atlas->numtextures);
108 atlas->numtextures++;
109 return texture;
110}
111
112SGAtlas* SG_CALL__cdecl sgAtlasCreate(size_t width, size_t height, SGenum bpp)
113{
114 return sgAtlasCreateData(width, height, bpp, NULL((void*)0));
115}
116SGAtlas* SG_CALL__cdecl sgAtlasCreateData(size_t width, size_t height, SGenum bpp, void* data)
117{
118 SGAtlas* atlas = malloc(sizeof(SGAtlas));
119 if(!atlas) return NULL((void*)0);
120
121 atlas->width = width;
122 atlas->height = height;
123 atlas->bpp = bpp;
124 atlas->numtextures = 0;
125 atlas->textures = NULL((void*)0);
126
127 _sgAtlasAddTexture(atlas, sgTextureCreateData(width, height, bpp, data), SG_TRUE1);
128
129 return atlas;
130}
131SGAtlas* SG_CALL__cdecl sgAtlasCreateTexture(SGTexture* texture, SGbool owner)
132{
133 SGAtlas* atlas = sgAtlasCreate(sgTextureGetWidth(texture), sgTextureGetHeight(texture), sgTextureGetBPP(texture));
134 if(!atlas) return NULL((void*)0);
135
136 _sgAtlasAddTexture(atlas, texture, owner);
137
138 return atlas;
139}
140SGAtlas* SG_CALL__cdecl sgAtlasCreateFile(const char* fname)
141{
142 return sgAtlasCreateTexture(sgTextureCreateFile(fname), SG_TRUE1);
143}
144void SG_CALL__cdecl sgAtlasDestroy(SGAtlas* atlas)
145{
146 if(!atlas)
147 return;
148
149 size_t i;
150 for(i = 0; i < atlas->numtextures; i++)
151 {
152 if(atlas->textures[i].owner)
153 sgTextureDestroy(atlas->textures[i].texture);
154 _sgAtlasNodeDestroy(atlas->textures[i].root);
155 }
156 free(atlas->textures);
157 free(atlas);
158}
159
160SGAtlasArea* SG_CALL__cdecl sgAtlasAreaReserve(SGAtlas* atlas, size_t width, size_t height, SGbool overflow)
161{
162 if(width > atlas->width || height > atlas->height)
1
Taking false branch
163 return NULL((void*)0);
164
165 SGAtlasNode* node = _sgAtlasNodeInsert(atlas->textures[atlas->numtextures - 1].root, width, height, atlas->numtextures - 1);
166 if(node) return &node->area;
2
Assuming 'node' is null
3
Taking false branch
167
168 // no node, and we don't allow overflow
169 if(!overflow) return NULL((void*)0);
4
Assuming 'overflow' is not equal to 0
5
Taking false branch
170
171 _sgAtlasAddTexture(atlas, sgTextureCreateData(atlas->width, atlas->height, atlas->bpp, NULL((void*)0)), SG_TRUE1);
172 node = _sgAtlasNodeInsert(atlas->textures[atlas->numtextures - 1].root, width, height, atlas->numtextures - 1);
6
Calling '_sgAtlasNodeInsert'
173 if(node) return &node->area;
174
175 return NULL((void*)0);
176}
177void SG_CALL__cdecl sgAtlasAreaSetData(SGAtlas* atlas, SGAtlasArea* area, size_t width, size_t height, SGenum bpp, void* data)
178{
179 if(area->index >= atlas->numtextures)
180 return;
181 if(width > area->w || height > area->h)
182 return;
183 sgTextureSetSubData(atlas->textures[area->index].texture, area->x, area->y, width, height, bpp, data);
184}
185
186void SG_CALL__cdecl sgAtlasAreaDrawRads3f2f2f1f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float z, float xscale, float yscale, float xoffset, float yoffset, float angle)
187{
188 float s0, t0, s1, t1;
189 sgAtlasGetTexCoordsA(atlas, area, &s0, &t0, &s1, &t1);
190
191 // offset -> scale -> rotate -> translate
192 SGVec2 pos = sgVec2f(x, y);
193 SGVec2 p0, p1, p2, p3;
194 p0 = sgVec2f(-xoffset , -yoffset );
195 p1 = sgVec2f(-xoffset , -yoffset + area->h * yscale);
196 p2 = sgVec2f(-xoffset + area->w * xscale, -yoffset + area->h * yscale);
197 p3 = sgVec2f(-xoffset + area->w * xscale, -yoffset );
198
199 p0 = sgVec2RotateRads(p0, sgVec2AngleRads(p0) + angle);
200 p1 = sgVec2RotateRads(p1, sgVec2AngleRads(p1) + angle);
201 p2 = sgVec2RotateRads(p2, sgVec2AngleRads(p2) + angle);
202 p3 = sgVec2RotateRads(p3, sgVec2AngleRads(p3) + angle);
203
204 p0 = sgVec2Add(p0, pos);
205 p1 = sgVec2Add(p1, pos);
206 p2 = sgVec2Add(p2, pos);
207 p3 = sgVec2Add(p3, pos);
208
209 sgDrawBeginT(SG_QUADS0x0A, sgAtlasGetTextureA(atlas, area));
210 sgDrawTexCoord2f(s0, t0);
211 sgDrawVertex3f(p0.x, p0.y, z);
212 sgDrawTexCoord2f(s0, t1);
213 sgDrawVertex3f(p1.x, p1.y, z);
214 sgDrawTexCoord2f(s1, t1);
215 sgDrawVertex3f(p2.x, p3.y, z);
216 sgDrawTexCoord2f(s1, t0);
217 sgDrawVertex3f(p2.x, p3.y, z);
218 sgDrawEnd();
219}
220void SG_CALL__cdecl sgAtlasAreaDrawDegs3f2f2f1f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float z, float xscale, float yscale, float xoffset, float yoffset, float angle)
221{
222 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, x, y, z, xscale, yscale, xoffset, yoffset, angle * SG_PI3.14159265358979323846 / 180.0);
223}
224void SG_CALL__cdecl sgAtlasAreaDrawRads2f2f2f1f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float xscale, float yscale, float xoffset, float yoffset, float angle)
225{
226 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, x, y, 0.0, xscale, yscale, xoffset, yoffset, angle);
227}
228void SG_CALL__cdecl sgAtlasAreaDrawDegs2f2f2f1f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float xscale, float yscale, float xoffset, float yoffset, float angle)
229{
230 sgAtlasAreaDrawDegs3f2f2f1f(atlas, area, x, y, 0.0, xscale, yscale, xoffset, yoffset, angle);
231}
232void SG_CALL__cdecl sgAtlasAreaDrawRads3f2f1f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float z, float xscale, float yscale, float angle)
233{
234 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, x, y, z, xscale, yscale, 0.0, 0.0, angle);
235}
236void SG_CALL__cdecl sgAtlasAreaDrawDegs3f2f1f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float z, float xscale, float yscale, float angle)
237{
238 sgAtlasAreaDrawDegs3f2f2f1f(atlas, area, x, y, z, xscale, yscale, 0.0, 0.0, angle);
239}
240void SG_CALL__cdecl sgAtlasAreaDrawRads2f2f1f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float xscale, float yscale, float angle)
241{
242 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, x, y, 0.0, xscale, yscale, 0.0, 0.0, angle);
243}
244void SG_CALL__cdecl sgAtlasAreaDrawDegs2f2f1f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float xscale, float yscale, float angle)
245{
246 sgAtlasAreaDrawDegs3f2f2f1f(atlas, area, x, y, 0.0, xscale, yscale, 0.0, 0.0, angle);
247}
248void SG_CALL__cdecl sgAtlasAreaDrawRads3f1f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float z, float angle)
249{
250 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, x, y, z, 1.0, 1.0, 0.0, 0.0, angle);
251}
252void SG_CALL__cdecl sgAtlasAreaDrawDegs3f1f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float z, float angle)
253{
254 sgAtlasAreaDrawDegs3f2f2f1f(atlas, area, x, y, z, 1.0, 1.0, 0.0, 0.0, angle);
255}
256void SG_CALL__cdecl sgAtlasAreaDrawRads2f1f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float angle)
257{
258 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, x, y, 0.0, 1.0, 1.0, 0.0, 0.0, angle);
259}
260void SG_CALL__cdecl sgAtlasAreaDrawDegs2f1f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float angle)
261{
262 sgAtlasAreaDrawDegs3f2f2f1f(atlas, area, x, y, 0.0, 1.0, 1.0, 0.0, 0.0, angle);
263}
264void SG_CALL__cdecl sgAtlasAreaDraw3f2f2f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float z, float xscale, float yscale, float xoffset, float yoffset)
265{
266 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, x, y, z, xscale, yscale, xoffset, yoffset, 0.0);
267}
268void SG_CALL__cdecl sgAtlasAreaDraw2f2f2f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float xscale, float yscale, float xoffset, float yoffset)
269{
270 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, x, y, 0.0, xscale, yscale, xoffset, yoffset, 0.0);
271}
272void SG_CALL__cdecl sgAtlasAreaDraw3f2f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float z, float xscale, float yscale)
273{
274 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, x, y, z, xscale, yscale, 0.0, 0.0, 0.0);
275}
276void SG_CALL__cdecl sgAtlasAreaDraw2f2f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float xscale, float yscale)
277{
278 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, x, y, 0.0, xscale, yscale, 0.0, 0.0, 0.0);
279}
280void SG_CALL__cdecl sgAtlasAreaDraw3f(SGAtlas* atlas, SGAtlasArea* area, float x, float y, float z)
281{
282 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, x, y, z, 1.0, 1.0, 0.0, 0.0, 0.0);
283}
284void SG_CALL__cdecl sgAtlasAreaDraw2f(SGAtlas* atlas, SGAtlasArea* area, float x, float y)
285{
286 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, x, y, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0);
287}
288void SG_CALL__cdecl sgAtlasAreaDraw(SGAtlas* atlas, SGAtlasArea* area)
289{
290 sgAtlasAreaDrawRads3f2f2f1f(atlas, area, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0);
291}
292
293void SG_CALL__cdecl sgAtlasGetTexCoords4i(SGAtlas* atlas, SGint x, SGint y, SGint w, SGint h, float* s0, float* t0, float* s1, float* t1)
294{
295 *s0 = x / (float)atlas->width;
296 *t0 = y / (float)atlas->height;
297 *s1 = (x + w) / (float)atlas->width;
298 *t1 = (y + h) / (float)atlas->width;
299}
300void SG_CALL__cdecl sgAtlasGetTexCoordsA(SGAtlas* atlas, SGAtlasArea* area, float* s0, float* t0, float* s1, float* t1)
301{
302 sgAtlasGetTexCoords4i(atlas, area->x, area->y, area->w, area->h, s0, t0, s1, t1);
303}
304
305size_t SG_CALL__cdecl sgAtlasGetNumTextures(SGAtlas* atlas)
306{
307 return atlas->numtextures;
308}
309SGTexture* SG_CALL__cdecl sgAtlasGetTexture(SGAtlas* atlas, size_t index)
310{
311 if(index >= atlas->numtextures)
312 return NULL((void*)0);
313 return atlas->textures[index].texture;
314}
315SGTexture* SG_CALL__cdecl sgAtlasGetTextureA(SGAtlas* atlas, SGAtlasArea* area)
316{
317 return sgAtlasGetTexture(atlas, area->index);
318}
319
320void SG_CALL__cdecl sgAtlasGetSize(SGAtlas* atlas, size_t* width, size_t* height)
321{
322 if(width) *width = atlas->width;
323 if(height) *height = atlas->height;
324}
325size_t SG_CALL__cdecl sgAtlasGetWidth(SGAtlas* atlas)
326{
327 return atlas->width;
328}
329size_t SG_CALL__cdecl sgAtlasGetHeight(SGAtlas* atlas)
330{
331 return atlas->height;
332}
333
334void SG_CALL__cdecl sgAtlasDrawDBG(SGAtlas* atlas, float x, float y, size_t index, SGbool wires)
335{
336 if(index > atlas->numtextures)
337 {
338 sgDrawRectangleWH(x, y, atlas->width, atlas->height, SG_FALSE0);
339 return;
340 }
341 if(wires)
342 _sgAtlasNodeDrawDBG(atlas->textures[index].root, x, y);
343 else
344 sgTextureDraw2f(atlas->textures[index].texture, x, y);
345}