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