fwrite() and file corruption - c

I'm trying to write a wchar array to a file in C, however there is some sort of corruption and unrelevant data like variables and paths like this
c.:.\.p.r.o.g.r.a.m. .f.i.l.e.s.\.m.i.c.r.o.s.o.f.t. .v.i.s.u.a.l. .s.t.u.d.i.o. 1.0...0.\.v.c.\.i.n.c.l.u.d.e.\.x.s.t.r.i.n.g..l.i.s.t...i.n.s.e.r.t
are written on to the file along with the correct data (example) I have confirmed that the buffer is null-terminated and contains proper data.
Heres my code:
myfile = fopen("logs.txt","ab+");
fseek(myfile,0,SEEK_END);
long int size = ftell(myfile);
fseek(myfile,0,SEEK_SET);
if (size == 0)
{
wchar_t bom_mark = 0xFFFE;
size_t written = fwrite(&bom_mark,sizeof(wchar_t),1,myfile);
}
// in another func
while (true)
{
[..]
unsigned char Temp[512];
iBytesRcvd = recv(sclient_socket,(char*)&Temp,iSize,NULL);
if(iBytesRcvd > 0 )
{
WCHAR* unicode_recv = (WCHAR*)&Temp;
fwrite(unicode_recv,sizeof(WCHAR),wcslen(unicode_recv),myfile);
fflush(myfile);
}
[..]
}
What could be causing this?

recv() will not null-terminate &Temp, so wcslen() runs over the bytes actually written by recv(). You will get correct results if you just use iBytesReceived as byte count for fwrite() instead of using wcslen() and hoping the data received is correctly null-terminated (wide-NULL-terminated, that is):
fwrite(unicode_recv, 1, iBytesReceived, myfile);

Related

How to allocate memory when using custom reading functions in libpng?

I'm in need of reading base64 encoded PNG image, stored as char array/null terminated string, and I'm stuck. Here is what I have found out for now:
Libpng is capable of changing it's workings, by using png_set_*_fn().
reading functions must have prototype alike this one : void user_read_data(png_structp png_ptr, png_bytep data, size_t length); and must check for EOF errors.
Original read function (which reads from png file directly) calls an fread function and dumps everything to memory pointed by data. I have no idea how libpng knows about image size.
So, here is my implementation of read function
size_t base64_to_PNG(const char *const base64_png, png_bytep out)
{
size_t encoded_size, decoded_count;
size_t decoded_size = base64_decoded_block_size(base64_png, &encoded_size);
decoded_count = base64_decode_block(base64_png, encoded_size, (char*)out);
if(decoded_count != decoded_size)
return 0;
return decoded_size;
}
void my_read_png_from_data_uri(png_structp png_ptr, png_bytep data, size_t length)
{
const char *base64_encoded_png = NULL;
size_t PNG_bytes_len;
if(png_ptr == NULL)
return;
base64_encoded_png = png_get_io_ptr(png_ptr);
PNG_bytes_len = base64_to_PNG(base64_encoded_png, data);
if(PNG_bytes_len != length)
png_error(png_ptr, "Error occured during decoding of the image data");
}
I do believe that information about the decoded image size is lost, and I'm going straight to the segfault with that, as I'll be writing to some random address, but I have no idea how to tell libpng how much memory I need. Can you please help me with that?

How to use ReadFile with wchar_t?

Consider the following two functions, the first one uses the Windows API functions ReadFile() and CreateFileW(), whereas the second function uses fopen() and fgetws(), to read a non-English text from a file called data.txt.
The first function outputs garbage text, whereas the second function outputs the text from the file without any problems.
Notice that fopen() has ccs=UTF-8 that defines what character encoding to use, whereas read_file_2() does not have something similar.
DWORD read_file_2()
{
wchar_t wstr[512];
BOOL success = FALSE;
DWORD dwRead, total =0;
HANDLE handle = CreateFileW(L"data.txt",
GENERIC_READ,
0,
NULL,
3,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (handle == INVALID_HANDLE_VALUE)
return -1;
do
{
success = ReadFile(handle, wstr, 20, &dwRead, NULL);
total += dwRead;
} while(!success || dwRead == 0);
wstr[total] = L'\0';
wprintf(L"%ls\n",wstr);
return 0;
}
void read_file_1()
{
wchar_t converted[20];
FILE * ptr;view=msvc-170
ptr = fopen("data.txt", "rt+,ccs=UTF-8");
fgetws(converted, 20, ptr);
wprintf(L"%ls\n", converted);
fclose(ptr);
}
int main()
{
_setmode(fileno(stdin), _O_U8TEXT);
_setmode(fileno(stdout), _O_U8TEXT);
read_file_1();
read_file_2();
}
How does one use ReadFile() to read a wchar_t string from a text file and output it to the terminal without turning it into garbage text?
Шифрование.txt ال
퀠킨톸톄킀킾킲킰킽킸♥
Actual content of data.txt:
Шифрование.txt العربية.txt
You can use MultiByteToWideChar.
int total_wchars = MultiByteToWideChar(
CP_UTF8, // CodePage
0, // dwFlags
bytes, // lpMultiByteStr The bytes read using `ReadFile`/`read`.
total_bytes, // cbMultiByte No need for NUL.
NULL, // lpWideCharStr
0 // cchWideChar 0 = Get size incl NUL.
);
if ( total_wchars == 0 ) {
// Error. Use GetLastError() and such.
...
}
LPWSTR wchars = malloc( total_wchars * sizeof( *wchars ) );
MultiByteToWideChar(
CP_UTF8, // CodePage
0, // dwFlags
bytes, // lpMultiByteStr
total_bytes, // cbMultiByte
wchars, // lpWideCharStr
total_wchars // cchWideChar
);
Note that if the compiler has wchar_t,
WCHAR is wchar_t
LPWSTR is wchar_t *
LPCWSTR is const wchar_t *
The problem is that ReadFile() doesn't read strings, or even characters. It reads bytes.
Since it doesn't read strings, it also doesn't null-terminate the data like a string.
You need to make sure that it reads enough bytes, and to null-terminate the buffer if it's a string.
By using a loop, you have a good start, but your loop overwrites what was read in the last iteration of the loop, making you lose the data.
You need to pass a pointer to the end of the buffer in the loop.
And as I already mentioned in a comment, make sure that the loop works properly (and not go into an infinite loop if there's an error, for example).

Why does malloc provoke memory corruption here?

I keep getting the following error:
*** Error in `./vice': malloc(): memory corruption: 0x08e77530 ***
Aborted (core dumped)
The relevant code is:
open_result *
open_file_1_svc(open_args *argp, struct svc_req *rqstp)
{
static open_result result;
int obtained_fd;
int just_read;
int total_read = 0;
int max_bytes_read = 1024;
char *ptr_file;
char *pathName = "MyFiles/"; // strlen = 8
int toReserve;
xdr_free((xdrproc_t)xdr_open_result, (char *)&result);
// Construct full name of the file (in "MyFiles")
toReserve = strlen(argp->fname) + strlen(pathName) + 1; // "\0"
char *fullName = malloc(toReserve*sizeof(char));
fullName = strdup(pathName);
fullName = strcat(fullName, argp->fname);
// Call to open in POSIX
obtained_fd = open(fullName, argp->flags);
result.fd = obtained_fd;
/* If there was an error while reading, the error code will be sent, but not
the file (it might not even exist) */
if (obtained_fd < 0) {
result.characters = "";
result.number_characters = 0;
}
/* If the file opening was successful,
both the fd and the file will be sent */
else {
char *file_just_read = malloc(max_bytes_read * sizeof(char)); // This is the problem
ptr_file = file_just_read;
/* Reading the file byte by byte */
while((just_read = read(obtained_fd, ptr_file, max_bytes_read)) > 0) {
total_read += just_read;
file_just_read = realloc(file_just_read, (total_read+max_bytes_read) * sizeof(char));
ptr_file = file_just_read + total_read;
}
result.characters = file_just_read;
result.number_characters = total_read;
}
return &result;
}
Let me explain what the code does. This is a server named "vice" which communicates with its clients via RPC. This function is supposed to receive "open_args" and return "open_result". These are defined in the "vice.x" file. The relevant part of this file is:
struct open_args {
string fname<>;
int flags;
};
struct open_result {
string characters<>;
int number_characters;
int fd;
};
open_file_1_svc is supposed to try to open a file with the name given in argp->fname in the directory MyFiles. If open is successful, open_file_1_svc will attempt to copy the contents of the file in result.characters, sending a copy of the contents of the file to the client this way. The number_characters will allow me to know if there are any null bytes in between.
The error I'm getting appears when I attempt to allocate some memory for the part of the file I'm about to read.
I've been reading about this type of error, but I don't understand what's wrong with this particular case.
malloc does not "provoke" the corruption; malloc detects it.
This error is telling you that something had scribbled over the heap meta data before malloc was called (this time); you probably have a buffer overrun.
Both malloc calls in this code are before anything writes to memory, so the overrun is most likely elsewhere. (I've not done a detailed check that this code is right, but it's after-the-fact here.)
Edit: I missed the implicit malloc call inside the strdup. This will cause an overrun because the duplicated string has a smaller allocation. I think you mean strcpy, not strdup.

fread returns no data in my buffer in spite of saying it read 4096 bytes

I'm porting some C code that loads sprites from files containing multiple bitmaps. Basically the code fopens the file, fgetcs some header info, then freads the bitmap data. I can see that the fgetcs are returning proper data, but the outcome of the fread is null. Here's the code - fname does exist, the path is correct, fil is non-zero, num is the number of sprites in the file (encoded into the header, little-endian), pak is an array of sprites, sprite is a typedef of width, height and bits, and new_sprite inits one for you.
FILE *fil;
uint8 *buffu;
uint8 read;
int32 x,num;
int32 w,h,c;
fil = fopen(fname, "rb");
if (!fil) return NULL;
num = fgetc(fil);
num += fgetc(fil)*256;
if (num > max) max = num;
for (x=0;x<max;x++) {
// header
w=fgetc(fil);
w+=fgetc(fil)*256;
h=fgetc(fil);
h+=fgetc(fil)*256;
fgetc(fil); // stuff we don't use
fgetc(fil);
fgetc(fil);
fgetc(fil);
// body
buffu = (uint8*)malloc(w * h);
read=fread(buffu,1,w*h,fil);
pak->spr[x]=new_sprite(w,h);
memcpy(pak->spr[x]->data, buffu, w*h);
// done
free(buffu);
}
I've stepped through this code line by line, and I can see that w and h are getting set up properly, and read=4096, which is the right number of bits. However, buffer is "" after the fread, so of course memcpy does nothing useful and my pak is filled with empty sprites.
My apologies for what is surely a totally noob question, but I normally use Cocoa so this pure-C file handling is new to me. I looked all over for examples of fread, and they all look like the one here - which apparently works fine on Win32.
Since fgetc seems to work, you could try this as a test
int each;
int byte;
//body
buffu = malloc(w * h);
for (each = 0; each < w*h; each++) {
byte = fgetc(fil);
if ( byte == EOF) {
printf("End of file\n");
break;
}
buffu[each] = (uint8)byte;
printf ("byte: %d each: %d\n", byte, each);
}
pak->spr[x]=new_sprite(w,h);
memcpy(pak->spr[x]->data, buffu, w*h);
// done
You say:
However, buffer is "" after the fread, so of course memcpy does nothing useful
But that is not true at all. memcpy() is not a string function, it will copy the requested number of bytes. Every time. If that isn't "useful", then something else is wrong.
Your buffer, when treated as a string (which it is not, it's a bunch of binary data) will look like an empty string if the first byte happens to be 0. The remaining 4095 bytes can be whatever, to C's string printing functions it will look "empty".

Why is zlib deflate() hanging?

My issue is that my program hangs on use of zlib's deflate() function.
I first initialize my z_stream, as follows:
int setupGzipOutputStream(z_stream zStream) {
int zError;
zStream.zalloc = Z_NULL;
zStream.zfree = Z_NULL;
zStream.opaque = Z_NULL;
zError = deflateInit(&zStream, Z_COMPRESSION_LEVEL);
/* error handling code to test if zError != Z_OK... */
return EXIT_SUCCESS;
}
I attempt to write data to my z-stream with the following function:
int compressDataToGzipOutputStream(unsigned char *myData, z_stream zStream, Boolean flushZStreamFlag) {
int zError;
int zOutHave;
FILE *outFp = stdout;
unsigned char zBuffer[Z_BUFFER_MAX_LENGTH] = {0};
zStream.next_in = myData;
zStream.avail_in = strlen(myData); /* myData is a null-terminated string */
do {
zStream.avail_out = Z_BUFFER_MAX_LENGTH;
zStream.next_out = zBuffer;
zError = deflate(&zStream, (flushZStreamFlag == kFalse) ? Z_NO_FLUSH : Z_FINISH);
/* error handling code to test if zError != Z_OK... */
zOutHave = Z_BUFFER_MAX_LENGTH - zStream.avail_out;
fwrite(zBuffer, sizeof(unsigned char), zOutHave, outFp);
fflush(outFp);
} while (zStream.avail_out == 0);
return EXIT_SUCCESS;
}
I call these two functions (with simplifications for the purpose of asking this question) as follows:
z_stream zOutStream;
setupGzipOutputStream(zOutStream);
compressDataToGzipOutputStream(data, zOutStream, kFalse);
compressDataToGzipOutputStream(data, zOutStream, kFalse);
...
compressDataToGzipOutputStream(data, zOutStream, kTrue);
I then break down the zOutStream struct with deflateEnd().
The kTrue value on the last compression step sends the Z_FINISH flag to deflate(), instead of Z_NO_FLUSH.
It hangs on the following line:
zError = deflate(&zStream, (flushZStreamFlag == kFalse) ? Z_NO_FLUSH : Z_FINISH);
I then tried using gdb. I set a break at this line, the line where the program hangs.
At this breakpoint, I can see the values of the variables zStream, flushZStreamFlag and others. The zStream variable is not NULL, which I can verify with print zStream, print zStream.next_in, etc. which are populated with my data of interest.
If I type next in gdb, then this line of code is processed and the entire process hangs, which I verify with log statements before and after this line of code. The "before" log statement shows up, but the "after" statement does not.
My question is: Why is deflate() hanging here? Am I not initializing the output stream correctly? Not using deflate() correctly? I've been banging my head on the wall trying to solve this, but no luck. Thanks for any advice you might have.
Your functions should take a pointer to a z_stream, rather than passing the struct in. Your init function is initialising what is effectively a local copy, which will be discarded. Then your compression function will have a garbage z_stream passed to it.
e.g:
int setupGzipOutputStream(z_stream *zStream) {
int zError;
zStream->zalloc = Z_NULL;
...
}
... etc.
It also looks like your compression function is not taking into account the null on the end of the string, so that might cause you problems when you try to re-inflate your data.
zStream.avail_in = strlen(myData);
Might want to be:
zStream.avail_in = strlen(myData) + 1;

Resources