@ @ requires \valid(f); @ requires 0 < size <= 4096; @ requires \valid_read((const char *)needle + (0 .. size-1)); @ requires \separated(f, (const char *)needle+(..), &errno, &Frama_C_entropy_source); @ assigns *f,errno; @ assigns Frama_C_entropy_source; @*/
| 200 | @ assigns Frama_C_entropy_source; |
| 201 | @*/ |
| 202 | static int64_t file_get_pos(FILE *f, const void* needle, const unsigned int size) |
| 203 | { |
| 204 | char buffer[4096]; |
| 205 | int64_t total = 0; |
| 206 | #ifdef DEBUG_ZIP |
| 207 | log_trace("zip: file_get_pos(f, needle, %u)\n", size); |
| 208 | #endif |
| 209 | |
| 210 | /*@ |
| 211 | @ loop assigns total, *f, errno, buffer[0..4096-1]; |
| 212 | @ loop assigns Frama_C_entropy_source; |
| 213 | @*/ |
| 214 | while (!feof(f)) |
| 215 | { |
| 216 | const size_t read_size=fread(&buffer, 1, 4096, f); |
| 217 | if(read_size <= 0 || total > (0x7fffffffffffffff - 4096)) |
| 218 | { |
| 219 | return -1; |
| 220 | } |
| 221 | /*@ assert 0 < read_size <= 4096; */ |
| 222 | /*@ assert total <= 0x8000000000000000 - 4096; */ |
| 223 | #if defined(__FRAMAC__) |
| 224 | Frama_C_make_unknown(&buffer, 4096); |
| 225 | #endif |
| 226 | if(read_size >= size) |
| 227 | { |
| 228 | /*@ assert read_size >= size; */ |
| 229 | const unsigned int count_max=read_size - size; |
| 230 | unsigned int count = 0; |
| 231 | // TODO loop invariant 0 <= count <= count_max + 1; |
| 232 | /*@ |
| 233 | @ loop assigns count, *f, errno; |
| 234 | @ loop variant count_max - count; |
| 235 | @*/ |
| 236 | for(count=0; count <= count_max; count++) |
| 237 | { |
| 238 | /*@ assert count <= count_max; */ |
| 239 | if (buffer[count]==*(const char *)needle && memcmp(buffer+count, needle, size)==0) |
| 240 | { |
| 241 | if(my_fseek(f, (off_t)count-(off_t)read_size, SEEK_CUR)<0) |
| 242 | { |
| 243 | #if !defined(DISABLED_FOR_FRAMAC) |
| 244 | log_trace("zip: file_get_pos count-read failed\n"); |
| 245 | #endif |
| 246 | return -1; |
| 247 | } |
| 248 | return total+count; |
| 249 | } |
| 250 | } |
| 251 | total+=count_max+1; |
| 252 | } |
| 253 | if(feof(f) || my_fseek(f, (off_t)1-size, SEEK_CUR)<0) |
| 254 | { |
| 255 | #if !defined(DISABLED_FOR_FRAMAC) |
| 256 | log_trace("zip: file_get_pos 1-size failed\n"); |
| 257 | #endif |
| 258 | return -1; |
| 259 | } |
no test coverage detected