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 | } |