/* File: fuzzerfidentify.cpp Copyright (C) 2018 Christophe GRENIER This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_TIME_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include "types.h" #include "common.h" #include "filegen.h" #include #include extern file_enable_t array_file_enable[]; extern file_check_list_t file_check_list; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { const size_t blocksize=65536; static unsigned char *buffer_start=NULL; static file_stat_t *file_stats=NULL; static char *filename=NULL; uint8_t *buffer; if(Size == 0) return 0; if(filename==NULL) { pid_t pid=getpid(); filename=(char *)MALLOC(64); sprintf(filename, "sample%u", pid); } if(file_stats==NULL) { /* Enable all file formats */ file_enable_t *file_enable; for(file_enable=array_file_enable;file_enable->file_hint!=NULL;file_enable++) file_enable->enable=1; file_stats=init_file_stats(array_file_enable); } if(buffer_start==NULL) { buffer_start=(unsigned char *)MALLOC(2*blocksize); } buffer=buffer_start+blocksize; memcpy(buffer, Data, (Size < blocksize ? Size : blocksize)); { struct td_list_head *tmpl; file_recovery_t file_recovery_new; file_recovery_t file_recovery; reset_file_recovery(&file_recovery); file_recovery.blocksize=blocksize; file_recovery_new.blocksize=blocksize; file_recovery_new.file_stat=NULL; td_list_for_each(tmpl, &file_check_list.list) { struct td_list_head *tmp; const file_check_list_t *pos=td_list_entry_const(tmpl, const file_check_list_t, list); if(pos->offset <= blocksize) { td_list_for_each(tmp, &pos->file_checks[buffer[pos->offset]].list) { const file_check_t *file_check=td_list_entry_const(tmp, const file_check_t, list); if((file_check->length==0 || (file_check->offset+file_check->length <=blocksize && memcmp(buffer + file_check->offset, file_check->value, file_check->length)==0)) && file_check->header_check(buffer, blocksize, 0, &file_recovery, &file_recovery_new)!=0) { file_recovery_new.file_stat=file_check->file_stat; break; } } } if(file_recovery_new.file_stat!=NULL) break; } #if 0 if( file_recovery_new.file_stat!=NULL && file_recovery_new.file_stat->file_hint!=NULL && file_recovery_new.file_check!=NULL) { FILE *out; file_recovery_new.file_size=Size; file_recovery_new.calculated_file_size=Size; out=fopen(filename, "wb"); fwrite(Data, Size, 1, out); file_recovery_new.handle=out; (file_recovery_new.file_check)(&file_recovery_new); fclose(out); // unlink(filename); } #endif } return 0; // Non-zero return values are reserved for future use. }