├── examples ├── demo │ ├── input │ │ └── sample │ ├── Makefile │ ├── demo-app.c │ └── demo-app-posix.c └── libpng │ ├── README.md │ ├── libpng-nocrc.diff │ ├── build.sh │ ├── readpng.h │ ├── readpng.c │ ├── readpng-pers.c │ └── readpng-fiow.c ├── afl-fiow-stats.png ├── afl-pers-stats.png ├── Dockerfile ├── Makefile ├── libfiodef.h ├── Performance.md ├── README.md ├── LICENSE ├── libfioinfo.c └── libfiowrapper.c /examples/demo/input/sample: -------------------------------------------------------------------------------- 1 | fooxxx 2 | -------------------------------------------------------------------------------- /afl-fiow-stats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekzmyslowski/libfiowrapper/HEAD/afl-fiow-stats.png -------------------------------------------------------------------------------- /afl-pers-stats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekzmyslowski/libfiowrapper/HEAD/afl-pers-stats.png -------------------------------------------------------------------------------- /examples/libpng/README.md: -------------------------------------------------------------------------------- 1 | This is libpng example. 2 | 3 | ## Building 4 | The simple way is just to run the ```./build.sh``` script. It downloads libpng, applies patches, compiles and build the ```readpng.c``` application ready to fuzz. 5 | 6 | ``` 7 | export LD_LIBRARY_PATH= 8 | afl-fuzz -i ./input-png/ -o ./output -- ./readpng @@ 9 | ``` 10 | -------------------------------------------------------------------------------- /examples/libpng/libpng-nocrc.diff: -------------------------------------------------------------------------------- 1 | diff --git a/pngrutil.c b/pngrutil.c 2 | index 4db3de990..1868af672 100644 3 | --- a/pngrutil.c 4 | +++ b/pngrutil.c 5 | @@ -277,7 +277,7 @@ png_crc_error(png_structrp png_ptr) 6 | if (need_crc != 0) 7 | { 8 | crc = png_get_uint_32(crc_bytes); 9 | - return ((int)(crc != png_ptr->crc)); 10 | + return ((int)(1 != 1)); 11 | } 12 | 13 | else 14 | 15 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.10 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | 5 | RUN apt-get update && apt-get upgrade -y && \ 6 | apt-get -y install wget git cmake subversion build-essential libtool-bin python3-dev automake flex bison libglib2.0-dev libpixman-1-dev clang python3-setuptools llvm gcc-10-plugin-dev 7 | 8 | 9 | RUN mkdir /work 10 | WORKDIR /work 11 | RUN git clone https://github.com/AFLplusplus/AFLplusplus.git aflpp 12 | RUN cd aflpp && make && make install 13 | 14 | RUN git clone https://github.com/marekzmyslowski/libfiowrapper.git 15 | WORKDIR /work/libfiowrapper 16 | RUN make all 17 | 18 | -------------------------------------------------------------------------------- /examples/libpng/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Clone the libpng directory 4 | git clone https://git.code.sf.net/p/libpng/code libpng-code 5 | 6 | # Build libpng 7 | cd libpng-code 8 | git apply ../libpng-nocrc.diff 9 | mkdir afl-build 10 | cd afl-build 11 | CC=afl-clang-fast cmake .. 12 | make 13 | cd ../.. 14 | 15 | # Build harness files. 16 | afl-clang-fast readpng-fiow.c -o readpng-fiow ./libpng-code/afl-build/libpng16.a -lz -lm -L../../ -lfiowrapper -I./libpng-code/afl-build -I./libpng-code 17 | afl-clang-fast readpng-pers.c -o readpng-pers ./libpng-code/afl-build/libpng16.a -lz -lm -I./libpng-code/afl-build -I./libpng-code 18 | afl-clang-fast readpng.c -o readpng ./libpng-code/afl-build/libpng16.a -lz -lm -I./libpng-code/afl-build -I./libpng-code 19 | 20 | # Download corpus and reduce the file to size 10K 21 | svn export https://github.com/mozillasecurity/fuzzdata.git/trunk/samples/png input-png 22 | cd input-png 23 | mv ./chrome/* ./ 24 | mv ./common/* ./ 25 | rm -rf ./chrome 26 | rm -rf common 27 | find ./ -type f -size +10k | xargs rm -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | CC = clang 3 | CFLAGS = -ldl -fPIC -shared 4 | 5 | .PHONY: all debug demo examples help 6 | 7 | help: 8 | @echo '' 9 | @echo ' usage: make [target]' 10 | @echo '' 11 | @echo ' release - build release version of the libraries' 12 | @echo ' debug - build debug version of the libraries' 13 | @echo ' all - build everything (release, demo, example)' 14 | @echo ' demo - build demo applications' 15 | @echo ' examples - build example applications' 16 | @echo ' clean - clean libraries and demo applications' 17 | @echo '' 18 | 19 | all: release demo examples 20 | 21 | release: libfioinfo libfiowrapper 22 | release: CFLAGS += -O3 23 | 24 | debug: CFLAGS += -DDEBUG 25 | debug: libfioinfo libfiowrapper 26 | 27 | demo: 28 | $(MAKE) -C ./examples/demo 29 | 30 | examples: 31 | cd ./examples/libpng; ./build.sh 32 | 33 | libfioinfo: libfioinfo.c 34 | $(CC) $(CFLAGS) $? -o $@.so 35 | 36 | libfiowrapper: libfiowrapper.c 37 | $(CC) $(CFLAGS) $? -o $@.so 38 | 39 | clean: 40 | rm -f libfioinfo.so libfiowrapper.so 41 | $(MAKE) clean -C ./examples/demo -------------------------------------------------------------------------------- /examples/demo/Makefile: -------------------------------------------------------------------------------- 1 | CC := clang 2 | AFLCC := afl-clang-fast 3 | LDFLAGS := -L../../ -lfiowrapper 4 | 5 | all: info-demo file-fuzz-demo mem-fuzz-demo per-fuzz-demo info-demo-posix file-fuzz-demo-posix mem-fuzz-demo-posix per-fuzz-demo-posix 6 | .PHONE: all 7 | 8 | info-demo: demo-app.c 9 | $(CC) $(CFLAGS) $? -o $@ 10 | 11 | file-fuzz-demo: demo-app.c 12 | $(AFLCC) $(CFLAGS) $? -o $@ 13 | 14 | per-fuzz-demo: demo-app.c 15 | $(AFLCC) $(CFLAGS) $? -DAFL_PERSISTENT -o $@ 16 | 17 | mem-fuzz-demo: demo-app.c 18 | $(AFLCC) $(CFLAGS) $(LDFLAGS) $? -DAFL_MEMORY -o $@ 19 | 20 | info-demo-posix: demo-app-posix.c 21 | $(CC) $(CFLAGS) $? -o $@ 22 | 23 | file-fuzz-demo-posix: demo-app-posix.c 24 | $(AFLCC) $(CFLAGS) $? -o $@ 25 | 26 | per-fuzz-demo-posix: demo-app-posix.c 27 | $(AFLCC) $(CFLAGS) $? -DAFL_PERSISTENT -o $@ 28 | 29 | mem-fuzz-demo-posix: demo-app-posix.c 30 | $(AFLCC) $(CFLAGS) $(LDFLAGS) $? -DAFL_MEMORY -o $@ 31 | 32 | clean: 33 | rm -f info-demo file-fuzz-demo mem-fuzz-demo per-fuzz-demo info-demo-posix file-fuzz-demo-posix mem-fuzz-demo-posix per-fuzz-demo-posix -------------------------------------------------------------------------------- /libfiodef.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBFIODEF_H 2 | #define __LIBFIODEF_H 3 | 4 | #include 5 | #include 6 | 7 | /* 8 | * THe pointer definitions for the original functions that are hooked. 9 | */ 10 | 11 | // Standard stdio functions 12 | static FILE *(*_libc_fopen)(const char *path, const char *mode); 13 | 14 | static size_t (*_libc_fwrite)(const void *ptr, size_t size, size_t nmemb, FILE *stream); 15 | static int (*_libc_fputc)(int character, FILE *stream); 16 | static int (*_libc_fputs)(const char *str, FILE *stream); 17 | static size_t (*_libc_fread)(void *ptr, size_t size, size_t nmemb, FILE *stream); 18 | static int (*_libc_fgetc)(FILE *stream); 19 | static char *(*_libc_fgets)(char *str, int num, FILE *stream); 20 | 21 | static int (*_libc_fseek)(FILE *stream, long offset, int whence); 22 | static int (*_libc_fseeko)(FILE *stream, off_t offset, int whence); 23 | static int (*_libc_fseeko64)(FILE *stream, off64_t offset, int whence); 24 | 25 | static long (*_libc_ftell)(FILE *stream); 26 | static off_t (*_libc_ftello)(FILE *stream); 27 | 28 | #if defined(_LARGEFILE64_SOURCE) && !defined(__APPLE__) 29 | static FILE * (*_libc_fopen64)(const char *path, const char *mode); 30 | static int (*_libc_fseeko64)(FILE *stream, off64_t offset, int whence); 31 | static off64_t (*_libc_ftello64)(FILE *stream); 32 | #endif 33 | 34 | static int (*_libc_fclose)(FILE *stream); 35 | static int (*_libc_fileno)(FILE *stream); 36 | 37 | // Nonlocking stdio functions 38 | static size_t (*_libc_fwrite_unlocked)(const void *ptr, size_t size, size_t nmemb, FILE *stream); 39 | static int (*_libc_fputc_unlocked)(int character, FILE *stream); 40 | static int (*_libc_fputs_unlocked)(const char *str, FILE *stream); 41 | static size_t (*_libc_fread_unlocked)(void *ptr, size_t size, size_t nmemb, FILE *stream); 42 | static int (*_libc_fgetc_unlocked)(FILE *stream); 43 | static char *(*_libc_fgets_unlocked)(char *str, int num, FILE *stream); 44 | static int (*_libc_fileno_unlocked)(FILE *stream); 45 | 46 | // POSIX functions 47 | static int (* _posix_open)(const char *pathname, int flags, ...); 48 | static ssize_t (* _posix_read)(int fd, void *buf, size_t count); 49 | static ssize_t (* _posix_write)(int fd, const void *buf, size_t count); 50 | static off_t (* _posix_lseek)(int fd, off_t offset, int whence); 51 | 52 | static int (* _posix_close)(int fd); 53 | 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /examples/demo/demo-app.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - persistent mode example 3 | -------------------------------------------- 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Copyright 2015 Google Inc. All rights reserved. 8 | 9 | Modifed: Marek Zmysłowski 10 | Copyright: 2020 11 | 12 | Licensed under the Apache License, Version 2.0 (the "License"); 13 | you may not use this file except in compliance with the License. 14 | You may obtain a copy of the License at: 15 | 16 | http://www.apache.org/licenses/LICENSE-2.0 17 | 18 | This file demonstrates the high-performance "persistent mode" that may be 19 | suitable for fuzzing certain fast and well-behaved libraries, provided that 20 | they are stateless or that their internal state can be easily reset 21 | across runs. 22 | 23 | To make this work, the library and this shim need to be compiled in LLVM 24 | mode using afl-clang-fast (other compiler wrappers will *not* work). 25 | 26 | */ 27 | 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #ifdef AFL_MEMORY 36 | __AFL_FUZZ_INIT(); 37 | extern void set_memory_size(ssize_t size); 38 | extern void set_memory_ptr(unsigned char *buffer); 39 | #endif 40 | 41 | 42 | 43 | /* Main entry point. */ 44 | 45 | int main(int argc, char **argv) { 46 | 47 | ssize_t len; /* how much input did we read? */ 48 | unsigned char *buf; /* test case buffer pointer */ 49 | FILE *file; 50 | 51 | /* The number passed to __AFL_LOOP() controls the maximum number of 52 | iterations before the loop exits and the program is allowed to 53 | terminate normally. This limits the impact of accidental memory leaks 54 | and similar hiccups. */ 55 | #ifdef AFL_MEMORY 56 | // Set the memory pointer inside library. 57 | set_memory_ptr(__AFL_FUZZ_TESTCASE_BUF); 58 | 59 | 60 | while (__AFL_LOOP(1000)) { 61 | // Set the file size. 62 | set_memory_size(__AFL_FUZZ_TESTCASE_LEN); 63 | #endif 64 | #ifdef AFL_PERSISTENT 65 | __AFL_INIT(); 66 | while (__AFL_LOOP(1000)) { 67 | #endif 68 | file = fopen(argv[1], "r"); 69 | if (fgetc(file) == 'f') { 70 | 71 | printf("one\n"); 72 | if (fgetc(file) == 'o') { 73 | 74 | printf("two\n"); 75 | if (fgetc(file) == 'o') { 76 | 77 | printf("three\n"); 78 | if (fgetc(file) == '!') { 79 | 80 | printf("four\n"); 81 | if (fgetc(file) == '!') { 82 | 83 | printf("five\n"); 84 | if (fgetc(file) == '!') { 85 | 86 | printf("six\n"); 87 | abort(); 88 | 89 | } 90 | 91 | } 92 | 93 | } 94 | 95 | } 96 | 97 | } 98 | 99 | } 100 | fclose(file); 101 | /*** END PLACEHOLDER CODE ***/ 102 | #if defined AFL_MEMORY || defined AFL_PERSISTENT 103 | } 104 | #endif 105 | /* Once the loop is exited, terminate normally - AFL will restart the process 106 | when this happens, with a clean slate when it comes to allocated memory, 107 | leftover file descriptors, etc. */ 108 | 109 | return 0; 110 | 111 | } 112 | 113 | -------------------------------------------------------------------------------- /Performance.md: -------------------------------------------------------------------------------- 1 | # Performance 2 | The performance test was done on the libpng library with readpng console application. Original source code is available [here](./examples/libpng/readpng.c). 3 | 4 | ## Setup 5 | For this test, two cases ware prepared. Original file was changed to be fuzzed in the persistent mode and the persistent mode with libfiowrapper. Following diff shows differences between the files. As it can be seen, only few addition lines were added for the libfiowrapper. 6 | ``` 7 | /research/libfiowrapper/examples/libpng$ diff -u readpng-pers.c readpng-fiow.c 8 | --- readpng-pers.c 2020-11-02 22:58:56.207491235 +0100 9 | +++ readpng-fiow.c 2020-11-02 23:07:21.736258287 +0100 10 | @@ -55,7 +55,7 @@ 11 | /* 12 | * Modified by: Marek Zmysłowski 13 | * Copyrights: 2020 14 | - * This file contains code to be fuzzed in persistent mode. 15 | + * This file contains code to be fuzzed in persistent mode with libfiowrapper. 16 | */ 17 | 18 | #include 19 | @@ -66,6 +66,10 @@ 20 | #include "png.h" /* libpng header; includes zlib.h */ 21 | #include "readpng.h" /* typedefs, common macros, public prototypes */ 22 | 23 | +__AFL_FUZZ_INIT(); 24 | +extern void set_memory_size(ssize_t size); 25 | +extern void set_memory_ptr(unsigned char *buffer); 26 | + 27 | /* future versions of libpng will provide this macro: */ 28 | #ifndef png_jmpbuf 29 | # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 30 | @@ -317,8 +321,12 @@ 31 | uch red, green, blue; 32 | int pChannels; 33 | ulg pRowbytes; 34 | + // Set the memory pointer 35 | + set_memory_ptr(__AFL_FUZZ_TESTCASE_BUF); 36 | while (__AFL_LOOP(65535)) 37 | { 38 | + // Set the file size. 39 | + set_memory_size(__AFL_FUZZ_TESTCASE_LEN); 40 | image_data = NULL; 41 | infile = fopen(argv[1], "r"); 42 | if (!readpng_init(infile, &w, &h)) { 43 | ``` 44 | The following commands were used to build the executables: 45 | ``` 46 | afl-clang-fast readpng-fiow.c -o readpng-fiow ./libpng-code/afl-build/libpng16.a -lz -lm -L../../ -lfiowrapper -I./libpng-code/afl-build -I./libpng-code 47 | ``` 48 | ``` 49 | afl-clang-fast readpng-pers.c -o readpng-pers ./libpng-code/afl-build/libpng16.a -lz -lm -I./libpng-code/afl-build -I./libpng-code 50 | ``` 51 | 52 | ## Results: 53 | There were 4 tests performed, each took 4 hours with the AFL++. In every case the same seed was used. The following command was used: 54 | ``` 55 | afl-fuzz -i ./input-png/ -o ./output -s 1234 -V 14400 -p seek -M fiow -m none -- ./readpng-fiow @@ 56 | 57 | afl-fuzz -i ./input-png/ -o ./output -s 1234 -V 14400 -p seek -M pers -m none -- ./readpng-pers @@ 58 | ``` 59 | Here are the results: 60 | 61 | | | Persistent Mode | libfiowrapper | 62 | |---|---|---| 63 | | Total execs (Avg) | 76,5M | 140M | 64 | | Total paths | 1860 | 1940 | 65 | | Total crashes | 1 (1 unique) | 1 (1 unique) | 66 | 67 | 68 | Here are the statistics from the example single run: 69 | 70 | |![Fuzzing with persistent mode only](afl-fiow-stats.png)| 71 | |:--:| 72 | | *Image 1. Fuzzing with persistent mode + libfiowrapper* | 73 | 74 | |![Fuzzing with persistent mode + libfiowrapper](afl-pers-stats.png)| 75 | |:--:| 76 | | *Image 2. Fuzzing with persistent mode only - stats* | 77 | 78 | 79 | The tests were performed inside docker container running Linux 4.19.76-linuxkit #1 SMP x86_64 80 | -------------------------------------------------------------------------------- /examples/libpng/readpng.h: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------- 2 | 3 | rpng - simple PNG display program readpng.h 4 | 5 | --------------------------------------------------------------------------- 6 | 7 | Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. 8 | 9 | This software is provided "as is," without warranty of any kind, 10 | express or implied. In no event shall the author or contributors 11 | be held liable for any damages arising in any way from the use of 12 | this software. 13 | 14 | The contents of this file are DUAL-LICENSED. You may modify and/or 15 | redistribute this software according to the terms of one of the 16 | following two licenses (at your option): 17 | 18 | 19 | LICENSE 1 ("BSD-like with advertising clause"): 20 | 21 | Permission is granted to anyone to use this software for any purpose, 22 | including commercial applications, and to alter it and redistribute 23 | it freely, subject to the following restrictions: 24 | 25 | 1. Redistributions of source code must retain the above copyright 26 | notice, disclaimer, and this list of conditions. 27 | 2. Redistributions in binary form must reproduce the above copyright 28 | notice, disclaimer, and this list of conditions in the documenta- 29 | tion and/or other materials provided with the distribution. 30 | 3. All advertising materials mentioning features or use of this 31 | software must display the following acknowledgment: 32 | 33 | This product includes software developed by Greg Roelofs 34 | and contributors for the book, "PNG: The Definitive Guide," 35 | published by O'Reilly and Associates. 36 | 37 | 38 | LICENSE 2 (GNU GPL v2 or later): 39 | 40 | This program is free software; you can redistribute it and/or modify 41 | it under the terms of the GNU General Public License as published by 42 | the Free Software Foundation; either version 2 of the License, or 43 | (at your option) any later version. 44 | 45 | This program is distributed in the hope that it will be useful, 46 | but WITHOUT ANY WARRANTY; without even the implied warranty of 47 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 48 | GNU General Public License for more details. 49 | 50 | You should have received a copy of the GNU General Public License 51 | along with this program; if not, write to the Free Software Foundation, 52 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 53 | 54 | ---------------------------------------------------------------------------*/ 55 | 56 | #ifndef TRUE 57 | # define TRUE 1 58 | # define FALSE 0 59 | #endif 60 | 61 | #ifndef MAX 62 | # define MAX(a,b) ((a) > (b)? (a) : (b)) 63 | # define MIN(a,b) ((a) < (b)? (a) : (b)) 64 | #endif 65 | 66 | #ifdef DEBUG 67 | # define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);} 68 | #else 69 | # define Trace(x) ; 70 | #endif 71 | 72 | typedef unsigned char uch; 73 | typedef unsigned short ush; 74 | typedef unsigned long ulg; 75 | 76 | 77 | /* prototypes for public functions in readpng.c */ 78 | 79 | void readpng_version_info(void); 80 | 81 | int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight); 82 | 83 | int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue); 84 | 85 | uch *readpng_get_image(double display_exponent, int *pChannels, 86 | ulg *pRowbytes); 87 | 88 | void readpng_cleanup(int free_image_data); 89 | -------------------------------------------------------------------------------- /examples/demo/demo-app-posix.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - persistent mode example 3 | -------------------------------------------- 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Copyright 2015 Google Inc. All rights reserved. 8 | 9 | Modifed: Marek Zmysłowski 10 | Copyright: 2020 11 | 12 | Licensed under the Apache License, Version 2.0 (the "License"); 13 | you may not use this file except in compliance with the License. 14 | You may obtain a copy of the License at: 15 | 16 | http://www.apache.org/licenses/LICENSE-2.0 17 | 18 | This file demonstrates the high-performance "persistent mode" that may be 19 | suitable for fuzzing certain fast and well-behaved libraries, provided that 20 | they are stateless or that their internal state can be easily reset 21 | across runs. 22 | 23 | To make this work, the library and this shim need to be compiled in LLVM 24 | mode using afl-clang-fast (other compiler wrappers will *not* work). 25 | 26 | */ 27 | 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #ifdef AFL_MEMORY 39 | __AFL_FUZZ_INIT(); 40 | extern void set_memory_size(ssize_t size); 41 | extern void set_memory_ptr(unsigned char *buffer); 42 | #endif 43 | 44 | 45 | 46 | /* Main entry point. */ 47 | 48 | int main(int argc, char **argv) { 49 | 50 | ssize_t len; /* how much input did we read? */ 51 | unsigned char *buf; /* test case buffer pointer */ 52 | int file; 53 | char byte; 54 | 55 | /* The number passed to __AFL_LOOP() controls the maximum number of 56 | iterations before the loop exits and the program is allowed to 57 | terminate normally. This limits the impact of accidental memory leaks 58 | and similar hiccups. */ 59 | #ifdef AFL_MEMORY 60 | // Set the memory pointer inside library. 61 | set_memory_ptr(__AFL_FUZZ_TESTCASE_BUF); 62 | 63 | 64 | while (__AFL_LOOP(1000)) { 65 | // Set the file size. 66 | set_memory_size(__AFL_FUZZ_TESTCASE_LEN); 67 | #endif 68 | #ifdef AFL_PERSISTENT 69 | __AFL_INIT(); 70 | while (__AFL_LOOP(1000)) { 71 | #endif 72 | file = open(argv[1], O_RDONLY); 73 | read(file, &byte, 1); 74 | if (byte == 'f') { 75 | 76 | printf("one\n"); 77 | read(file, &byte, 1); 78 | if (byte == 'o') { 79 | 80 | printf("two\n"); 81 | read(file, &byte, 1); 82 | if (byte == 'o') { 83 | 84 | printf("three\n"); 85 | read(file, &byte, 1); 86 | if (byte == '!') { 87 | 88 | printf("four\n"); 89 | read(file, &byte, 1); 90 | if (byte == '!') { 91 | 92 | printf("five\n"); 93 | read(file, &byte, 1); 94 | if (byte == '!') { 95 | 96 | printf("six\n"); 97 | abort(); 98 | 99 | } 100 | 101 | } 102 | 103 | } 104 | 105 | } 106 | 107 | } 108 | 109 | } 110 | close(file); 111 | /*** END PLACEHOLDER CODE ***/ 112 | #if defined AFL_MEMORY || defined AFL_PERSISTENT 113 | } 114 | #endif 115 | /* Once the loop is exited, terminate normally - AFL will restart the process 116 | when this happens, with a clean slate when it comes to allocated memory, 117 | leftover file descriptors, etc. */ 118 | 119 | return 0; 120 | 121 | } 122 | 123 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libfiowrapper 2 | 3 | This library was created to help fuzzing application that are reading data from the file. It hooks file calls and replaces it with memory access. 4 | 5 | Two libraries are available: 6 | 7 | libfioinfo.so - this library just collects the statistics of different file calls that are used in the application 8 | 9 | libfiowrapper.so - this library is used to replace file function calls with just memory access. 10 | 11 | ## Building 12 | To build just run: 13 | ``` 14 | make 15 | ``` 16 | 17 | To display more information build debug version: 18 | ``` 19 | make debug 20 | ``` 21 | 22 | The demo applications are available inside the ```./examples``` directory. To build them just run: 23 | ``` 24 | cd ./examples/demo 25 | make 26 | ``` 27 | 28 | ## Running Demo Apps 29 | The examples\demo directory, after build, will containe 3 application: 30 | - info-demo - this application is just compailed with the clang. 31 | - file-fuzz-demo, file-fuzz-demo-posix - these applications are compiled with afl-clang-fast. They can be used to run fuzzing with simple input file. 32 | - per-fuzz-demo, per-fuzz-demo-posix - these applications are compiled with the persistent mode. 33 | - mem-fuzz-demo, mem-fuzz-demo-posix - these applicaitons are compiled with persistend mode with shared memory the libfiowrapper - it hooks all the f* stdio and posix file functions. 34 | 35 | Bellow commands needs to be run from the examples/demo directory. 36 | 37 | To collect information: 38 | ``` 39 | LD_PRELOAD=../../libfioinfo.so ./info-demo ./input/sample 40 | =========================================== 41 | libfioinfo 42 | Version: 0.3 43 | Author: Marek Zmysłowski 44 | =========================================== 45 | 46 | one 47 | two 48 | three 49 | =========================================== 50 | File calls statistics: 51 | fopen: 1 52 | fwrite: 0 - unlocked: 0 53 | fputc: 0 - unlocked: 0 54 | fputs: 0 - unlocked: 0 55 | fread: 0 - unlocked: 0 56 | fgetc: 4 - unlocked: 0 57 | fgets: 0 - unlocked: 0 58 | fseek: 0 59 | ftell: 0 60 | fclose: 1 61 | 62 | open: 0 63 | read: 0 64 | write: 0 65 | lseek: 0 66 | close: 0 67 | =========================================== 68 | 69 | ``` 70 | 71 | For the regular fuzzing with files run the file-fuzz-demo: 72 | ``` 73 | afl-fuzz -i ./input -o ./output -- ./file-fuzz-demo @@ 74 | ``` 75 | 76 | For the persistent fuzzing run the per-fuzz-demo: 77 | ``` 78 | afl-fuzz -i ./input -o ./output -- ./per-fuzz-demo @@ 79 | ``` 80 | For the persistent fuzzing with shared memory first the LD_LIBRARY_PATH needs to be set for the directory where the libfiowrapper.so is located. 81 | ``` 82 | export LD_LIBRARY_PATH=../../ 83 | afl-fuzz -i ./input -o ./output -- ./mem-fuzz-demo @@ 84 | ``` 85 | ## Modifing code 86 | The code needs to be modify by adding few calls from the library. Just after __AFL_FUZZ_INIT add two function declarations: 87 | ``` 88 | __AFL_FUZZ_INIT(); 89 | #ifdef __cplusplus 90 | extern "C" void set_memory_size(ssize_t size); 91 | extern "C" void set_memory_ptr(unsigned char *buffer); 92 | #else 93 | extern void set_memory_size(ssize_t size); 94 | extern void set_memory_ptr(unsigned char *buffer); 95 | #endif 96 | ``` 97 | 98 | Before the AFL loop initialize the memory pointer: 99 | ``` 100 | set_memory_ptr(__AFL_FUZZ_TESTCASE_BUF); 101 | ``` 102 | 103 | Each iteration, the size needs to be set: 104 | ``` 105 | while (__AFL_LOOP(1000)) { 106 | // Set the file size. 107 | set_memory_size(__AFL_FUZZ_TESTCASE_LEN); 108 | ``` 109 | ## Real Live Example 110 | ### libpng 111 | To build libpng as an example please read [examples/libpng/README.md](examples/libpng) 112 | 113 | ## Questions and Feedback 114 | If you have any questions or feedback, please send me an email to marekzmyslowski@poczta.onet.pl 115 | -------------------------------------------------------------------------------- /examples/libpng/readpng.c: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------- 2 | 3 | rpng - simple PNG display program readpng.c 4 | 5 | --------------------------------------------------------------------------- 6 | 7 | Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. 8 | 9 | This software is provided "as is," without warranty of any kind, 10 | express or implied. In no event shall the author or contributors 11 | be held liable for any damages arising in any way from the use of 12 | this software. 13 | 14 | The contents of this file are DUAL-LICENSED. You may modify and/or 15 | redistribute this software according to the terms of one of the 16 | following two licenses (at your option): 17 | 18 | 19 | LICENSE 1 ("BSD-like with advertising clause"): 20 | 21 | Permission is granted to anyone to use this software for any purpose, 22 | including commercial applications, and to alter it and redistribute 23 | it freely, subject to the following restrictions: 24 | 25 | 1. Redistributions of source code must retain the above copyright 26 | notice, disclaimer, and this list of conditions. 27 | 2. Redistributions in binary form must reproduce the above copyright 28 | notice, disclaimer, and this list of conditions in the documenta- 29 | tion and/or other materials provided with the distribution. 30 | 3. All advertising materials mentioning features or use of this 31 | software must display the following acknowledgment: 32 | 33 | This product includes software developed by Greg Roelofs 34 | and contributors for the book, "PNG: The Definitive Guide," 35 | published by O'Reilly and Associates. 36 | 37 | 38 | LICENSE 2 (GNU GPL v2 or later): 39 | 40 | This program is free software; you can redistribute it and/or modify 41 | it under the terms of the GNU General Public License as published by 42 | the Free Software Foundation; either version 2 of the License, or 43 | (at your option) any later version. 44 | 45 | This program is distributed in the hope that it will be useful, 46 | but WITHOUT ANY WARRANTY; without even the implied warranty of 47 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 48 | GNU General Public License for more details. 49 | 50 | You should have received a copy of the GNU General Public License 51 | along with this program; if not, write to the Free Software Foundation, 52 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 53 | 54 | ---------------------------------------------------------------------------*/ 55 | /* 56 | * Modified by: Marek Zmysłowski 57 | * Copyrights: 2020 58 | */ 59 | 60 | #include 61 | #include 62 | 63 | #include 64 | 65 | #include "png.h" /* libpng header; includes zlib.h */ 66 | #include "readpng.h" /* typedefs, common macros, public prototypes */ 67 | 68 | /* future versions of libpng will provide this macro: */ 69 | #ifndef png_jmpbuf 70 | # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 71 | #endif 72 | 73 | 74 | static png_structp png_ptr = NULL; 75 | static png_infop info_ptr = NULL; 76 | 77 | png_uint_32 width, height; 78 | int bit_depth, color_type; 79 | uch *image_data = NULL; 80 | 81 | 82 | void readpng_version_info(void) 83 | { 84 | fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n", 85 | PNG_LIBPNG_VER_STRING, png_libpng_ver); 86 | fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n", 87 | ZLIB_VERSION, zlib_version); 88 | } 89 | 90 | 91 | /* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */ 92 | 93 | int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight) 94 | { 95 | uch sig[8]; 96 | 97 | 98 | /* first do a quick check that the file really is a PNG image; could 99 | * have used slightly more general png_sig_cmp() function instead */ 100 | 101 | fread(sig, 1, 8, infile); 102 | if (!png_check_sig(sig, 8)) 103 | return 1; /* bad signature */ 104 | 105 | 106 | /* could pass pointers to user-defined error handlers instead of NULLs: */ 107 | 108 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 109 | if (!png_ptr) 110 | return 4; /* out of memory */ 111 | 112 | info_ptr = png_create_info_struct(png_ptr); 113 | if (!info_ptr) { 114 | png_destroy_read_struct(&png_ptr, NULL, NULL); 115 | return 4; /* out of memory */ 116 | } 117 | 118 | 119 | /* we could create a second info struct here (end_info), but it's only 120 | * useful if we want to keep pre- and post-IDAT chunk info separated 121 | * (mainly for PNG-aware image editors and converters) */ 122 | 123 | 124 | /* setjmp() must be called in every function that calls a PNG-reading 125 | * libpng function */ 126 | 127 | if (setjmp(png_jmpbuf(png_ptr))) { 128 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 129 | return 2; 130 | } 131 | 132 | 133 | png_init_io(png_ptr, infile); 134 | png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ 135 | 136 | png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ 137 | 138 | 139 | /* alternatively, could make separate calls to png_get_image_width(), 140 | * etc., but want bit_depth and color_type for later [don't care about 141 | * compression_type and filter_type => NULLs] */ 142 | 143 | png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 144 | NULL, NULL, NULL); 145 | *pWidth = width; 146 | *pHeight = height; 147 | 148 | 149 | /* OK, that's all we need for now; return happy */ 150 | 151 | return 0; 152 | } 153 | 154 | 155 | 156 | 157 | /* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error; 158 | * scales values to 8-bit if necessary */ 159 | 160 | int readpng_get_bgcolor(uch *red, uch *green, uch *blue) 161 | { 162 | png_color_16p pBackground; 163 | 164 | 165 | /* setjmp() must be called in every function that calls a PNG-reading 166 | * libpng function */ 167 | 168 | if (setjmp(png_jmpbuf(png_ptr))) { 169 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 170 | return 2; 171 | } 172 | 173 | 174 | if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) 175 | return 1; 176 | 177 | /* it is not obvious from the libpng documentation, but this function 178 | * takes a pointer to a pointer, and it always returns valid red, green 179 | * and blue values, regardless of color_type: */ 180 | 181 | png_get_bKGD(png_ptr, info_ptr, &pBackground); 182 | 183 | 184 | /* however, it always returns the raw bKGD data, regardless of any 185 | * bit-depth transformations, so check depth and adjust if necessary */ 186 | 187 | if (bit_depth == 16) { 188 | *red = pBackground->red >> 8; 189 | *green = pBackground->green >> 8; 190 | *blue = pBackground->blue >> 8; 191 | } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { 192 | if (bit_depth == 1) 193 | *red = *green = *blue = pBackground->gray? 255 : 0; 194 | else if (bit_depth == 2) 195 | *red = *green = *blue = (255/3) * pBackground->gray; 196 | else /* bit_depth == 4 */ 197 | *red = *green = *blue = (255/15) * pBackground->gray; 198 | } else { 199 | *red = (uch)pBackground->red; 200 | *green = (uch)pBackground->green; 201 | *blue = (uch)pBackground->blue; 202 | } 203 | 204 | return 0; 205 | } 206 | 207 | 208 | 209 | 210 | /* display_exponent == LUT_exponent * CRT_exponent */ 211 | 212 | uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) 213 | { 214 | double gamma; 215 | png_uint_32 i, rowbytes; 216 | png_bytepp row_pointers = NULL; 217 | 218 | 219 | /* setjmp() must be called in every function that calls a PNG-reading 220 | * libpng function */ 221 | 222 | if (setjmp(png_jmpbuf(png_ptr))) { 223 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 224 | return NULL; 225 | } 226 | 227 | 228 | /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits, 229 | * transparency chunks to full alpha channel; strip 16-bit-per-sample 230 | * images to 8 bits per sample; and convert grayscale to RGB[A] */ 231 | 232 | if (color_type == PNG_COLOR_TYPE_PALETTE) 233 | png_set_expand(png_ptr); 234 | if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) 235 | png_set_expand(png_ptr); 236 | if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 237 | png_set_expand(png_ptr); 238 | if (bit_depth == 16) 239 | png_set_strip_16(png_ptr); 240 | if (color_type == PNG_COLOR_TYPE_GRAY || 241 | color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 242 | png_set_gray_to_rgb(png_ptr); 243 | 244 | 245 | /* unlike the example in the libpng documentation, we have *no* idea where 246 | * this file may have come from--so if it doesn't have a file gamma, don't 247 | * do any correction ("do no harm") */ 248 | 249 | if (png_get_gAMA(png_ptr, info_ptr, &gamma)) 250 | png_set_gamma(png_ptr, display_exponent, gamma); 251 | 252 | 253 | /* all transformations have been registered; now update info_ptr data, 254 | * get rowbytes and channels, and allocate image memory */ 255 | 256 | png_read_update_info(png_ptr, info_ptr); 257 | 258 | *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr); 259 | *pChannels = (int)png_get_channels(png_ptr, info_ptr); 260 | 261 | if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) { 262 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 263 | return NULL; 264 | } 265 | if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { 266 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 267 | free(image_data); 268 | image_data = NULL; 269 | return NULL; 270 | } 271 | 272 | Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n", *pChannels, rowbytes, height)); 273 | 274 | 275 | /* set the individual row_pointers to point at the correct offsets */ 276 | 277 | for (i = 0; i < height; ++i) 278 | row_pointers[i] = image_data + i*rowbytes; 279 | 280 | 281 | /* now we can go ahead and just read the whole image */ 282 | 283 | png_read_image(png_ptr, row_pointers); 284 | 285 | 286 | /* and we're done! (png_read_end() can be omitted if no processing of 287 | * post-IDAT text/time/etc. is desired) */ 288 | 289 | free(row_pointers); 290 | row_pointers = NULL; 291 | 292 | png_read_end(png_ptr, NULL); 293 | 294 | return image_data; 295 | } 296 | 297 | 298 | void readpng_cleanup(int free_image_data) 299 | { 300 | if (free_image_data && image_data) { 301 | free(image_data); 302 | image_data = NULL; 303 | } 304 | 305 | if (png_ptr && info_ptr) { 306 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 307 | png_ptr = NULL; 308 | info_ptr = NULL; 309 | } 310 | } 311 | 312 | int main(int argc, char *argv[]) 313 | { 314 | FILE *infile; 315 | unsigned long h,w; 316 | uch red, green, blue; 317 | int pChannels; 318 | ulg pRowbytes; 319 | image_data = NULL; 320 | infile = fopen(argv[1], "r"); 321 | if (!readpng_init(infile, &w, &h)) { 322 | readpng_get_bgcolor(&red, &green, &blue); 323 | image_data = readpng_get_image((2.2*1.0), &pChannels, &pRowbytes); 324 | readpng_cleanup(1); 325 | } 326 | fclose(infile); 327 | } 328 | -------------------------------------------------------------------------------- /examples/libpng/readpng-pers.c: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------- 2 | 3 | rpng - simple PNG display program readpng.c 4 | 5 | --------------------------------------------------------------------------- 6 | 7 | Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. 8 | 9 | This software is provided "as is," without warranty of any kind, 10 | express or implied. In no event shall the author or contributors 11 | be held liable for any damages arising in any way from the use of 12 | this software. 13 | 14 | The contents of this file are DUAL-LICENSED. You may modify and/or 15 | redistribute this software according to the terms of one of the 16 | following two licenses (at your option): 17 | 18 | 19 | LICENSE 1 ("BSD-like with advertising clause"): 20 | 21 | Permission is granted to anyone to use this software for any purpose, 22 | including commercial applications, and to alter it and redistribute 23 | it freely, subject to the following restrictions: 24 | 25 | 1. Redistributions of source code must retain the above copyright 26 | notice, disclaimer, and this list of conditions. 27 | 2. Redistributions in binary form must reproduce the above copyright 28 | notice, disclaimer, and this list of conditions in the documenta- 29 | tion and/or other materials provided with the distribution. 30 | 3. All advertising materials mentioning features or use of this 31 | software must display the following acknowledgment: 32 | 33 | This product includes software developed by Greg Roelofs 34 | and contributors for the book, "PNG: The Definitive Guide," 35 | published by O'Reilly and Associates. 36 | 37 | 38 | LICENSE 2 (GNU GPL v2 or later): 39 | 40 | This program is free software; you can redistribute it and/or modify 41 | it under the terms of the GNU General Public License as published by 42 | the Free Software Foundation; either version 2 of the License, or 43 | (at your option) any later version. 44 | 45 | This program is distributed in the hope that it will be useful, 46 | but WITHOUT ANY WARRANTY; without even the implied warranty of 47 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 48 | GNU General Public License for more details. 49 | 50 | You should have received a copy of the GNU General Public License 51 | along with this program; if not, write to the Free Software Foundation, 52 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 53 | 54 | ---------------------------------------------------------------------------*/ 55 | /* 56 | * Modified by: Marek Zmysłowski 57 | * Copyrights: 2020 58 | * This file contains code to be fuzzed in persistent mode. 59 | */ 60 | 61 | #include 62 | #include 63 | 64 | #include 65 | 66 | #include "png.h" /* libpng header; includes zlib.h */ 67 | #include "readpng.h" /* typedefs, common macros, public prototypes */ 68 | 69 | /* future versions of libpng will provide this macro: */ 70 | #ifndef png_jmpbuf 71 | # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 72 | #endif 73 | 74 | 75 | static png_structp png_ptr = NULL; 76 | static png_infop info_ptr = NULL; 77 | 78 | png_uint_32 width, height; 79 | int bit_depth, color_type; 80 | uch *image_data = NULL; 81 | 82 | 83 | void readpng_version_info(void) 84 | { 85 | fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n", 86 | PNG_LIBPNG_VER_STRING, png_libpng_ver); 87 | fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n", 88 | ZLIB_VERSION, zlib_version); 89 | } 90 | 91 | 92 | /* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */ 93 | 94 | int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight) 95 | { 96 | uch sig[8]; 97 | 98 | 99 | /* first do a quick check that the file really is a PNG image; could 100 | * have used slightly more general png_sig_cmp() function instead */ 101 | 102 | fread(sig, 1, 8, infile); 103 | if (!png_check_sig(sig, 8)) 104 | return 1; /* bad signature */ 105 | 106 | 107 | /* could pass pointers to user-defined error handlers instead of NULLs: */ 108 | 109 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 110 | if (!png_ptr) 111 | return 4; /* out of memory */ 112 | 113 | info_ptr = png_create_info_struct(png_ptr); 114 | if (!info_ptr) { 115 | png_destroy_read_struct(&png_ptr, NULL, NULL); 116 | return 4; /* out of memory */ 117 | } 118 | 119 | 120 | /* we could create a second info struct here (end_info), but it's only 121 | * useful if we want to keep pre- and post-IDAT chunk info separated 122 | * (mainly for PNG-aware image editors and converters) */ 123 | 124 | 125 | /* setjmp() must be called in every function that calls a PNG-reading 126 | * libpng function */ 127 | 128 | if (setjmp(png_jmpbuf(png_ptr))) { 129 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 130 | return 2; 131 | } 132 | 133 | 134 | png_init_io(png_ptr, infile); 135 | png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ 136 | 137 | png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ 138 | 139 | 140 | /* alternatively, could make separate calls to png_get_image_width(), 141 | * etc., but want bit_depth and color_type for later [don't care about 142 | * compression_type and filter_type => NULLs] */ 143 | 144 | png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 145 | NULL, NULL, NULL); 146 | *pWidth = width; 147 | *pHeight = height; 148 | 149 | 150 | /* OK, that's all we need for now; return happy */ 151 | 152 | return 0; 153 | } 154 | 155 | 156 | 157 | 158 | /* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error; 159 | * scales values to 8-bit if necessary */ 160 | 161 | int readpng_get_bgcolor(uch *red, uch *green, uch *blue) 162 | { 163 | png_color_16p pBackground; 164 | 165 | 166 | /* setjmp() must be called in every function that calls a PNG-reading 167 | * libpng function */ 168 | 169 | if (setjmp(png_jmpbuf(png_ptr))) { 170 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 171 | return 2; 172 | } 173 | 174 | 175 | if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) 176 | return 1; 177 | 178 | /* it is not obvious from the libpng documentation, but this function 179 | * takes a pointer to a pointer, and it always returns valid red, green 180 | * and blue values, regardless of color_type: */ 181 | 182 | png_get_bKGD(png_ptr, info_ptr, &pBackground); 183 | 184 | 185 | /* however, it always returns the raw bKGD data, regardless of any 186 | * bit-depth transformations, so check depth and adjust if necessary */ 187 | 188 | if (bit_depth == 16) { 189 | *red = pBackground->red >> 8; 190 | *green = pBackground->green >> 8; 191 | *blue = pBackground->blue >> 8; 192 | } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { 193 | if (bit_depth == 1) 194 | *red = *green = *blue = pBackground->gray? 255 : 0; 195 | else if (bit_depth == 2) 196 | *red = *green = *blue = (255/3) * pBackground->gray; 197 | else /* bit_depth == 4 */ 198 | *red = *green = *blue = (255/15) * pBackground->gray; 199 | } else { 200 | *red = (uch)pBackground->red; 201 | *green = (uch)pBackground->green; 202 | *blue = (uch)pBackground->blue; 203 | } 204 | 205 | return 0; 206 | } 207 | 208 | 209 | 210 | 211 | /* display_exponent == LUT_exponent * CRT_exponent */ 212 | 213 | uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) 214 | { 215 | double gamma; 216 | png_uint_32 i, rowbytes; 217 | png_bytepp row_pointers = NULL; 218 | 219 | 220 | /* setjmp() must be called in every function that calls a PNG-reading 221 | * libpng function */ 222 | 223 | if (setjmp(png_jmpbuf(png_ptr))) { 224 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 225 | return NULL; 226 | } 227 | 228 | 229 | /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits, 230 | * transparency chunks to full alpha channel; strip 16-bit-per-sample 231 | * images to 8 bits per sample; and convert grayscale to RGB[A] */ 232 | 233 | if (color_type == PNG_COLOR_TYPE_PALETTE) 234 | png_set_expand(png_ptr); 235 | if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) 236 | png_set_expand(png_ptr); 237 | if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 238 | png_set_expand(png_ptr); 239 | if (bit_depth == 16) 240 | png_set_strip_16(png_ptr); 241 | if (color_type == PNG_COLOR_TYPE_GRAY || 242 | color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 243 | png_set_gray_to_rgb(png_ptr); 244 | 245 | 246 | /* unlike the example in the libpng documentation, we have *no* idea where 247 | * this file may have come from--so if it doesn't have a file gamma, don't 248 | * do any correction ("do no harm") */ 249 | 250 | if (png_get_gAMA(png_ptr, info_ptr, &gamma)) 251 | png_set_gamma(png_ptr, display_exponent, gamma); 252 | 253 | 254 | /* all transformations have been registered; now update info_ptr data, 255 | * get rowbytes and channels, and allocate image memory */ 256 | 257 | png_read_update_info(png_ptr, info_ptr); 258 | 259 | *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr); 260 | *pChannels = (int)png_get_channels(png_ptr, info_ptr); 261 | 262 | if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) { 263 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 264 | return NULL; 265 | } 266 | if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { 267 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 268 | free(image_data); 269 | image_data = NULL; 270 | return NULL; 271 | } 272 | 273 | Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n", *pChannels, rowbytes, height)); 274 | 275 | 276 | /* set the individual row_pointers to point at the correct offsets */ 277 | 278 | for (i = 0; i < height; ++i) 279 | row_pointers[i] = image_data + i*rowbytes; 280 | 281 | 282 | /* now we can go ahead and just read the whole image */ 283 | 284 | png_read_image(png_ptr, row_pointers); 285 | 286 | 287 | /* and we're done! (png_read_end() can be omitted if no processing of 288 | * post-IDAT text/time/etc. is desired) */ 289 | 290 | free(row_pointers); 291 | row_pointers = NULL; 292 | 293 | png_read_end(png_ptr, NULL); 294 | 295 | return image_data; 296 | } 297 | 298 | 299 | void readpng_cleanup(int free_image_data) 300 | { 301 | if (free_image_data && image_data) { 302 | free(image_data); 303 | image_data = NULL; 304 | } 305 | 306 | if (png_ptr && info_ptr) { 307 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 308 | png_ptr = NULL; 309 | info_ptr = NULL; 310 | } 311 | } 312 | 313 | int main(int argc, char *argv[]) 314 | { 315 | FILE *infile; 316 | unsigned long h,w; 317 | uch red, green, blue; 318 | int pChannels; 319 | ulg pRowbytes; 320 | while (__AFL_LOOP(65535)) 321 | { 322 | image_data = NULL; 323 | infile = fopen(argv[1], "r"); 324 | if (!readpng_init(infile, &w, &h)) { 325 | readpng_get_bgcolor(&red, &green, &blue); 326 | image_data = readpng_get_image((2.2*1.0), &pChannels, &pRowbytes); 327 | readpng_cleanup(1); 328 | } 329 | fclose(infile); 330 | } 331 | } 332 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /examples/libpng/readpng-fiow.c: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------- 2 | 3 | rpng - simple PNG display program readpng.c 4 | 5 | --------------------------------------------------------------------------- 6 | 7 | Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. 8 | 9 | This software is provided "as is," without warranty of any kind, 10 | express or implied. In no event shall the author or contributors 11 | be held liable for any damages arising in any way from the use of 12 | this software. 13 | 14 | The contents of this file are DUAL-LICENSED. You may modify and/or 15 | redistribute this software according to the terms of one of the 16 | following two licenses (at your option): 17 | 18 | 19 | LICENSE 1 ("BSD-like with advertising clause"): 20 | 21 | Permission is granted to anyone to use this software for any purpose, 22 | including commercial applications, and to alter it and redistribute 23 | it freely, subject to the following restrictions: 24 | 25 | 1. Redistributions of source code must retain the above copyright 26 | notice, disclaimer, and this list of conditions. 27 | 2. Redistributions in binary form must reproduce the above copyright 28 | notice, disclaimer, and this list of conditions in the documenta- 29 | tion and/or other materials provided with the distribution. 30 | 3. All advertising materials mentioning features or use of this 31 | software must display the following acknowledgment: 32 | 33 | This product includes software developed by Greg Roelofs 34 | and contributors for the book, "PNG: The Definitive Guide," 35 | published by O'Reilly and Associates. 36 | 37 | 38 | LICENSE 2 (GNU GPL v2 or later): 39 | 40 | This program is free software; you can redistribute it and/or modify 41 | it under the terms of the GNU General Public License as published by 42 | the Free Software Foundation; either version 2 of the License, or 43 | (at your option) any later version. 44 | 45 | This program is distributed in the hope that it will be useful, 46 | but WITHOUT ANY WARRANTY; without even the implied warranty of 47 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 48 | GNU General Public License for more details. 49 | 50 | You should have received a copy of the GNU General Public License 51 | along with this program; if not, write to the Free Software Foundation, 52 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 53 | 54 | ---------------------------------------------------------------------------*/ 55 | /* 56 | * Modified by: Marek Zmysłowski 57 | * Copyrights: 2020 58 | * This file contains code to be fuzzed in persistent mode with libfiowrapper. 59 | */ 60 | 61 | #include 62 | #include 63 | 64 | #include 65 | 66 | #include "png.h" /* libpng header; includes zlib.h */ 67 | #include "readpng.h" /* typedefs, common macros, public prototypes */ 68 | 69 | __AFL_FUZZ_INIT(); 70 | extern void set_memory_size(ssize_t size); 71 | extern void set_memory_ptr(unsigned char *buffer); 72 | 73 | /* future versions of libpng will provide this macro: */ 74 | #ifndef png_jmpbuf 75 | # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 76 | #endif 77 | 78 | 79 | static png_structp png_ptr = NULL; 80 | static png_infop info_ptr = NULL; 81 | 82 | png_uint_32 width, height; 83 | int bit_depth, color_type; 84 | uch *image_data = NULL; 85 | 86 | 87 | void readpng_version_info(void) 88 | { 89 | fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n", 90 | PNG_LIBPNG_VER_STRING, png_libpng_ver); 91 | fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n", 92 | ZLIB_VERSION, zlib_version); 93 | } 94 | 95 | 96 | /* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */ 97 | 98 | int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight) 99 | { 100 | uch sig[8]; 101 | 102 | 103 | /* first do a quick check that the file really is a PNG image; could 104 | * have used slightly more general png_sig_cmp() function instead */ 105 | 106 | fread(sig, 1, 8, infile); 107 | if (!png_check_sig(sig, 8)) 108 | return 1; /* bad signature */ 109 | 110 | 111 | /* could pass pointers to user-defined error handlers instead of NULLs: */ 112 | 113 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 114 | if (!png_ptr) 115 | return 4; /* out of memory */ 116 | 117 | info_ptr = png_create_info_struct(png_ptr); 118 | if (!info_ptr) { 119 | png_destroy_read_struct(&png_ptr, NULL, NULL); 120 | return 4; /* out of memory */ 121 | } 122 | 123 | 124 | /* we could create a second info struct here (end_info), but it's only 125 | * useful if we want to keep pre- and post-IDAT chunk info separated 126 | * (mainly for PNG-aware image editors and converters) */ 127 | 128 | 129 | /* setjmp() must be called in every function that calls a PNG-reading 130 | * libpng function */ 131 | 132 | if (setjmp(png_jmpbuf(png_ptr))) { 133 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 134 | return 2; 135 | } 136 | 137 | 138 | png_init_io(png_ptr, infile); 139 | png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ 140 | 141 | png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ 142 | 143 | 144 | /* alternatively, could make separate calls to png_get_image_width(), 145 | * etc., but want bit_depth and color_type for later [don't care about 146 | * compression_type and filter_type => NULLs] */ 147 | 148 | png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 149 | NULL, NULL, NULL); 150 | *pWidth = width; 151 | *pHeight = height; 152 | 153 | 154 | /* OK, that's all we need for now; return happy */ 155 | 156 | return 0; 157 | } 158 | 159 | 160 | 161 | 162 | /* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error; 163 | * scales values to 8-bit if necessary */ 164 | 165 | int readpng_get_bgcolor(uch *red, uch *green, uch *blue) 166 | { 167 | png_color_16p pBackground; 168 | 169 | 170 | /* setjmp() must be called in every function that calls a PNG-reading 171 | * libpng function */ 172 | 173 | if (setjmp(png_jmpbuf(png_ptr))) { 174 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 175 | return 2; 176 | } 177 | 178 | 179 | if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) 180 | return 1; 181 | 182 | /* it is not obvious from the libpng documentation, but this function 183 | * takes a pointer to a pointer, and it always returns valid red, green 184 | * and blue values, regardless of color_type: */ 185 | 186 | png_get_bKGD(png_ptr, info_ptr, &pBackground); 187 | 188 | 189 | /* however, it always returns the raw bKGD data, regardless of any 190 | * bit-depth transformations, so check depth and adjust if necessary */ 191 | 192 | if (bit_depth == 16) { 193 | *red = pBackground->red >> 8; 194 | *green = pBackground->green >> 8; 195 | *blue = pBackground->blue >> 8; 196 | } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { 197 | if (bit_depth == 1) 198 | *red = *green = *blue = pBackground->gray? 255 : 0; 199 | else if (bit_depth == 2) 200 | *red = *green = *blue = (255/3) * pBackground->gray; 201 | else /* bit_depth == 4 */ 202 | *red = *green = *blue = (255/15) * pBackground->gray; 203 | } else { 204 | *red = (uch)pBackground->red; 205 | *green = (uch)pBackground->green; 206 | *blue = (uch)pBackground->blue; 207 | } 208 | 209 | return 0; 210 | } 211 | 212 | 213 | 214 | 215 | /* display_exponent == LUT_exponent * CRT_exponent */ 216 | 217 | uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) 218 | { 219 | double gamma; 220 | png_uint_32 i, rowbytes; 221 | png_bytepp row_pointers = NULL; 222 | 223 | 224 | /* setjmp() must be called in every function that calls a PNG-reading 225 | * libpng function */ 226 | 227 | if (setjmp(png_jmpbuf(png_ptr))) { 228 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 229 | return NULL; 230 | } 231 | 232 | 233 | /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits, 234 | * transparency chunks to full alpha channel; strip 16-bit-per-sample 235 | * images to 8 bits per sample; and convert grayscale to RGB[A] */ 236 | 237 | if (color_type == PNG_COLOR_TYPE_PALETTE) 238 | png_set_expand(png_ptr); 239 | if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) 240 | png_set_expand(png_ptr); 241 | if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 242 | png_set_expand(png_ptr); 243 | if (bit_depth == 16) 244 | png_set_strip_16(png_ptr); 245 | if (color_type == PNG_COLOR_TYPE_GRAY || 246 | color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 247 | png_set_gray_to_rgb(png_ptr); 248 | 249 | 250 | /* unlike the example in the libpng documentation, we have *no* idea where 251 | * this file may have come from--so if it doesn't have a file gamma, don't 252 | * do any correction ("do no harm") */ 253 | 254 | if (png_get_gAMA(png_ptr, info_ptr, &gamma)) 255 | png_set_gamma(png_ptr, display_exponent, gamma); 256 | 257 | 258 | /* all transformations have been registered; now update info_ptr data, 259 | * get rowbytes and channels, and allocate image memory */ 260 | 261 | png_read_update_info(png_ptr, info_ptr); 262 | 263 | *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr); 264 | *pChannels = (int)png_get_channels(png_ptr, info_ptr); 265 | 266 | if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) { 267 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 268 | return NULL; 269 | } 270 | if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { 271 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 272 | free(image_data); 273 | image_data = NULL; 274 | return NULL; 275 | } 276 | 277 | Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n", *pChannels, rowbytes, height)); 278 | 279 | 280 | /* set the individual row_pointers to point at the correct offsets */ 281 | 282 | for (i = 0; i < height; ++i) 283 | row_pointers[i] = image_data + i*rowbytes; 284 | 285 | 286 | /* now we can go ahead and just read the whole image */ 287 | 288 | png_read_image(png_ptr, row_pointers); 289 | 290 | 291 | /* and we're done! (png_read_end() can be omitted if no processing of 292 | * post-IDAT text/time/etc. is desired) */ 293 | 294 | free(row_pointers); 295 | row_pointers = NULL; 296 | 297 | png_read_end(png_ptr, NULL); 298 | 299 | return image_data; 300 | } 301 | 302 | 303 | void readpng_cleanup(int free_image_data) 304 | { 305 | if (free_image_data && image_data) { 306 | free(image_data); 307 | image_data = NULL; 308 | } 309 | 310 | if (png_ptr && info_ptr) { 311 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 312 | png_ptr = NULL; 313 | info_ptr = NULL; 314 | } 315 | } 316 | 317 | int main(int argc, char *argv[]) 318 | { 319 | FILE *infile; 320 | unsigned long h,w; 321 | uch red, green, blue; 322 | int pChannels; 323 | ulg pRowbytes; 324 | // Set the memory pointer 325 | set_memory_ptr(__AFL_FUZZ_TESTCASE_BUF); 326 | while (__AFL_LOOP(65535)) 327 | { 328 | // Set the file size. 329 | set_memory_size(__AFL_FUZZ_TESTCASE_LEN); 330 | image_data = NULL; 331 | infile = fopen(argv[1], "r"); 332 | if (!readpng_init(infile, &w, &h)) { 333 | readpng_get_bgcolor(&red, &green, &blue); 334 | image_data = readpng_get_image((2.2*1.0), &pChannels, &pRowbytes); 335 | readpng_cleanup(1); 336 | } 337 | fclose(infile); 338 | } 339 | } 340 | -------------------------------------------------------------------------------- /libfioinfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File I/O Functions Info 3 | * This library provides the statistics what functions where used during the execution. 4 | * 5 | * Author: Marek Zmysłowski 6 | * Version: 0.3 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at: 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * This is the real deal: the program takes an instrumented binary and 13 | * attempts a variety of basic fuzzing tricks, paying close attention to 14 | * how they affect the execution path. 15 | * 16 | */ 17 | 18 | #define _GNU_SOURCE 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include "libfiodef.h" 25 | 26 | // 27 | // Variables holding statistics 28 | // 29 | // Standard 30 | static int fopen_count; 31 | static int fwrite_count; 32 | static int fputc_count; 33 | static int fputs_count; 34 | static int fread_count; 35 | static int fseek_count; 36 | 37 | static int ftell_count; 38 | static int fgetc_count; 39 | static int fgets_count; 40 | static int fclose_count; 41 | 42 | // Nonlocking 43 | static int fwrite_unlocked_count; 44 | static int fputc_unlocked_count; 45 | static int fputs_unlocked_count; 46 | static int fread_unlocked_count; 47 | static int fgetc_unlocked_count; 48 | static int fgets_unlocked_count; 49 | 50 | // POSIX 51 | static int open_count; 52 | static int read_count; 53 | static int write_count; 54 | static int lseek_count; 55 | static int close_count; 56 | 57 | /* 58 | * fopen wrapper 59 | */ 60 | FILE *fopen(const char *path, const char *mode) 61 | { 62 | fopen_count++; 63 | #ifdef DEBUG 64 | printf("fopen - path:%s, mode:%s\n", path, mode); 65 | #endif 66 | return _libc_fopen(path, mode); 67 | } 68 | 69 | #if defined(_LARGEFILE64_SOURCE) && !defined(__APPLE__) 70 | FILE *fopen64(const char *path, const char *mode) 71 | { 72 | fopen_count++; 73 | #ifdef DEBUG 74 | printf("fopen - path:%s, mode:%s\n", path, mode); 75 | #endif 76 | return _libc_fopen64(path, mode); 77 | } 78 | #endif 79 | 80 | /**************************************************************************************************** 81 | * 82 | * Standard stdio function wrappers 83 | * 84 | ****************************************************************************************************/ 85 | 86 | /* 87 | * fwrite wrapper 88 | */ 89 | size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 90 | { 91 | if (stream != stderr && stream != stdout) 92 | fwrite_count++; 93 | #ifdef DEBUG 94 | printf("fwrite - stream:%p, buffer:%p, size:%ld, nmemb:%ld\n", stream, ptr, size, nmemb); 95 | #endif 96 | return _libc_fwrite(ptr, size, nmemb, stream); 97 | } 98 | 99 | /* 100 | * fputc wrapper 101 | */ 102 | int fputc(int character, FILE *stream) 103 | { 104 | if (stream != stderr && stream != stdout) 105 | fputc_count++; 106 | #ifdef DEBUG 107 | printf("fputc - stream:%p, character:%x \n", stream, character); 108 | #endif 109 | return _libc_fputc(character, stream); 110 | } 111 | 112 | /* 113 | * fputs wrapper 114 | */ 115 | int fputs(const char *str, FILE *stream) 116 | { 117 | if (stream != stderr && stream != stdout) 118 | fputs_count++; 119 | #ifdef DEBUG 120 | printf("fputs - stream:%p, buffer:%s\n", stream, str); 121 | #endif 122 | return _libc_fputs(str, stream); 123 | } 124 | 125 | /* 126 | * fread wrapper 127 | */ 128 | size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 129 | { 130 | if (stream != stderr && stream != stdout) 131 | fread_count++; 132 | #ifdef DEBUG 133 | printf("fread - stream:%p, buffer:%p, size:%ld, nmemb:%ld\n", stream, ptr, size, nmemb); 134 | #endif 135 | return _libc_fread(ptr, size, nmemb, stream); 136 | } 137 | 138 | /* 139 | * fseek wrapper 140 | */ 141 | int fseek(FILE *stream, long offset, int whence) 142 | { 143 | if (stream != stderr && stream != stdout) 144 | fseek_count++; 145 | #ifdef DEBUG 146 | printf("fseek - stream:%p, offest:%ld, whence:%d\n", stream, offset, whence); 147 | #endif 148 | return _libc_fseek(stream, offset, whence); 149 | } 150 | 151 | /* 152 | * fgetc wrapper 153 | */ 154 | int fgetc(FILE *stream) 155 | { 156 | if (stream != stderr && stream != stdout) 157 | fgetc_count++; 158 | #ifdef DEBUG 159 | printf("fgetc - stream:%p\n", stream); 160 | #endif 161 | return _libc_fgetc(stream); 162 | } 163 | 164 | /* 165 | * fgets wrapper 166 | */ 167 | char *fgets(char *str, int num, FILE *stream) 168 | { 169 | if (stream != stderr && stream != stdout) 170 | fgets_count++; 171 | #ifdef DEBUG 172 | printf("fgets - stream:%p, buffer:%s, size:%d\n", stream, str, num); 173 | #endif 174 | return _libc_fgets(str, num, stream); 175 | } 176 | 177 | ///////////////////////////////////////////////////////////////////////////////////////////////// 178 | /* 179 | * ftell wrapper 180 | */ 181 | long ftell(FILE *stream) 182 | { 183 | if (stream != stderr && stream != stdout) 184 | ftell_count++; 185 | #ifdef DEBUG 186 | printf("ftell - stream:%p\n", stream); 187 | #endif 188 | return _libc_ftell(stream); 189 | } 190 | 191 | off_t ftello(FILE *stream) 192 | { 193 | if (stream != stderr && stream != stdout) 194 | ftell_count++; 195 | #ifdef DEBUG 196 | printf("ftello - stream:%p\n", stream); 197 | #endif 198 | return _libc_ftello(stream); 199 | } 200 | 201 | #if defined(_LARGEFILE64_SOURCE) && !defined(__APPLE__) 202 | off64_t ftello64(FILE *stream) 203 | { 204 | if (stream != stderr && stream != stdout) 205 | ftell_count++; 206 | #ifdef DEBUG 207 | printf("ftello64 - stream:%p\n", stream); 208 | #endif 209 | return _libc_ftello64(stream); 210 | } 211 | #endif 212 | 213 | ///////////////////////////////////////////////////////////////////////////////////////////////// 214 | /* 215 | * fclose wrapper 216 | */ 217 | int fclose(FILE *stream) 218 | { 219 | if (stream != stderr && stream != stdout) 220 | fclose_count++; 221 | #ifdef DEBUG 222 | printf("fclose - stream:%p\n", stream); 223 | #endif 224 | return _libc_fclose(stream); 225 | } 226 | 227 | /**************************************************************************************************** 228 | * 229 | * Nonlocking stdio function wrappers 230 | * 231 | ****************************************************************************************************/ 232 | 233 | /* 234 | * fwrite_unlocked wrapper 235 | */ 236 | #ifndef __OPTIMIZE__ 237 | size_t fwrite_unlocked(const void *ptr, size_t size, size_t nmemb, FILE *stream) 238 | { 239 | if (stream != stderr && stream != stdout) 240 | fwrite_unlocked_count++; 241 | #ifdef DEBUG 242 | printf("fwrite_unlocked - stream:%p, buffer:%p, size:%ld, nmemb:%ld\n", stream, ptr, size, nmemb); 243 | #endif 244 | return _libc_fwrite_unlocked(ptr, size, nmemb, stream); 245 | } 246 | #endif 247 | /* 248 | * fputc_unlocked wrapper 249 | */ 250 | int fputc_unlocked(int character, FILE *stream) 251 | { 252 | if (stream != stderr && stream != stdout) 253 | fputc_unlocked_count++; 254 | #ifdef DEBUG 255 | printf("fputs_unlocked - stream:%p, character:%c \n", stream, character); 256 | #endif 257 | return _libc_fputc_unlocked(character, stream); 258 | } 259 | 260 | /* 261 | * fputs_unlocked wrapper 262 | */ 263 | int fputs_unlocked(const char *str, FILE *stream) 264 | { 265 | if (stream != stderr && stream != stdout) 266 | fputs_unlocked_count++; 267 | #ifdef DEBUG 268 | printf("fputs_unlocked - stream:%p, buffer:%s\n", stream, str); 269 | #endif 270 | return _libc_fputs_unlocked(str, stream); 271 | } 272 | 273 | /* 274 | * fread_unlocked wrapper 275 | */ 276 | #ifndef __OPTIMIZE__ 277 | size_t fread_unlocked(void *ptr, size_t size, size_t nmemb, FILE *stream) 278 | { 279 | if (stream != stderr && stream != stdout) 280 | fread_unlocked_count++; 281 | #ifdef DEBUG 282 | printf("fread_unlocked - stream:%p, buffer:%p, size:%ld, nmemb:%ld\n", stream, ptr, size, nmemb); 283 | #endif 284 | return _libc_fread_unlocked(ptr, size, nmemb, stream); 285 | } 286 | #endif 287 | /* 288 | * fgetc_unlocked wrapper 289 | */ 290 | int fgetc_unlocked(FILE *stream) 291 | { 292 | if (stream != stderr && stream != stdout) 293 | fgetc_unlocked_count++; 294 | #ifdef DEBUG 295 | printf("fgetc_unlocked - stream:%p\n", stream); 296 | #endif 297 | return _libc_fgetc_unlocked(stream); 298 | } 299 | 300 | /* 301 | * fgets_unlocked wrapper 302 | */ 303 | char *fgets_unlocked(char *str, int num, FILE *stream) 304 | { 305 | if (stream != stderr && stream != stdout) 306 | fgets_unlocked_count++; 307 | #ifdef DEBUG 308 | printf("fgets_unlocked - stream:%p, buffer:%s, size:%d\n", stream, str, num); 309 | #endif 310 | return _libc_fgets_unlocked(str, num, stream); 311 | } 312 | 313 | int open(const char *pathname, int flags, ...) 314 | { 315 | open_count++; 316 | #ifdef DEBUG 317 | printf("open - path:%s\n", pathname); 318 | #endif 319 | return _posix_open(pathname, flags); 320 | } 321 | 322 | ssize_t read(int fd, void *buf, size_t count) 323 | { 324 | read_count++; 325 | #ifdef DEBUG 326 | printf("read - fd %d, buf:%p, count:%ld\n", fd, buf, count); 327 | #endif 328 | return _posix_read(fd, buf, count); 329 | } 330 | 331 | ssize_t write(int fd, const void *buf, size_t count) 332 | { 333 | write_count++; 334 | #ifdef DEBUG 335 | printf("write - fd %d, buf:%p, count:%ld\n", fd, buf, count); 336 | #endif 337 | return _posix_write(fd, buf, count); 338 | } 339 | 340 | off_t lseek(int fd, off_t offset, int whence) 341 | { 342 | lseek_count++; 343 | #ifdef DEBUG 344 | printf("lseek - fd %d, offset:%ld, whence:%d\n", fd, offset, whence); 345 | #endif 346 | return _posix_lseek(fd, offset, whence); 347 | } 348 | 349 | int close(int fd) 350 | { 351 | close_count++; 352 | #ifdef DEBUG 353 | printf("close - fd %d\n", fd); 354 | #endif 355 | return _posix_close(fd); 356 | } 357 | 358 | /* 359 | * Fuction prints the banner and the library info 360 | */ 361 | void show_banner() 362 | { 363 | printf("===========================================\n"); 364 | printf("\t\tlibfioinfo\n"); 365 | printf("Version: 0.3\n"); 366 | printf("Author: Marek Zmysłowski\n"); 367 | printf("===========================================\n\n"); 368 | } 369 | 370 | /* 371 | * Function that prints statistics of the function calls 372 | */ 373 | void show_results() 374 | { 375 | printf("===========================================\n"); 376 | printf("\tFile calls statistics:\n"); 377 | printf("fopen: %d\n", fopen_count); 378 | printf("fwrite: %d - unlocked: %d\n", fwrite_count, fwrite_unlocked_count); 379 | printf("fputc: %d - unlocked: %d\n", fputc_count, fputc_unlocked_count); 380 | printf("fputs: %d - unlocked: %d\n", fputs_count, fputs_unlocked_count); 381 | printf("fread: %d - unlocked: %d\n", fread_count, fread_unlocked_count); 382 | printf("fgetc: %d - unlocked: %d\n", fgetc_count, fgetc_unlocked_count); 383 | printf("fgets: %d - unlocked: %d\n", fgets_count, fgets_unlocked_count); 384 | printf("fseek: %d\n", fseek_count); 385 | printf("ftell: %d\n", ftell_count); 386 | printf("fclose: %d\n", fclose_count); 387 | printf ("\n"); 388 | printf("open: %d\n", open_count); 389 | printf("read: %d\n", read_count); 390 | printf("write: %d\n", write_count); 391 | printf("lseek: %d\n", lseek_count); 392 | printf("close: %d\n", close_count); 393 | printf("===========================================\n"); 394 | } 395 | 396 | /* 397 | * Library constructor 398 | */ 399 | __attribute__((constructor)) static void init(void) 400 | { 401 | _libc_fopen = (FILE * (*)(const char *path, const char *mode)) dlsym(RTLD_NEXT, "fopen"); 402 | 403 | _libc_fwrite = (size_t (*)(const void *ptr, size_t size, size_t nmemb, FILE *stream))dlsym(RTLD_NEXT, "fwrite"); 404 | _libc_fputc = (int (*)(int character, FILE *fp))dlsym(RTLD_NEXT, "fputc"); 405 | _libc_fputs = (int (*)(const char *str, FILE *fp))dlsym(RTLD_NEXT, "fputs"); 406 | _libc_fread = (size_t (*)(void *ptr, size_t size, size_t nmemb, FILE *stream))dlsym(RTLD_NEXT, "fread"); 407 | _libc_fgetc = (int (*)(FILE * fp)) dlsym(RTLD_NEXT, "fgetc"); 408 | _libc_fgets = (char *(*)(char *str, int num, FILE *fp))dlsym(RTLD_NEXT, "fgets"); 409 | 410 | _libc_fseek = (int (*)(FILE * stream, long offset, int whence)) dlsym(RTLD_NEXT, "fseek"); 411 | _libc_fseeko = (int (*)(FILE * stream, off_t offset, int whence)) dlsym(RTLD_NEXT, "fseeko"); 412 | 413 | _libc_ftell = (long (*)(FILE * fp)) dlsym(RTLD_NEXT, "ftell"); 414 | _libc_ftello = (off_t (*)(FILE * fp)) dlsym(RTLD_NEXT, "ftello"); 415 | 416 | #if defined(_LARGEFILE64_SOURCE) && !defined(__APPLE__) 417 | _libc_fopen64 = (FILE * (*)(const char *path, const char *mode)) dlsym(RTLD_NEXT, "fopen64"); 418 | _libc_ftello64 = (off64_t(*)(FILE * fp)) dlsym(RTLD_NEXT, "ftello64"); 419 | _libc_fseeko64 = (int (*)(FILE * stream, off64_t offset, int whence)) dlsym(RTLD_NEXT, "fseeko64"); 420 | #endif 421 | 422 | _libc_fclose = (int (*)(FILE * fp)) dlsym(RTLD_NEXT, "fclose"); 423 | 424 | _libc_fwrite_unlocked = (size_t (*)(const void *ptr, size_t size, size_t nmemb, FILE *stream))dlsym(RTLD_NEXT, "fwrite_unlocked"); 425 | _libc_fputc_unlocked = (int (*)(int character, FILE *fp))dlsym(RTLD_NEXT, "fputc_unlocked"); 426 | _libc_fputs_unlocked = (int (*)(const char *str, FILE *fp))dlsym(RTLD_NEXT, "fputs_unlocked"); 427 | _libc_fread_unlocked = (size_t(*)(void *ptr, size_t size, size_t nmemb, FILE *stream))dlsym(RTLD_NEXT, "fread_unlocked"); 428 | _libc_fgetc_unlocked = (int (*)(FILE * fp)) dlsym(RTLD_NEXT, "fgetc_unlocked"); 429 | _libc_fgets_unlocked = (char *(*)(char *str, int num, FILE *fp))dlsym(RTLD_NEXT, "fgets_unlocked"); 430 | 431 | _posix_open = (int (*)(const char *pathname, int flags, ...))dlsym(RTLD_NEXT, "open"); 432 | _posix_read = (ssize_t (*)(int fd, void *buf, size_t count))dlsym(RTLD_NEXT, "read"); 433 | _posix_write = (ssize_t (*)(int fd, const void *buf, size_t count))dlsym(RTLD_NEXT, "write"); 434 | _posix_lseek = (off_t (*)(int fd, off_t offset, int whence))dlsym(RTLD_NEXT, "lseek"); 435 | _posix_close = (int (*)(int fd))dlsym(RTLD_NEXT, "close"); 436 | 437 | fopen_count = 0; 438 | fwrite_count = 0; 439 | fputc_count = 0; 440 | fputs_count = 0; 441 | fread_count = 0; 442 | fgetc_count = 0; 443 | fgets_count = 0; 444 | fseek_count = 0; 445 | ftell_count = 0; 446 | fclose_count = 0; 447 | 448 | fwrite_unlocked_count = 0; 449 | fputc_unlocked_count = 0; 450 | fputs_unlocked_count = 0; 451 | fread_unlocked_count = 0; 452 | fgetc_unlocked_count = 0; 453 | fgets_unlocked_count = 0; 454 | 455 | open_count = 0; 456 | read_count = 0; 457 | write_count = 0; 458 | lseek_count = 0; 459 | close_count = 0; 460 | 461 | show_banner(); 462 | } 463 | 464 | /* 465 | * Library destructor 466 | */ 467 | __attribute__((destructor)) static void unload(void) 468 | { 469 | show_results(); 470 | } -------------------------------------------------------------------------------- /libfiowrapper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File I/O Functions Info 3 | * This library provides the statistics what functions where used during the execution. 4 | * 5 | * Author: Marek Zmysłowski 6 | * Version: 0.3 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at: 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * This is the real deal: the program takes an instrumented binary and 13 | * attempts a variety of basic fuzzing tricks, paying close attention to 14 | * how they affect the execution path. 15 | * 16 | */ 17 | 18 | #define _GNU_SOURCE 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "libfiodef.h" 27 | 28 | #define AFL_FILE_NAME ".cur_input" 29 | struct _AFL_MEMORY_FILE_ 30 | { 31 | // This definition is very limited for now 32 | FILE *stream; 33 | unsigned char *buffer; 34 | int read_pointer; 35 | ssize_t size; 36 | int memory; 37 | int fd; 38 | } afl_input_file; 39 | 40 | // This is used to speed up the process of allocating the FILE structure for the AFL input file/ 41 | // This needs to be done as valid pointer to the FILE struct needs to be returned 42 | // QUESTION: does this structur needs to contain any real values or can be zeroed as it caputer all f* calls 43 | FILE _fake_file; 44 | 45 | /* 46 | * Function sets the pointer for the shared memory from the AFL. 47 | */ 48 | void set_memory_ptr(unsigned char *buffer) 49 | { 50 | #ifdef DEBUG 51 | printf("set_memory_ptr:%p\n", buffer); 52 | #endif 53 | afl_input_file.size = 0; 54 | afl_input_file.buffer = buffer; 55 | afl_input_file.memory = 1; 56 | afl_input_file.read_pointer = 0; 57 | afl_input_file.stream = &_fake_file; 58 | } 59 | 60 | /* 61 | * Function sets the "size" of the shared memory. 62 | * The shared memory from AFL is fixed size. This is needed to understand where the input ends. 63 | */ 64 | void set_memory_size(ssize_t size) 65 | { 66 | #ifdef DEBUG 67 | printf("set_memory_size:%ld\n", size); 68 | #endif 69 | afl_input_file.size = size; 70 | afl_input_file.read_pointer = 0; 71 | } 72 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 73 | 74 | /* 75 | * fopen wrapper 76 | * 77 | * If the memory was not initialized, the function will open file, copy it to memory and return fake structure. 78 | * If the memory was initialized, it just return the fake structure. 79 | * 80 | * TODO: Add fopen64 when requested. Investigate if requires. 81 | */ 82 | FILE *_fopen(const char *path, const char *mode) 83 | { 84 | #ifdef DEBUG 85 | printf("fopen - path:%s, mode:%s\n", path, mode); 86 | #endif 87 | if (strstr(path, AFL_FILE_NAME) != NULL) 88 | { 89 | // AFL input file 90 | if (!afl_input_file.memory) 91 | { 92 | #ifdef DEBUG 93 | printf("fopen - loading file into memory\n"); 94 | #endif 95 | afl_input_file.stream = _libc_fopen(path, mode); 96 | /* Get the number of bytes */ 97 | _libc_fseek(afl_input_file.stream, 0L, SEEK_END); 98 | afl_input_file.size = _libc_ftell(afl_input_file.stream); 99 | _libc_fseek(afl_input_file.stream, 0L, SEEK_SET); 100 | 101 | 102 | #ifdef DEBUG 103 | printf("fopen - size:%ld\n", afl_input_file.size); 104 | #endif 105 | afl_input_file.buffer = malloc(afl_input_file.size + 1); 106 | _libc_fread(afl_input_file.buffer, 1, afl_input_file.size, afl_input_file.stream); 107 | afl_input_file.read_pointer = 0; 108 | } 109 | return afl_input_file.stream; 110 | } 111 | // The other file is requested to be opened 112 | return _libc_fopen(path, mode); 113 | } 114 | 115 | FILE *fopen(const char *path, const char *mode) 116 | { 117 | return _fopen(path, mode); 118 | } 119 | 120 | #if defined(_LARGEFILE64_SOURCE) && !defined(__APPLE__) 121 | FILE *fopen64(const char *path, const char *mode) 122 | { 123 | return _fopen(path, mode); 124 | } 125 | #endif 126 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 127 | /* 128 | * fwrite wrapper 129 | * 130 | * Currently the assumption is, that the data stored by the application are not used at all so 131 | * it just fakes the data were written. 132 | * 133 | * Note: The other functionality is not implemented. I assume that the fuzzed application is not writing to the input 134 | */ 135 | 136 | size_t _fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 137 | { 138 | return size * nmemb; 139 | } 140 | 141 | size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 142 | { 143 | #ifdef DEBUG 144 | printf("fwrite - stream:%p, buffer:%p, size:%ld, nmemb:%ld\n", stream, ptr, size, nmemb); 145 | #endif 146 | return _fwrite(ptr, size, nmemb, stream); 147 | } 148 | 149 | // 150 | // fwrite_unlocked in optimized version is a preprocessor declaration that uses fputc_unlocked 151 | // 152 | #ifndef __OPTIMIZE__ 153 | size_t fwrite_unlocked(const void *ptr, size_t size, size_t nmemb, FILE *stream) 154 | { 155 | #ifdef DEBUG 156 | printf("fwrite - stream:%p, buffer:%p, size:%ld, nmemb:%ld\n", stream, ptr, size, nmemb); 157 | #endif 158 | return _fwrite(ptr, size, nmemb, stream); 159 | } 160 | #endif 161 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 162 | /* 163 | * fputc wrapper 164 | * 165 | * The function fakes that the write operation was performed. 166 | * 167 | * Note: The other functionality is not implemented. I assume that the fuzzed application is not writing to the input. 168 | */ 169 | int _fputc(int character, FILE *stream) 170 | { 171 | return character; 172 | } 173 | 174 | int fputc(int character, FILE *stream) 175 | { 176 | #ifdef DEBUG 177 | printf("fputc - stream:%p, character:0x%.2X\n", stream, character); 178 | #endif 179 | return _fputc(character, stream); 180 | } 181 | 182 | int fputc_unlocked(int character, FILE *stream) 183 | { 184 | #ifdef DEBUG 185 | printf("fputc_unlocked - stream:%p, character:0x%.2X\n", stream, character); 186 | #endif 187 | return _fputc(character, stream); 188 | } 189 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 190 | /* 191 | * fputs wrapper 192 | * 193 | * The function fakes that the write operation was performed. 194 | * TODO: verify what exact value is returned on success. 195 | * 196 | * Note: The other functionality is not implemented. I assume that the fuzzed application is not writing to the input. 197 | */ 198 | int _fputs(const char *str, FILE *stream) 199 | { 200 | return 1; 201 | } 202 | 203 | int fputs(const char *str, FILE *stream) 204 | { 205 | #ifdef DEBUG 206 | printf("fputs - stream:%p, buffer:%s\n", stream, str); 207 | #endif 208 | return _fputs(str, stream); 209 | } 210 | 211 | // 212 | // fputs_unlocked in optimized version is a preprocessor declaration that uses fputc_unlocked 213 | // 214 | #ifndef __OPTIMIZE__ 215 | int fputs_unlocked(const char *str, FILE *stream) 216 | { 217 | #ifdef DEBUG 218 | printf("fputs_unlocked - stream:%p, buffer:%s\n", stream, str); 219 | #endif 220 | return _fputs(str, stream); 221 | } 222 | #endif 223 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 224 | /* 225 | * fread wrapper 226 | */ 227 | size_t _fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 228 | { 229 | if (stream == afl_input_file.stream) 230 | { 231 | size_t bytes_to_copy_left = size * nmemb; 232 | size_t bytes_copied = 0; 233 | while (bytes_to_copy_left) 234 | { 235 | if (afl_input_file.read_pointer == afl_input_file.size) 236 | break; 237 | ((char *)ptr)[bytes_copied] = afl_input_file.buffer[afl_input_file.read_pointer]; 238 | afl_input_file.read_pointer++; 239 | bytes_to_copy_left--; 240 | bytes_copied++; 241 | } 242 | return bytes_copied; 243 | } 244 | else 245 | { 246 | return _libc_fread(ptr, size, nmemb, stream); 247 | } 248 | } 249 | 250 | size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 251 | { 252 | #ifdef DEBUG 253 | printf("fread - stream:%p, buffer:%p, size:%ld, nmemb:%ld\n", stream, ptr, size, nmemb); 254 | #endif 255 | return _fread(ptr, size, nmemb, stream); 256 | } 257 | 258 | // 259 | // fread_unlocked in optimized version is a preprocessor declaration that uses fgetc_unlocked 260 | // 261 | #ifndef __OPTIMIZE__ 262 | size_t fread_unlocked(void *ptr, size_t size, size_t nmemb, FILE *stream) 263 | { 264 | #ifdef DEBUG 265 | printf("fread_unlocked - stream:%p, buffer:%p, size:%ld, nmemb:%ld\n", stream, ptr, size, nmemb); 266 | #endif 267 | return _fread(ptr, size, nmemb, stream); 268 | } 269 | #endif 270 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 271 | /* 272 | * fgetc wrapper 273 | */ 274 | int _fgetc(FILE *stream) 275 | { 276 | char c; 277 | if (stream == afl_input_file.stream) 278 | { 279 | if (afl_input_file.read_pointer == afl_input_file.size) 280 | { 281 | // This is the end of the file 282 | return EOF; 283 | } 284 | c = afl_input_file.buffer[afl_input_file.read_pointer]; 285 | afl_input_file.read_pointer++; 286 | return (unsigned char)c; 287 | } 288 | else 289 | { 290 | return _libc_fgetc(stream); 291 | } 292 | } 293 | 294 | int fgetc(FILE *stream) 295 | { 296 | #ifdef DEBUG 297 | char c = _fgetc(stream); 298 | printf("fgetc - stream:%p, returned:0x%.2X\n", stream, c); 299 | return c; 300 | #else 301 | return _fgetc(stream); 302 | #endif 303 | } 304 | 305 | int fgetc_unlocked(FILE *stream) 306 | { 307 | #ifdef DEBUG 308 | char c = _fgetc(stream); 309 | printf("fgetc_unlocked - stream:%p, returned:0x%.2X\n", stream, c); 310 | return c; 311 | #else 312 | return _fgetc(stream); 313 | #endif 314 | } 315 | 316 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 317 | /* 318 | * fgets wrapper 319 | * 320 | * TODO: Fix the function. 321 | */ 322 | char *_fgets(char *str, int num, FILE *stream) 323 | { 324 | return NULL; 325 | } 326 | 327 | char *fgets(char *str, int num, FILE *stream) 328 | { 329 | #ifdef DEBUG 330 | printf("fgets - stream:%p, str:%s, num:%d\n", stream, str, num); 331 | #endif 332 | return _fgets(str, num, stream); 333 | } 334 | 335 | char *fgets_unlocked(char *str, int num, FILE *stream) 336 | { 337 | #ifdef DEBUG 338 | printf("fgets_unlocked - stream:%p, str:%s, num:%d\n", stream, str, num); 339 | #endif 340 | return _fgets(str, num, stream); 341 | } 342 | 343 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 344 | /* 345 | * fseek wrapper 346 | * 347 | * TODO: Make sure that the offsets are correct. 348 | */ 349 | int _fseek(FILE *fp, off64_t offset, int whence) { 350 | switch (whence) 351 | { 352 | case SEEK_CUR: 353 | case SEEK_END: 354 | if (afl_input_file.read_pointer + offset >= afl_input_file.size || afl_input_file.read_pointer + offset < 0) 355 | { 356 | afl_input_file.read_pointer = afl_input_file.size; 357 | return EOF; 358 | } 359 | else 360 | { 361 | afl_input_file.read_pointer += offset; 362 | return 0; 363 | } 364 | break; 365 | case SEEK_SET: 366 | if (offset >= afl_input_file.size) 367 | return EOF; 368 | else 369 | afl_input_file.read_pointer = offset; 370 | return 0; 371 | break; 372 | default: 373 | return EOF; 374 | } 375 | } 376 | 377 | int fseek(FILE *stream, long offset, int whence) 378 | { 379 | #ifdef DEBUG 380 | printf("fseek - stream:%p, offset:%ld, whence:%d\n", stream, offset, whence); 381 | #endif 382 | if (stream == afl_input_file.stream) 383 | return _fseek(stream, offset, whence); 384 | return _libc_fseek(stream, offset, whence); 385 | } 386 | 387 | int fseeko(FILE *stream, off_t offset, int whence) 388 | { 389 | #ifdef DEBUG 390 | printf("fseeko - stream:%p, offset:%ld, whence:%d\n", stream, offset, whence); 391 | #endif 392 | if (stream == afl_input_file.stream) 393 | return _fseek(stream, offset, whence); 394 | return _libc_fseeko(stream, offset, whence); 395 | } 396 | 397 | int fseeko64(FILE *stream, off64_t offset, int whence) 398 | { 399 | #ifdef DEBUG 400 | printf("fseeko64 - stream:%p, offset:%ld, whence:%d\n", stream, offset, whence); 401 | #endif 402 | if (stream == afl_input_file.stream) 403 | return _fseek(stream, offset, whence); 404 | return _libc_fseeko64(stream, offset, whence); 405 | } 406 | 407 | long ftell(FILE *stream) 408 | { 409 | #ifdef DEBUG 410 | printf("ftell - stream:%p\n", stream); 411 | #endif 412 | if (stream == afl_input_file.stream) 413 | { 414 | return afl_input_file.read_pointer; 415 | } 416 | else 417 | { 418 | return _libc_ftell(stream); 419 | } 420 | } 421 | #if defined(_LARGEFILE64_SOURCE) && !defined(__APPLE__) 422 | off_t ftello64(FILE *stream) 423 | { 424 | #ifdef DEBUG 425 | printf("ftello64 - stream:%p\n", stream); 426 | #endif 427 | if (stream == afl_input_file.stream) 428 | { 429 | return (off_t)afl_input_file.read_pointer; 430 | } 431 | else 432 | { 433 | return _libc_ftello64(stream); 434 | } 435 | } 436 | #endif 437 | 438 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 439 | /* 440 | * fclose wrapper 441 | */ 442 | int fclose(FILE *stream) 443 | { 444 | #ifdef DEBUG 445 | printf("fclose - stream:%p\n", stream); 446 | #endif 447 | if (stream == afl_input_file.stream) 448 | { 449 | if (!afl_input_file.memory) 450 | return _libc_fclose(stream); 451 | else 452 | return 0; 453 | } 454 | else 455 | return _libc_fclose(stream); 456 | } 457 | 458 | // TODO Fix argument passing 459 | int open(const char *pathname, int flags, ...) 460 | { 461 | #ifdef DEBUG 462 | printf("open - path:%s\n", pathname); 463 | #endif 464 | if (strstr(pathname, AFL_FILE_NAME) != NULL) 465 | { 466 | if (!afl_input_file.memory) 467 | { 468 | // TODO Fix later 469 | } 470 | return afl_input_file.fd; 471 | } 472 | return _posix_open(pathname, flags); 473 | } 474 | 475 | ssize_t read(int fd, void *buf, size_t count) 476 | { 477 | #ifdef DEBUG 478 | printf("read - fd %d, buf:%p, count:%ld\n", fd, buf, count); 479 | #endif 480 | if (fd == afl_input_file.fd) 481 | { 482 | size_t bytes_to_copy_left = count; 483 | size_t bytes_copied = 0; 484 | while (bytes_to_copy_left) 485 | { 486 | if (afl_input_file.read_pointer == afl_input_file.size) 487 | break; 488 | ((char *)buf)[bytes_copied] = afl_input_file.buffer[afl_input_file.read_pointer]; 489 | afl_input_file.read_pointer++; 490 | bytes_to_copy_left--; 491 | bytes_copied++; 492 | } 493 | return bytes_copied; 494 | } 495 | else 496 | { 497 | return _posix_read(fd, buf, count); 498 | } 499 | } 500 | 501 | ssize_t write(int fd, const void *buf, size_t count) 502 | { 503 | #ifdef DEBUG 504 | printf("write - fd %d, buf:%p, count:%ld\n", fd, buf, count); 505 | #endif 506 | return _posix_write(fd, buf, count); 507 | } 508 | 509 | off_t lseek(int fd, off_t offset, int whence) 510 | { 511 | #ifdef DEBUG 512 | printf("lseek - fd %d, offset:%ld, whence:%d\n", fd, offset, whence); 513 | #endif 514 | if (fd == afl_input_file.fd) 515 | { 516 | switch (whence) 517 | { 518 | case SEEK_CUR: 519 | case SEEK_END: 520 | if (afl_input_file.read_pointer + offset >= afl_input_file.size || afl_input_file.read_pointer + offset < 0) 521 | { 522 | afl_input_file.read_pointer = afl_input_file.size; 523 | return EOF; 524 | } 525 | else 526 | { 527 | afl_input_file.read_pointer += offset; 528 | return 0; 529 | } 530 | break; 531 | case SEEK_SET: 532 | if (offset >= afl_input_file.size) 533 | return EOF; 534 | else 535 | afl_input_file.read_pointer = offset; 536 | return 0; 537 | break; 538 | default: 539 | return EOF; 540 | } 541 | } 542 | else 543 | { 544 | return _posix_lseek(fd, offset, whence); 545 | } 546 | } 547 | 548 | int close(int fd) 549 | { 550 | #ifdef DEBUG 551 | printf("close - fd %d\n", fd); 552 | #endif 553 | if (fd == afl_input_file.fd) 554 | { 555 | // TODO Fix this 556 | return 0; 557 | } 558 | else 559 | return _posix_close(fd); 560 | } 561 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 562 | /* 563 | * fileno wrapper 564 | */ 565 | int fileno(FILE *stream) 566 | { 567 | #ifdef DEBUG 568 | printf("fileno - stream:%p\n", stream); 569 | #endif 570 | if (stream == afl_input_file.stream) 571 | return afl_input_file.fd; 572 | return _libc_fileno(stream); 573 | } 574 | 575 | #ifndef __OPTIMIZE__ 576 | int fileno_unlocked(FILE *stream) 577 | { 578 | #ifdef DEBUG 579 | printf("fileno_unlocked - stream:%p\n", stream); 580 | #endif 581 | if (stream == afl_input_file.stream) 582 | return afl_input_file.fd; 583 | return _libc_fileno_unlocked(stream); 584 | } 585 | #endif 586 | 587 | 588 | /* 589 | * Library constructor 590 | */ 591 | __attribute__((constructor)) static void init(void) 592 | { 593 | // TODO Remove unused functions 594 | _libc_fopen = (FILE * (*)(const char *path, const char *mode)) dlsym(RTLD_NEXT, "fopen"); 595 | 596 | _libc_fwrite = (size_t(*)(const void *ptr, size_t size, size_t nmemb, FILE *stream))dlsym(RTLD_NEXT, "fwrite"); 597 | _libc_fputc = (int (*)(int character, FILE *fp))dlsym(RTLD_NEXT, "fputc"); 598 | _libc_fputs = (int (*)(const char *str, FILE *fp))dlsym(RTLD_NEXT, "fputs"); 599 | _libc_fread = (size_t(*)(void *ptr, size_t size, size_t nmemb, FILE *stream))dlsym(RTLD_NEXT, "fread"); 600 | _libc_fseek = (int (*)(FILE * stream, long offset, int whence)) dlsym(RTLD_NEXT, "fseek"); 601 | _libc_fseeko = (int (*)(FILE * stream, off_t offset, int whence)) dlsym(RTLD_NEXT, "fseeko"); 602 | _libc_fseeko64 = (int (*)(FILE * stream, off64_t offset, int whence)) dlsym(RTLD_NEXT, "fseeko64"); 603 | _libc_ftell = (long (*)(FILE * stream)) dlsym(RTLD_NEXT, "ftell"); 604 | _libc_fgetc = (int (*)(FILE * fp)) dlsym(RTLD_NEXT, "fgetc"); 605 | _libc_fgets = (char *(*)(char *str, int num, FILE *fp))dlsym(RTLD_NEXT, "fgets"); 606 | _libc_fclose = (int (*)(FILE * fp)) dlsym(RTLD_NEXT, "fclose"); 607 | 608 | #if defined(_LARGEFILE64_SOURCE) && !defined(__APPLE__) 609 | _libc_fopen64 = (FILE * (*)(const char *path, const char *mode)) dlsym(RTLD_NEXT, "fopen64"); 610 | _libc_ftello64 = (off_t (*)(FILE * stream)) dlsym(RTLD_NEXT, "ftello64"); 611 | #endif 612 | _libc_fileno = (int (*)(FILE *stream))dlsym(RTLD_NEXT, "fileno"); 613 | 614 | _libc_fwrite_unlocked = (size_t(*)(const void *ptr, size_t size, size_t nmemb, FILE *stream))dlsym(RTLD_NEXT, "fwrite_unlocked"); 615 | _libc_fputc_unlocked = (int (*)(int character, FILE *fp))dlsym(RTLD_NEXT, "fputc_unlocked"); 616 | _libc_fputs_unlocked = (int (*)(const char *str, FILE *fp))dlsym(RTLD_NEXT, "fputs_unlocked"); 617 | _libc_fread_unlocked = (size_t(*)(void *ptr, size_t size, size_t nmemb, FILE *stream))dlsym(RTLD_NEXT, "fread_unlocked"); 618 | _libc_fgetc_unlocked = (int (*)(FILE * fp)) dlsym(RTLD_NEXT, "fgetc_unlocked"); 619 | _libc_fgets_unlocked = (char *(*)(char *str, int num, FILE *fp))dlsym(RTLD_NEXT, "fgets_unlocked"); 620 | _libc_fileno_unlocked = (int (*)(FILE *stream))dlsym(RTLD_NEXT, "fileno_unlocked"); 621 | 622 | _posix_open = (int (*)(const char *pathname, int flags, ...))dlsym(RTLD_NEXT, "open"); 623 | _posix_read = (ssize_t (*)(int fd, void *buf, size_t count))dlsym(RTLD_NEXT, "read"); 624 | _posix_write = (ssize_t (*)(int fd, const void *buf, size_t count))dlsym(RTLD_NEXT, "write"); 625 | _posix_lseek = (off_t (*)(int fd, off_t offset, int whence))dlsym(RTLD_NEXT, "lseek"); 626 | _posix_close = (int (*)(int fd))dlsym(RTLD_NEXT, "close"); 627 | 628 | // get ourselves an fd 629 | int fd = _posix_open("/dev/null", 2 /* O_RDWR */); 630 | afl_input_file.memory = 0; 631 | afl_input_file.fd = fd; 632 | } 633 | 634 | /* 635 | * Library destructor 636 | */ 637 | __attribute__((destructor)) static void unload(void) 638 | { 639 | } 640 | --------------------------------------------------------------------------------