Skip to content

Commit d72b7f9

Browse files
committed
Fix several bugs
There's a total of 12 bugs fixed, among which are NULL dereferences, double-frees, buffer overflows, and memory leaks.
1 parent da1c9f6 commit d72b7f9

6 files changed

Lines changed: 64 additions & 37 deletions

File tree

src/decode.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,20 +136,27 @@ uint8_t* tmj_zlib_decompress(const uint8_t* data, size_t data_size, size_t* deco
136136
if (stream.avail_out != 0) {
137137
logmsg(TMJ_LOG_ERR, "Decode (zlib): No progress possible");
138138

139+
free(out);
140+
139141
return NULL;
140142
}
141143

142144
logmsg(TMJ_LOG_DEBUG, "Decode (zlib): Z_BUF_ERROR");
143145
case Z_OK:
144146
logmsg(TMJ_LOG_DEBUG, "Decode (zlib): inflate OK");
145147

146-
out = realloc(out, INFLATE_BLOCK_SIZE * realloc_scale);
147-
if (out == NULL) {
148+
void* tmp = realloc(out, INFLATE_BLOCK_SIZE * realloc_scale);
149+
150+
if (tmp == NULL) {
148151
logmsg(TMJ_LOG_ERR, "Decode (zlib): Unable to grow inflate output buffer, the system is out memory");
149152

153+
free(out);
154+
150155
return NULL;
151156
}
152157

158+
out = tmp;
159+
153160
stream.avail_out = INFLATE_BLOCK_SIZE;
154161

155162
stream.next_out = out + stream.total_out;
@@ -381,6 +388,10 @@ size_t b64_decode_size(const char* data) {
381388

382389
size_t len = strlen(data);
383390

391+
if (len == 0) {
392+
return 0;
393+
}
394+
384395
size_t ret = len / 4 * 3;
385396

386397
// Check to see if the last 2 characters are padding bytes
@@ -485,6 +496,13 @@ char* tmj_b64_encode(uint8_t* data, size_t size) {
485496

486497
size_t enc_size = b64_encoded_size(size);
487498
char* out = malloc(enc_size + 1);
499+
500+
if (out == NULL) {
501+
logmsg(TMJ_LOG_ERR, "Encode (b64): Unable to allocate output buffer, the system is out of memory");
502+
503+
return NULL;
504+
}
505+
488506
out[enc_size] = '\0';
489507

490508
for (size_t i = 0, j = 0; i < size; i += 3, j += 4) {

src/map.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Property* unpack_properties(json_t* properties) {
4242
int unpk = json_unpack_ex(property,
4343
&error,
4444
0,
45-
"{s:s, s?s, s?s, s:o}",
45+
"{s:s, s:s, s?s, s:o}",
4646
"name",
4747
&ret[idx].name,
4848
"type",
@@ -60,8 +60,7 @@ Property* unpack_properties(json_t* properties) {
6060
return NULL;
6161
}
6262

63-
// note: string is default type, so missing field means string
64-
if (ret[idx].type == NULL || strcmp(ret[idx].type, "string") == 0) {
63+
if (strcmp(ret[idx].type, "string") == 0) {
6564
unpk = json_unpack_ex(value, &error, 0, "s", &ret[idx].value_string);
6665

6766
if (unpk == -1) {
@@ -86,7 +85,7 @@ Property* unpack_properties(json_t* properties) {
8685
}
8786

8887
if (strcmp(ret[idx].type, "float") == 0) {
89-
unpk = json_unpack_ex(value, &error, 0, "i", &ret[idx].value_float);
88+
unpk = json_unpack_ex(value, &error, 0, "F", &ret[idx].value_float);
9089

9190
if (unpk == -1) {
9291
logmsg(TMJ_LOG_ERR, "Unable to unpack float value from property, %s at line %d column %d", error.text, error.line, error.column);
@@ -260,6 +259,8 @@ Object* unpack_objects(json_t* objects) {
260259

261260
if (!json_is_array(objects)) {
262261
logmsg(TMJ_LOG_ERR, "'objects' must be an array");
262+
263+
return NULL;
263264
}
264265

265266
json_error_t error;
@@ -332,6 +333,8 @@ Object* unpack_objects(json_t* objects) {
332333
if (unpk == -1) {
333334
logmsg(TMJ_LOG_ERR, "Unable to unpack object, %s at line %d column %d", error.text, error.line, error.column);
334335

336+
free(ret);
337+
335338
return NULL;
336339
}
337340

@@ -1077,14 +1080,14 @@ Map* map_load_json(json_t* root, const char* path) {
10771080
goto fail_tilesets;
10781081
}
10791082
}
1080-
1081-
map->tileset_count = tileset_count;
10821083
}
10831084

1085+
map->tileset_count = tileset_count;
1086+
10841087
return map;
10851088

10861089
fail_tilesets:
1087-
tilesets_free(map->tilesets, map->tileset_count);
1090+
tilesets_free(map->tilesets, idx);
10881091

10891092
fail_layers:
10901093
layers_free(map->layers, map->layer_count);

src/tileset.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ int unpack_tileset(json_t* tileset, Tileset* ret) {
151151
"{s:b, s:b, s:b, s:b}",
152152
"hflip",
153153
&ret->transformations->hflip,
154-
"vfilp",
154+
"vflip",
155155
&ret->transformations->vflip,
156156
"rotate",
157157
&ret->transformations->rotate,
@@ -487,14 +487,25 @@ int unpack_tileset(json_t* tileset, Tileset* ret) {
487487
goto fail_tiles;
488488
}
489489

490+
if (json_array_size(terrain) > 4) {
491+
logmsg(TMJ_LOG_ERR,
492+
"Unable to unpack tileset[%s]->tiles[%d]->terrain, terrain cannot be more than 4 elements",
493+
ret->name,
494+
ret->tiles[idx].id);
495+
496+
goto fail_tiles;
497+
}
498+
490499
size_t idx2 = 0;
491500
json_t* terrain_idx = NULL;
492501

493502
json_array_foreach(terrain, idx2, terrain_idx) {
494503
if (!json_is_integer(terrain_idx)) {
495504
logmsg(TMJ_LOG_ERR,
496505
"Unable to unpack tileset[%s]->tiles[%d]->terrain, terrain must be an array of "
497-
"integers");
506+
"integers",
507+
ret->name,
508+
ret->tiles[idx].id);
498509

499510
goto fail_tiles;
500511
}

src/tmj.def

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,3 @@
11
EXPORTS
2-
tmj_map_loadf
3-
tmj_map_load
4-
tmj_tileset_loadf
5-
tmj_tileset_load
6-
tmj_map_free
7-
tmj_tileset_free
8-
tmj_log_regcb
9-
TMJ_VERSION_MAJOR
10-
TMJ_VERSION_MINOR
11-
TMJ_VERSION_PATCH
12-
TMJ_VERSION
13-
tmj_decode_layer
14-
tmj_zstd_decompress
15-
tmj_zlib_decompress
16-
tmj_zlib_compress
17-
tmj_b64_decode
18-
tmj_b64_encode
2+
tmj_map_loadf tmj_map_load tmj_tileset_loadf tmj_tileset_load tmj_map_free tmj_tileset_free tmj_log_regcb TMJ_VERSION_MAJOR TMJ_VERSION_MINOR
3+
TMJ_VERSION_PATCH TMJ_VERSION tmj_decode_layer tmj_zstd_decompress tmj_zlib_decompress tmj_zlib_compress tmj_b64_decode tmj_b64_encode

src/tmj.sym

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
2-
global:
3-
tmj_*;
4-
TMJ_*;
5-
local: *;
2+
global:
3+
tmj_*;
4+
TMJ_*;
5+
local:
6+
*;
67
};

src/util.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ uint32_t* tmj_decode_layer(const char* data, const char* encoding, const char* c
3333

3434
if (strlen(compression) == 0) {
3535
dat2 = malloc(dsize);
36+
37+
if (dat2 == NULL) {
38+
logmsg(TMJ_LOG_ERR, "Could not allocate buffer for decoded layer data, the system is out of memory");
39+
40+
goto fail;
41+
}
42+
3643
memcpy(dat2, dat, dsize);
3744
dsize2 = dsize;
3845
}
@@ -41,7 +48,7 @@ uint32_t* tmj_decode_layer(const char* data, const char* encoding, const char* c
4148
#ifndef LIBTMJ_ZLIB
4249
logmsg(TMJ_LOG_ERR, "Layer data encoded with %s, but libtmj was not compiled with %s support", compression, compression);
4350

44-
return NULL;
51+
goto fail;
4552
#endif
4653
// This ifdef is only here to shut up the compiler warnings
4754
#ifdef LIBTMJ_ZLIB
@@ -53,7 +60,7 @@ uint32_t* tmj_decode_layer(const char* data, const char* encoding, const char* c
5360
#ifndef LIBTMJ_ZSTD
5461
logmsg(TMJ_LOG_ERR, "Layer data encoded with zstd, but libtmj was not compiled with zstd support");
5562

56-
return NULL;
63+
goto fail;
5764
#endif
5865
#ifdef LIBTMJ_ZSTD
5966
dat2 = tmj_zstd_decompress(dat, dsize, &dsize2);
@@ -63,14 +70,16 @@ uint32_t* tmj_decode_layer(const char* data, const char* encoding, const char* c
6370
if (dat2 == NULL) {
6471
logmsg(TMJ_LOG_ERR, "Unable to decompress %s encoded layer data", compression);
6572

66-
free(dat);
67-
68-
return NULL;
73+
goto fail;
6974
}
7075

7176
free(dat);
7277

7378
*size = dsize2 / 4;
7479

7580
return (uint32_t*)dat2;
81+
82+
fail:
83+
free(dat);
84+
return NULL;
7685
}

0 commit comments

Comments
 (0)