Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Valgrind error m64 m32

Tags:

c

valgrind

I'm trying to verify this code file test.c below using valgrind, when I make gcc test.c -o test I get the follow error

Syscall param write(buf) points to uninitialised byte(s)
==22765==    at 0x4F22870: __write_nocancel (syscall-template.S:81)
==22765==    by 0x4EB0002: _IO_file_write@@GLIBC_2.2.5 (fileops.c:1261)
==22765==    by 0x4EB14DB: _IO_do_write@@GLIBC_2.2.5 (fileops.c:538)
==22765==    by 0x4EB0D5F: _IO_file_close_it@@GLIBC_2.2.5 (fileops.c:165)
==22765==    by 0x4EA4B0F: fclose@@GLIBC_2.2.5 (iofclose.c:59)
==22765==    by 0x400986: main (in /home/grados-sanchez/git/merkle-codigos-C/test)
==22765==  Address 0x4025770 is not stack'd, malloc'd or (recently) free'd
==22765==  Uninitialised value was created by a stack allocation
==22765==    at 0x4007E2: node_write (in /home/grados-sanchez/git/merkle-codigos-C/test)

but when I run gcc test.c -o test and then valgrind I don't get any error. My question is What happen with valgrind in this case? Is there any way for run valgrind for 32 or 64 bits?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define id_lenght 6000
typedef unsigned char * ustring;
typedef struct {
    ustring ustr;
    int height;
    char id[id_lenght];
} node;

int validation_read(void * ptr_var, size_t sizeof_datatype, int num,
    FILE * ptr_file) {
    if (fread(ptr_var, sizeof_datatype, num, ptr_file) <= 0) {
        printf("Error reading file");
       return 1;
    }
return 0;
}

void node_read(FILE * node_ptr, node * n, int r) {
    int i;
    validation_read(n->id, sizeof(unsigned char), id_lenght, node_ptr);
    validation_read(&(n->height), sizeof(int), 1, node_ptr);
    validation_read(n->ustr, sizeof(unsigned char) * (r + 1), 1,node_ptr);
}

void node_init(node * n, int r) {
    memset(n, 0, sizeof(node));
    n->ustr = malloc((r + 1) * sizeof(unsigned char));
    memset(n->ustr, 0, (r + 1));
    n->ustr[r] = 0;
    n->height = -1;
    memset(n->id,0,id_lenght+1);
}


void node_write(FILE * node_ptr, node * n, int r) {
    int i;
    char newid[id_lenght];
    memset(newid,0,id_lenght);
    sprintf(newid,"%s",n->id);
    fwrite(newid, sizeof(char), id_lenght+1, node_ptr);
    fwrite(&(n->height), sizeof(int), 1, node_ptr);
    fwrite(n->ustr, sizeof(unsigned char) * (r + 1), 1,node_ptr);
}


void node_destroy(node * n) {
    free(n->ustr);
    n->height = -1;
}

int main(){
    FILE * ptr = fopen("juantest","w+");
    int r = 64/8;
    node in;
    node_init(&in, r);
    node_write(ptr, &in, r);
    node_destroy(&in);
    fclose(ptr);
}

EDIT But a problem happens when I trying to read the file. I edited my above code. I get Error reading fileError reading fileError reading

like image 573
Juan Avatar asked May 28 '15 20:05

Juan


1 Answers

Valgrind is right to worry. In this line

fwrite(newid, sizeof(char), id_lenght+1, node_ptr);

you are writing 1 byte more data than allowed; the one beyond your new temporary stack string. You probably confused writing a string (with a +1 for the terminating zero) with writing exactly the (maximum) buffer size used:

fwrite(newid, sizeof(char), id_length, node_ptr);

Since you are dumping memory contents to a file, you are correct to clear the string memory before using sprintf. You never know what's inside freshly allocated memory!
Note that if you are worried about data integrity, it's always better to use the safe variant sprintf_s instead, as it will guard you from over-running this buffer.

like image 63
Jongware Avatar answered Nov 08 '22 23:11

Jongware