File: | aol.c |
Location: | line 287, column 14 |
Description: | Use of memory after it is freed |
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 | ||||
14 | int 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; | |||
23 | error: | |||
24 | return -1; | |||
25 | } | |||
26 | ||||
27 | int 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; | |||
31 | error: | |||
32 | return -1; | |||
33 | } | |||
34 | ||||
35 | static inline void _serialize_time(struct tm *time, char *buf) { | |||
36 | strftime(buf, 21, "%FT%TZ", time); | |||
37 | } | |||
38 | ||||
39 | void _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 | ||||
62 | int 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; | |||
108 | error: | |||
109 | return -1; | |||
110 | } | |||
111 | ||||
112 | ol_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 | ||||
141 | error: | |||
142 | free(data->data); | |||
143 | free(data); | |||
144 | return NULL((void *)0); | |||
145 | } | |||
146 | ||||
147 | int 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))) { | |||
| ||||
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)) { | |||
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) { | |||
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;}; | |||
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) { | |||
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') { | |||
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); | |||
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 | ||||
262 | error: | |||
263 | ol_log_msg(LOG_ERR6, "Restore failed. Corrupt AOL?"); | |||
264 | ||||
265 | /* Free all the stuff */ | |||
266 | if (command != NULL((void *)0)) { | |||
267 | free(command->data); | |||
268 | free(command); | |||
269 | } | |||
270 | if (key != NULL((void *)0)) { | |||
271 | free(key->data); | |||
272 | free(key); | |||
273 | } | |||
274 | if (value != NULL((void *)0)) { | |||
275 | free(value->data); | |||
276 | free(value); | |||
277 | } | |||
278 | if (ct != NULL((void *)0)) { | |||
279 | free(ct->data); | |||
280 | free(ct); | |||
281 | } | |||
282 | if (read_org_size) { | |||
283 | free(read_org_size->data); | |||
284 | free(read_org_size); | |||
285 | } | |||
286 | if (read_data_size) { | |||
287 | free(read_data_size->data); | |||
| ||||
288 | free(read_data_size); | |||
289 | } | |||
290 | if (fd != NULL((void *)0)) { | |||
291 | fclose(fd); | |||
292 | } | |||
293 | ||||
294 | return -1; | |||
295 | } |