src/file_xm.c: Add Frama-C annotations
This commit is contained in:
parent
160350774f
commit
11180bcb60
1 changed files with 123 additions and 60 deletions
183
src/file_xm.c
183
src/file_xm.c
|
@ -34,187 +34,250 @@
|
||||||
#include "filegen.h"
|
#include "filegen.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
/*@ requires \valid(file_stat); */
|
||||||
static void register_header_check_xm(file_stat_t *file_stat);
|
static void register_header_check_xm(file_stat_t *file_stat);
|
||||||
|
|
||||||
const file_hint_t file_hint_xm= {
|
const file_hint_t file_hint_xm = {
|
||||||
.extension="xm",
|
.extension = "xm",
|
||||||
.description="FastTrackerII Extended Module",
|
.description = "FastTrackerII Extended Module",
|
||||||
.max_filesize=PHOTOREC_MAX_FILE_SIZE,
|
.max_filesize = PHOTOREC_MAX_FILE_SIZE,
|
||||||
.recover=1,
|
.recover = 1,
|
||||||
.enable_by_default=1,
|
.enable_by_default = 1,
|
||||||
.register_header_check=®ister_header_check_xm
|
.register_header_check = ®ister_header_check_xm
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
@ requires \valid(fr);
|
||||||
|
@ requires valid_file_recovery(fr);
|
||||||
|
@ requires \separated(fr, fr->handle, fr->extension, &errno, &Frama_C_entropy_source);
|
||||||
|
@ ensures \valid(fr->handle);
|
||||||
|
@ assigns *fr->handle, errno, fr->file_size;
|
||||||
|
@ assigns Frama_C_entropy_source;
|
||||||
|
@*/
|
||||||
static int parse_patterns(file_recovery_t *fr, uint16_t patterns)
|
static int parse_patterns(file_recovery_t *fr, uint16_t patterns)
|
||||||
{
|
{
|
||||||
for(; patterns!=0; patterns--)
|
/*@
|
||||||
|
@ loop assigns *fr->handle, errno, fr->file_size;
|
||||||
|
@ loop assigns Frama_C_entropy_source;
|
||||||
|
@ loop assigns patterns;
|
||||||
|
@*/
|
||||||
|
for(; patterns != 0; patterns--)
|
||||||
{
|
{
|
||||||
|
char buffer[sizeof(uint32_t)];
|
||||||
|
const uint16_t *p16 = (const uint16_t *)&buffer;
|
||||||
|
const uint32_t *p32 = (const uint32_t *)&buffer;
|
||||||
uint32_t header_size;
|
uint32_t header_size;
|
||||||
uint16_t data_size;
|
uint16_t data_size;
|
||||||
|
if(fread(&buffer, sizeof(uint32_t), 1, fr->handle) != 1)
|
||||||
if (fread(&header_size, 4, 1, fr->handle) != 1)
|
|
||||||
return -1;
|
return -1;
|
||||||
#if defined(__FRAMAC__)
|
#if defined(__FRAMAC__)
|
||||||
Frama_C_make_unknown(&header_size, sizeof(header_size));
|
Frama_C_make_unknown(&buffer, sizeof(uint32_t));
|
||||||
#endif
|
#endif
|
||||||
|
header_size = le32(*p32);
|
||||||
header_size = le32(header_size);
|
#ifndef __FRAMAC__
|
||||||
log_debug("xm: pattern header of size %u\n", (unsigned int)header_size);
|
log_debug("xm: pattern header of size %u\n", (unsigned int)header_size);
|
||||||
|
#endif
|
||||||
/* Never seen any xm having anything but 9 here */
|
/* Never seen any xm having anything but 9 here */
|
||||||
if (header_size != 9)
|
if(header_size != 9)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Packing type + row count skipped */
|
/* Packing type + row count skipped */
|
||||||
if (fseek(fr->handle, 1+2, SEEK_CUR) == -1)
|
if(fseek(fr->handle, 1 + 2, SEEK_CUR) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
if(fread(&buffer, sizeof(uint16_t), 1, fr->handle) != 1)
|
||||||
if (fread(&data_size, 2, 1, fr->handle) != 1)
|
|
||||||
return -1;
|
return -1;
|
||||||
#if defined(__FRAMAC__)
|
#if defined(__FRAMAC__)
|
||||||
Frama_C_make_unknown(&data_size, sizeof(data_size));
|
Frama_C_make_unknown(&buffer, sizeof(uint16_t));
|
||||||
#endif
|
#endif
|
||||||
data_size = le16(data_size);
|
data_size = le16(*p16);
|
||||||
|
#ifndef __FRAMAC__
|
||||||
log_debug("xm: pattern data of size %u\n", data_size);
|
log_debug("xm: pattern data of size %u\n", data_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (fseek(fr->handle, data_size, SEEK_CUR) == -1)
|
if(fseek(fr->handle, data_size, SEEK_CUR) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
fr->file_size += (uint64_t)header_size+data_size;
|
fr->file_size += (uint64_t)header_size + data_size;
|
||||||
if(fr->file_size > PHOTOREC_MAX_FILE_SIZE)
|
if(fr->file_size > PHOTOREC_MAX_FILE_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*@
|
||||||
|
@ requires \valid(fr);
|
||||||
|
@ requires valid_file_recovery(fr);
|
||||||
|
@ requires \separated(fr, fr->handle, fr->extension, &errno, &Frama_C_entropy_source);
|
||||||
|
@ ensures \valid(fr->handle);
|
||||||
|
@ assigns *fr->handle, errno, fr->file_size;
|
||||||
|
@ assigns Frama_C_entropy_source;
|
||||||
|
@*/
|
||||||
static int parse_instruments(file_recovery_t *fr, uint16_t instrs)
|
static int parse_instruments(file_recovery_t *fr, uint16_t instrs)
|
||||||
{
|
{
|
||||||
for(; instrs!=0; instrs--)
|
/*@
|
||||||
|
@ loop assigns *fr->handle, errno, fr->file_size;
|
||||||
|
@ loop assigns Frama_C_entropy_source;
|
||||||
|
@ loop assigns instrs;
|
||||||
|
@*/
|
||||||
|
for(; instrs != 0; instrs--)
|
||||||
{
|
{
|
||||||
|
char buffer[sizeof(uint32_t)];
|
||||||
|
const uint16_t *p16 = (const uint16_t *)&buffer;
|
||||||
|
const uint32_t *p32 = (const uint32_t *)&buffer;
|
||||||
uint16_t samples;
|
uint16_t samples;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
|
||||||
if (fread(&size, 4, 1, fr->handle) != 1)
|
if(fread(&buffer, sizeof(uint32_t), 1, fr->handle) != 1)
|
||||||
return -1;
|
return -1;
|
||||||
#if defined(__FRAMAC__)
|
#if defined(__FRAMAC__)
|
||||||
Frama_C_make_unknown(&size, sizeof(size));
|
Frama_C_make_unknown(&buffer, sizeof(uint32_t));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size = le32(size);
|
size = le32(*p32);
|
||||||
|
#ifndef __FRAMAC__
|
||||||
log_debug("xm: instrument header of size %u\n", (unsigned int)size);
|
log_debug("xm: instrument header of size %u\n", (unsigned int)size);
|
||||||
if (size < 29)
|
#endif
|
||||||
|
if(size < 29)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Fixed string + type skipped *
|
/* Fixed string + type skipped *
|
||||||
* @todo Verify that fixed string is ASCII ? */
|
* @todo Verify that fixed string is ASCII ? */
|
||||||
if (fseek(fr->handle, 22+1, SEEK_CUR) == -1)
|
if(fseek(fr->handle, 22 + 1, SEEK_CUR) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (fread(&samples, 2, 1, fr->handle) != 1)
|
if(fread(&buffer, sizeof(uint16_t), 1, fr->handle) != 1)
|
||||||
return -1;
|
return -1;
|
||||||
#if defined(__FRAMAC__)
|
#if defined(__FRAMAC__)
|
||||||
Frama_C_make_unknown(&samples, sizeof(samples));
|
Frama_C_make_unknown(&buffer, sizeof(uint16_t));
|
||||||
#endif
|
#endif
|
||||||
samples = le16(samples);
|
samples = le16(*p16);
|
||||||
|
#ifndef __FRAMAC__
|
||||||
log_debug("xm: instrument with %u samples\n", samples);
|
log_debug("xm: instrument with %u samples\n", samples);
|
||||||
|
#endif
|
||||||
|
|
||||||
fr->file_size += size;
|
fr->file_size += size;
|
||||||
if(fr->file_size > PHOTOREC_MAX_FILE_SIZE)
|
if(fr->file_size > PHOTOREC_MAX_FILE_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
/* Never seen any xm having anything but 263 when there are samples */
|
/* Never seen any xm having anything but 263 when there are samples */
|
||||||
if (samples>0)
|
if(samples > 0)
|
||||||
{
|
{
|
||||||
if (size!=263)
|
if(size != 263)
|
||||||
{
|
{
|
||||||
|
#ifndef __FRAMAC__
|
||||||
log_debug("xm: UNEXPECTED HEADER SIZE OF %u, "
|
log_debug("xm: UNEXPECTED HEADER SIZE OF %u, "
|
||||||
" PLEASE REPORT THE FILE!\n", (unsigned int)size);
|
" PLEASE REPORT THE FILE!\n",
|
||||||
|
(unsigned int)size);
|
||||||
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2ndary header skipped */
|
/* 2ndary header skipped */
|
||||||
if (fseek(fr->handle, 234, SEEK_CUR) == -1)
|
if(fseek(fr->handle, 234, SEEK_CUR) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/*@ loop assigns samples, size, *fr->handle, errno, Frama_C_entropy_source, fr->file_size, buffer[0..3]; */
|
||||||
for(; samples!=0; samples--)
|
for(; samples != 0; samples--)
|
||||||
{
|
{
|
||||||
if (fread(&size, 4, 1, fr->handle) != 1)
|
if(fread(&buffer, sizeof(uint32_t), 1, fr->handle) != 1)
|
||||||
return -1;
|
return -1;
|
||||||
#if defined(__FRAMAC__)
|
#if defined(__FRAMAC__)
|
||||||
Frama_C_make_unknown(&size, sizeof(size));
|
Frama_C_make_unknown(&buffer, sizeof(uint32_t));
|
||||||
#endif
|
#endif
|
||||||
size = le32(size);
|
size = le32(*p32);
|
||||||
|
#ifndef __FRAMAC__
|
||||||
log_debug("xm: sample with length of %u\n", (unsigned int)size);
|
log_debug("xm: sample with length of %u\n", (unsigned int)size);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Skip remaining of sample header *
|
/* Skip remaining of sample header *
|
||||||
* @todo Verify that last 22 bytes are ASCII? */
|
* @todo Verify that last 22 bytes are ASCII? */
|
||||||
if (fseek(fr->handle, (uint64_t)36+size, SEEK_CUR) == -1)
|
if(fseek(fr->handle, (uint64_t)36 + size, SEEK_CUR) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
fr->file_size += (uint64_t)40+size;
|
fr->file_size += (uint64_t)40 + size;
|
||||||
if(fr->file_size > PHOTOREC_MAX_FILE_SIZE)
|
if(fr->file_size > PHOTOREC_MAX_FILE_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* No sample, account for garbage */
|
/* No sample, account for garbage */
|
||||||
else if (fseek(fr->handle, size-29, SEEK_CUR) == -1)
|
else if(fseek(fr->handle, size - 29, SEEK_CUR) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*@
|
||||||
|
@ requires \valid(fr);
|
||||||
|
@ requires valid_file_recovery(fr);
|
||||||
|
@ requires \separated(fr, fr->handle, fr->extension, &errno, &Frama_C_entropy_source);
|
||||||
|
@ requires fr->file_check == &file_check_xm;
|
||||||
|
@ ensures \valid(fr->handle);
|
||||||
|
@ assigns *fr->handle, errno, fr->file_size;
|
||||||
|
@ assigns Frama_C_entropy_source;
|
||||||
|
@*/
|
||||||
static void file_check_xm(file_recovery_t *fr)
|
static void file_check_xm(file_recovery_t *fr)
|
||||||
{
|
{
|
||||||
uint16_t patterns, instrs;
|
uint16_t patterns, instrs;
|
||||||
|
|
||||||
fr->file_size = 0;
|
fr->file_size = 0;
|
||||||
fr->offset_error=0;
|
fr->offset_error = 0;
|
||||||
fr->offset_ok=0;
|
fr->offset_ok = 0;
|
||||||
|
|
||||||
if (fseek(fr->handle, 70, SEEK_SET) == -1)
|
if(fseek(fr->handle, 70, SEEK_SET) == -1)
|
||||||
return;
|
return;
|
||||||
if (fread(&patterns, 2, 1, fr->handle) != 1)
|
if(fread(&patterns, 2, 1, fr->handle) != 1)
|
||||||
return;
|
return;
|
||||||
if (fread(&instrs, 2, 1, fr->handle) != 1)
|
if(fread(&instrs, 2, 1, fr->handle) != 1)
|
||||||
return;
|
return;
|
||||||
#if defined(__FRAMAC__)
|
#if defined(__FRAMAC__)
|
||||||
Frama_C_make_unknown(&patterns, sizeof(patterns));
|
Frama_C_make_unknown(&patterns, sizeof(patterns));
|
||||||
Frama_C_make_unknown(&instrs, sizeof(instrs));
|
Frama_C_make_unknown(&instrs, sizeof(instrs));
|
||||||
#endif
|
#endif
|
||||||
instrs = le16(instrs);
|
instrs = le16(instrs);
|
||||||
patterns = le16(patterns);
|
patterns = le16(patterns);
|
||||||
|
|
||||||
|
#ifndef __FRAMAC__
|
||||||
log_debug("xm: %u patterns, %u instruments\n", patterns, instrs);
|
log_debug("xm: %u patterns, %u instruments\n", patterns, instrs);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Skip flags + tempo + bmp + table */
|
/* Skip flags + tempo + bmp + table */
|
||||||
if (fseek(fr->handle, 2+2+2+256, SEEK_CUR) == -1)
|
if(fseek(fr->handle, 2 + 2 + 2 + 256, SEEK_CUR) == -1)
|
||||||
return;
|
return;
|
||||||
fr->file_size = 336;
|
fr->file_size = 336;
|
||||||
|
|
||||||
/* Parse patterns and next instruments */
|
/* Parse patterns and next instruments */
|
||||||
if (parse_patterns(fr, patterns) < 0 ||
|
if(parse_patterns(fr, patterns) < 0 || parse_instruments(fr, instrs) < 0)
|
||||||
parse_instruments(fr, instrs) < 0)
|
|
||||||
{
|
{
|
||||||
|
#ifndef __FRAMAC__
|
||||||
log_debug("xm: lost sync at pos %li\n", ftell(fr->handle));
|
log_debug("xm: lost sync at pos %li\n", ftell(fr->handle));
|
||||||
|
#endif
|
||||||
fr->offset_error = fr->file_size;
|
fr->offset_error = fr->file_size;
|
||||||
fr->file_size = 0;
|
fr->file_size = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ModPlug may insert additional data but it is of little relevance */
|
/* ModPlug may insert additional data but it is of little relevance */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*@
|
||||||
|
@ requires buffer_size > 0;
|
||||||
|
@ requires \valid_read(buffer+(0..buffer_size-1));
|
||||||
|
@ requires valid_file_recovery(file_recovery);
|
||||||
|
@ requires \valid(file_recovery_new);
|
||||||
|
@ requires file_recovery_new->blocksize > 0;
|
||||||
|
@ requires separation: \separated(&file_hint_xm, buffer+(..), file_recovery, file_recovery_new);
|
||||||
|
@ ensures \result!=0 ==> valid_file_recovery(file_recovery_new);
|
||||||
|
@ assigns *file_recovery_new;
|
||||||
|
@*/
|
||||||
static int header_check_xm(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
|
static int header_check_xm(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
|
||||||
{
|
{
|
||||||
reset_file_recovery(file_recovery_new);
|
reset_file_recovery(file_recovery_new);
|
||||||
file_recovery_new->extension=file_hint_xm.extension;
|
file_recovery_new->extension = file_hint_xm.extension;
|
||||||
file_recovery_new->min_filesize=336 + 29; /* Header + 1 instrument */
|
file_recovery_new->min_filesize = 336 + 29; /* Header + 1 instrument */
|
||||||
file_recovery_new->file_check=&file_check_xm;
|
file_recovery_new->file_check = &file_check_xm;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void register_header_check_xm(file_stat_t *file_stat)
|
static void register_header_check_xm(file_stat_t *file_stat)
|
||||||
{
|
{
|
||||||
static const unsigned char xm_header[17] = { 'E','x','t','e','n','d','e','d',' ','M','o','d','u','l','e',':',' '};
|
static const unsigned char xm_header[17] = { 'E', 'x', 't', 'e', 'n', 'd', 'e', 'd', ' ', 'M', 'o', 'd', 'u', 'l', 'e', ':', ' ' };
|
||||||
register_header_check(0, xm_header,sizeof(xm_header), &header_check_xm, file_stat);
|
register_header_check(0, xm_header, sizeof(xm_header), &header_check_xm, file_stat);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue