Fwrite () adds garbage data for output (WINE & Windows 7, mingw & MSVC; NOT linux / gcc)

Under certain circumstances, fwrite writes extra data (more bytes than requested). The result of a short demonstration is the easiest way to explain. The demo tries to create two files of 2048 bytes each and checks the offset after each fwrite call to determine the number of bytes written. The first fwrite call writes two additional 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 succeeds (it writes 2048 bytes to both files) when compiling as ELF (unix binary), but it crashes (as shown above) when compiling as PE (Windows binary / executable). I 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 this happens almost every time (unless you write 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 generated from 2048 bytes / dev / urandom and 2048 bytes from / dev / zero (respectively) using xxd . For instance:

 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 
+6
source share
1 answer

Disclaimer: 5 days have passed and no one has posted an β€œofficial” answer, so I accept this answer and accept it. The loan goes to Christophe and Retired Ninja to answer the question.

The simple answer is: you need to open the binaries in binary mode (by adding the second argument 'b' to fopen ).

By default, fopen opens files in text mode, not binary mode. In text mode, the newline character ( \n ) is replaced by the newline sequence of the operating system when writing to a file and vice versa when reading. Unlike POSIX systems (Linux, OSX, BSD, etc.) that use a single character ( \n ) as a newline, Windows uses the sequence \r\n a newline.

+3
source

Source: https://habr.com/ru/post/974140/


All Articles