Bug Summary

File:aol.c
Location:line 287, column 14
Description:Use of memory after it is freed

Annotated Source Code

1#include "aol.h"
2#include "data.h"
3#include "oleg.h"
4#include "logging.h"
5#include "errhandle.h"
6#include "lz4.h"
7
8#include <stdio.h>
9#include <unistd.h>
10#include <fcntl.h>
11#include <stdlib.h>
12#include <time.h>
13
14int ol_aol_init(ol_database *db) {
15 if (db->is_enabled(OL_F_APPENDONLY, &db->feature_set)) {
16 debug("Opening append only log");
17 debug("Append only log: %s", db->aol_file);
18 db->aolfd = fopen(db->aol_file, "ab+");
19 check(db->aolfd != NULL, "Error opening append only file")if(!(db->aolfd != ((void *)0))){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Error opening append only file" "\n", "src/aol.c",19,((* __error
()) == 0 ? "None" : strerror((* __error())))); (* __error())=
0; goto error;}
;
20 }
21
22 return 0;
23error:
24 return -1;
25}
26
27int ol_aol_fsync(FILE *fd) {
28 check(fflush(fd) == 0, "Could not fflush.")if(!(fflush(fd) == 0)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Could not fflush." "\n", "src/aol.c",28,((* __error()) == 0
? "None" : strerror((* __error())))); (* __error())=0; goto error
;}
;
29 check(fsync(fileno(fd)) == 0, "Could not fsync")if(!(fsync((!__isthreaded ? ((fd)->_file) : (fileno)(fd)))
== 0)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) " "Could not fsync"
"\n", "src/aol.c",29,((* __error()) == 0 ? "None" : strerror
((* __error())))); (* __error())=0; goto error;}
;
30 return 0;
31error:
32 return -1;
33}
34
35static inline void _serialize_time(struct tm *time, char *buf) {
36 strftime(buf, 21, "%FT%TZ", time);
37}
38
39void _deserialize_time(struct tm *fillout, char *buf) {
40 /* Example 8601 datestamp: 2014-03-08T11:17:39Z */
41 char year[4]={0}, month[2]={0}, day[2]={0};
42 char hour[2]={0}, min[2]={0}, sec[2]={0};
43
44 memcpy(&year, &buf, 4);
45 memcpy(&month, &buf[5], 2);
46 memcpy(&day, &buf[8], 2);
47
48 memcpy(&hour, &buf[11], 2);
49 memcpy(&min, &buf[14], 2);
50 memcpy(&sec, &buf[17], 2);
51
52 memset(fillout, '\0', sizeof(struct tm));
53 fillout->tm_year = strtol(year, NULL((void *)0), 10) - 1900;
54 fillout->tm_mon = strtol(month, NULL((void *)0), 10) - 1;
55 fillout->tm_mday = strtol(day, NULL((void *)0), 10);
56
57 fillout->tm_hour = strtol(hour, NULL((void *)0), 10);
58 fillout->tm_min = strtol(min, NULL((void *)0), 10);
59 fillout->tm_sec = strtol(sec, NULL((void *)0), 10);
60}
61
62int ol_aol_write_cmd(ol_database *db, const char *cmd, ol_bucket *bct) {
63 int ret;
64
65 if (strncmp(cmd, "JAR", 3) == 0) {
66 /* I'LL RIGOR YER MORTIS */
67 debug("Writing: \"%.*s\"", (int)bct->klen, bct->key);
68 char aol_str[] =
69 ":%zu:%s:" /* cmd length, cmd */
70 "%zu:%.*s:" /* klen size, key */
71 "%zu:%.*s:" /* ctype size, content_type */
72 "%zu:%0*i:" /* sizeof(original_size), original_size */
73 "%zu:%0*i:" /* sizeof(size_t), data_size */
74 "%zu:%0*i"; /* sizeof(size_t), offset into file */
75 ret = fprintf(db->aolfd, aol_str,
76 strlen(cmd), cmd,
77 bct->klen, (int)bct->klen, bct->key,
78 bct->ctype_size, (int)bct->ctype_size, bct->content_type,
79 sizeof(size_t), (int)sizeof(size_t), bct->original_size,
80 sizeof(size_t), (int)sizeof(size_t), bct->data_size,
81 sizeof(size_t), (int)sizeof(size_t), bct->data_offset);
82 check(ret > -1, "Error writing to file.")if(!(ret > -1)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Error writing to file." "\n", "src/aol.c",82,((* __error())
== 0 ? "None" : strerror((* __error())))); (* __error())=0; goto
error;}
;
83 ret = fprintf(db->aolfd, "\n");
84 } else if (strncmp(cmd, "SCOOP", 5) == 0) {
85 ret = fprintf(db->aolfd, ":%zu:%s:%zu:%s\n",
86 strlen(cmd), cmd,
87 bct->klen, bct->key);
88 check(ret > -1, "Error writing to file.")if(!(ret > -1)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Error writing to file." "\n", "src/aol.c",88,((* __error())
== 0 ? "None" : strerror((* __error())))); (* __error())=0; goto
error;}
;
89 } else if (strncmp(cmd, "SPOIL", 5) == 0) {
90 char exptime[21] = {'\0'};
91 _serialize_time(bct->expiration, exptime);
92
93 ret = fprintf(db->aolfd, ":%zu:%s:%zu:%s:%zu:%*s\n",
94 strlen(cmd), cmd,
95 bct->klen, bct->key,
96 strlen(exptime), 20, exptime);
97 check(ret > -1, "Error writing to file.")if(!(ret > -1)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Error writing to file." "\n", "src/aol.c",97,((* __error())
== 0 ? "None" : strerror((* __error())))); (* __error())=0; goto
error;}
;
98 } else {
99 ol_log_msg(LOG_ERR6, "No such command '%s'", cmd);
100 return -1;
101 }
102
103 check(ret > -1, "Error writing to file.")if(!(ret > -1)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Error writing to file." "\n", "src/aol.c",103,((* __error()
) == 0 ? "None" : strerror((* __error())))); (* __error())=0;
goto error;}
;
104
105 /* Force the OS to flush write to hardware */
106 check(ol_aol_fsync(db->aolfd) == 0, "Could not fsync. Panic!")if(!(ol_aol_fsync(db->aolfd) == 0)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Could not fsync. Panic!" "\n", "src/aol.c",106,((* __error(
)) == 0 ? "None" : strerror((* __error())))); (* __error())=0
; goto error;}
;
107 return 0;
108error:
109 return -1;
110}
111
112ol_string *_ol_read_data(FILE *fd) {
113 int c;
114 char buf[20] = {0};
115 ol_string *data = calloc(1, sizeof(ol_string));
116
117 c = fgetc(fd);
118 if (c == ':'){
119 int i = 0;
120 size_t l = 0;
121 while ((c = fgetc(fd)) != ':') {
122 buf[i] = '\0';
123 buf[i] = c;
124 i++;
125 }
126 buf[i + 1] = '\0';
127 l = (size_t)strtol(buf, NULL((void *)0), 10);
128 data->data = calloc(1, l);
129 check(fread(data->data, l, 1, fd) != 0, "Error reading")if(!(fread(data->data, l, 1, fd) != 0)){fprintf(__stderrp,
"[ERROR] (%s:%d: errno: %s) " "Error reading" "\n", "src/aol.c"
,129,((* __error()) == 0 ? "None" : strerror((* __error()))))
; (* __error())=0; goto error;}
;
130 data->dlen = l;
131 return data;
132 } else if (c == EOF(-1)) {
133 data->dlen = 0;
134 data->data = NULL((void *)0);
135 return data; /* A NULL ol_string means EOF was reached */
136 }
137
138 free(data);
139 return NULL((void *)0);
140
141error:
142 free(data->data);
143 free(data);
144 return NULL((void *)0);
145}
146
147int ol_aol_restore(ol_database *db) {
148 char c[1];
149 FILE *fd = NULL((void *)0);
150 ol_string *command = NULL((void *)0),
151 *key = NULL((void *)0),
152 *value = NULL((void *)0),
153 *ct = NULL((void *)0),
154 *read_data_size = NULL((void *)0),
155 *read_org_size = NULL((void *)0);
156 fd = fopen(db->aol_file, "r");
157 check(fd, "Error opening file")if(!(fd)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) " "Error opening file"
"\n", "src/aol.c",157,((* __error()) == 0 ? "None" : strerror
((* __error())))); (* __error())=0; goto error;}
;
158 while (!feof(fd)(!__isthreaded ? (((fd)->_flags & 0x0020) != 0) : (feof
)(fd))
) {
1
Loop condition is true. Entering loop body
159 command = _ol_read_data(fd);
160 check(command, "Error reading")if(!(command)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Error reading" "\n", "src/aol.c",160,((* __error()) == 0 ? "None"
: strerror((* __error())))); (* __error())=0; goto error;}
;
161
162 /* Kind of a hack to check for EOF. If the struct is blank, then we
163 * read past EOF in _ol_read_data. feof is rarely useful I guess... */
164 if (command->data == NULL((void *)0)) {
2
Taking false branch
165 free(command);
166 break;
167 }
168
169 key = _ol_read_data(fd);
170 check(key, "Error reading")if(!(key)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) " "Error reading"
"\n", "src/aol.c",170,((* __error()) == 0 ? "None" : strerror
((* __error())))); (* __error())=0; goto error;}
; /* Everything needs a key */
171
172 if (strncmp(command->data, "JAR", 3) == 0) {
3
Taking true branch
173 ct = _ol_read_data(fd);
174 check(ct, "Error reading")if(!(ct)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) " "Error reading"
"\n", "src/aol.c",174,((* __error()) == 0 ? "None" : strerror
((* __error())))); (* __error())=0; goto error;}
;
175
176 read_org_size = _ol_read_data(fd);
177 check(read_org_size, "Error reading")if(!(read_org_size)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Error reading" "\n", "src/aol.c",177,((* __error()) == 0 ? "None"
: strerror((* __error())))); (* __error())=0; goto error;}
;
178
179 read_data_size = _ol_read_data(fd);
180 check(read_data_size, "Error reading")if(!(read_data_size)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Error reading" "\n", "src/aol.c",180,((* __error()) == 0 ? "None"
: strerror((* __error())))); (* __error())=0; goto error;}
;
4
Within the expansion of the macro 'check':
a
Assuming 'read_data_size' is non-null
181
182 value = _ol_read_data(fd);
183 check(value, "Error reading")if(!(value)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) " "Error reading"
"\n", "src/aol.c",183,((* __error()) == 0 ? "None" : strerror
((* __error())))); (* __error())=0; goto error;}
;
184
185 size_t original_size = 0;
186 original_size = (size_t)strtol(read_org_size->data, NULL((void *)0), 10);
187
188 size_t current_size = 0;
189 current_size = (size_t)strtol(read_data_size->data, NULL((void *)0), 10);
190
191 size_t data_offset = 0;
192 data_offset = (size_t)strtol(value->data, NULL((void *)0), 10);
193
194 unsigned char *data_ptr = db->values + data_offset;
195
196 if (original_size != current_size) {
5
Taking false branch
197 /* Data is compressed, gotta deal with that. */
198 unsigned char tmp_data[original_size];
199 unsigned char *ret = memset(&tmp_data, 0, original_size);
200 check(ret == tmp_data, "Could not initialize tmp_data parameter.")if(!(ret == tmp_data)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Could not initialize tmp_data parameter." "\n", "src/aol.c"
,200,((* __error()) == 0 ? "None" : strerror((* __error()))))
; (* __error())=0; goto error;}
;
201
202 int processed = 0;
203 processed = LZ4_decompress_fast((const char*)data_ptr,
204 (char *)&tmp_data, original_size);
205 if (processed == current_size) {
206 ol_jar_ct(db, key->data, key->dlen, tmp_data, original_size,
207 ct->data, ct->dlen);
208 } else {
209 ol_log_msg(LOG_WARN3, "Could not decompress data. Data may have been previously deleted.");
210 }
211 } else {
212 /* Data is uncompressed, no need for trickery. */
213 if (data_ptr[0] != '\0') {
6
Taking false branch
214 ol_jar_ct(db, key->data, key->dlen, data_ptr, current_size,
215 ct->data, ct->dlen);
216 } else {
217 ol_log_msg(LOG_WARN3, "No data in values file that corresponds with this key. Deleted?");
218 }
219 }
220 free(read_org_size->data);
221 free(read_org_size);
222 free(read_data_size->data);
223 free(read_data_size);
7
Memory is released
224 free(ct->data);
225 free(ct);
226 free(value->data);
227 free(value);
228 read_org_size = NULL((void *)0);
229 ct = NULL((void *)0);
230 value = NULL((void *)0);
231 } else if (strncmp(command->data, "SCOOP", 5) == 0) {
232 ol_scoop(db, key->data, key->dlen);
233 } else if (strncmp(command->data, "SPOIL", 5) == 0) {
234 ol_string *spoil = NULL((void *)0);
235 spoil = _ol_read_data(fd);
236
237 struct tm time = {0};
238 _deserialize_time(&time, spoil->data);
239
240 check(spoil, "Error reading")if(!(spoil)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) " "Error reading"
"\n", "src/aol.c",240,((* __error()) == 0 ? "None" : strerror
((* __error())))); (* __error())=0; goto error;}
;
241 ol_spoil(db, key->data, key->dlen, &time);
242 free(spoil->data);
243 free(spoil);
244 spoil = NULL((void *)0);
245 }
246
247 /* Strip the newline char after each "record" */
248 check(fread(c, 1, 1, fd) != 0, "Error reading")if(!(fread(c, 1, 1, fd) != 0)){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Error reading" "\n", "src/aol.c",248,((* __error()) == 0 ? "None"
: strerror((* __error())))); (* __error())=0; goto error;}
;
249 check(*c == '\n', "Could not strip newline")if(!(*c == '\n')){fprintf(__stderrp,"[ERROR] (%s:%d: errno: %s) "
"Could not strip newline" "\n", "src/aol.c",249,((* __error(
)) == 0 ? "None" : strerror((* __error())))); (* __error())=0
; goto error;}
;
250
251 free(command->data);
252 free(command);
253 command = NULL((void *)0);
254 free(key->data);
255 free(key);
256 key = NULL((void *)0);
257 }
258 fclose(fd);
259 fd = NULL((void *)0);
260 return 0;
261
262error:
263 ol_log_msg(LOG_ERR6, "Restore failed. Corrupt AOL?");
264
265 /* Free all the stuff */
266 if (command != NULL((void *)0)) {
8
Taking true branch
267 free(command->data);
268 free(command);
269 }
270 if (key != NULL((void *)0)) {
9
Taking true branch
271 free(key->data);
272 free(key);
273 }
274 if (value != NULL((void *)0)) {
10
Taking false branch
275 free(value->data);
276 free(value);
277 }
278 if (ct != NULL((void *)0)) {
11
Taking false branch
279 free(ct->data);
280 free(ct);
281 }
282 if (read_org_size) {
12
Taking false branch
283 free(read_org_size->data);
284 free(read_org_size);
285 }
286 if (read_data_size) {
13
Taking true branch
287 free(read_data_size->data);
14
Use of memory after it is freed
288 free(read_data_size);
289 }
290 if (fd != NULL((void *)0)) {
291 fclose(fd);
292 }
293
294 return -1;
295}