| 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 != NULL((void *)0)) { | |||
| 283 | free(read_org_size->data); | |||
| 284 | free(read_org_size); | |||
| 285 | } | |||
| 286 | if (read_data_size != NULL((void *)0)) { | |||
| 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 | } |