Under certain circumstances, fwrite
writes extra data (more bytes than requested). The output of a short demo is the easiest way to explain. The demo attempts to create two 2048 byte files and checks the offset after each fwrite
call to determine the number of bytes written. The first fwrite
call writes two extra bytes:
len: 2048
current offset = 0
wrote 1024 bytes
current offset = 1026
EXITING:
offset % BLOCKSIZE = 2
len: 2048
current offset = 0
wrote 1024 bytes
current offset = 1024
wrote 1024 bytes
SUCCESS
The program runs successfully (writes 2048 bytes to both files) when compiled as an ELF (unix binary), but fails (as shown above) when compiled as a PE (windows binary/executable). I've tried compiling and testing with:
Ubuntu 14.04 and gcc 4.8.2 - SUCCESS
WINE 1.6.2 and mingw 4.8.2 - FAIL
Windows 7 and mingw 4.8.2 - FAIL
Windows 7 and Visual Studio 2013 - FAIL
The actual data in the buffer passed to fwrite
affects the number of extra bytes written, but it happens virtually every time (unless you're writing NULL bytes).
main.c:
#include <stdio.h>
#include "stub.h"
#include "stub2.h"
size_t min(size_t a, size_t b)
{
return a<b?a:b;
}
#define BLOCKSIZE 1024
void test(char buf[], size_t len)
{
FILE *f = fopen("out", "w");
printf("len: %lu\n", len);
for(size_t i=0;i<len;i+=BLOCKSIZE)
{
printf("current offset = %lu\n", ftell(f));
if(ftell(f) % BLOCKSIZE)
{
printf("EXITING:\noffset %% BLOCKSIZE = %d\n\n", ftell(f) % BLOCKSIZE);
return;
}
size_t wrote = fwrite(buf + i, 1, min(len - i, BLOCKSIZE), f);
printf("wrote %lu bytes\n", wrote);
}
printf("SUCCESS\n\n");
fclose(f);
}
int main()
{
test(stub_exe, stub_exe_len);
test(stub2_exe, stub2_exe_len);
return 0;
}
stub.h
and stub2.h
are generated from the 2048 bytes of /dev/urandom and 2048 bytes from /dev/zero (respectively) with xxd
. For example:
dd if=/dev/urandom of=stub2.exe bs=2048 count=1
xxd -i stub.exe stub.h
dd if=/dev/zero of=stub2.exe bs=2048 count=1
xxd -i stub2.exe stub2.h