fread(), solaris to unix portability and use of uninitialised values

117 views Asked by At

Valgrind found the following error and I, after reading the documentation, the code and other questions in here couldn't figure it out why.

Valgrind: first warning

~$ valgrind --vgdb=yes --vgdb-error=0 --read-var-info=yes --leak-check=yes --track-origins=yes debitadmin*

debitadmin  ==20720== Conditional jump or move depends on uninitialised value(s)
==20720==    at 0x4013BC6: initialise (dbg.c:199)
==20720==    by 0x4013F5C: ??? (in /opt/ivb/lib/libdbg.so)
==20720==    by 0x4013917: ??? (in /opt/ivb/lib/libdbg.so)
==20720==    by 0x5F5FFE: _dl_init (in /lib/ld-2.12.so)
==20720==    by 0x5E788E: ??? (in /lib/ld-2.12.so)
==20720==  Uninitialised value was created by a stack allocation
==20720==    at 0x4013A8F: initialise (dbg.c:150)

GDB & Valgrind: symbols

(gdb) info symbol 0x4013A8F
initialise + 5 in section .text of /opt/ivb/lib/libdbg.so

(gdb) info symbol 0x4013BC6
initialise + 316 in section .text of /opt/ivb/lib/libdbg.so

Code: dbg.c

148    void
149    initialise(void)
150    {
151        register int i = 0;
152        char buffer[FILENAME_MAX] = "";
153        char *program = NULL;
154        struct sigaction act = {0};
...
... 
195         while ( ! feof(proc_file) && ! ferror(proc_file))
196         {
197             char ch;
198             fread(&ch,1,1,proc_file);
199             if ( ch != 0 )
200             fprintf(stderr,"%c",ch);
201             else
202             fprintf(stderr," ");
203         }

GDB: backtrace

(gdb) bt
#0  0x04013bc6 in initialise () at dbg.c:199
#1  0x04013f5d in __do_global_ctors_aux () from /opt/ivb/lib/libdbg.so
#2  0x04013918 in _init () from /opt/ivb/lib/libdbg.so
#3  0x005f5fff in _dl_init_internal () from /lib/ld-linux.so.2
#4  0x005e788f in _dl_start_user () from /lib/ld-linux.so.2

GDB: locals

(gdb) info locals
ch = 0 '\000'
c = 10

Extra information

  • This code is part of a library, which was ported from Solaris to Unix

What I understood:

Valgrind complains that

char ch; 

is not initialised, even after

fread(&ch,1,1,proc_file);

After checking with GDB ch value after the above line, I have:

ch = 0 '\000'

proc_file does't correspond to that, as you can see:

(gdb) print *proc_file
$17 = {
  _flags = -72538984, 
  _IO_read_ptr = 0x4352000 "debitadmin", 
  _IO_read_end = 0x4352000 "debitadmin", 
  _IO_read_base = 0x4352000 "debitadmin", 
  _IO_write_base = 0x4352000 "debitadmin", 
  _IO_write_ptr = 0x4352000 "debitadmin", 
  _IO_write_end = 0x4352000 "debitadmin", 
  _IO_buf_base = 0x4352000 "debitadmin", 
  _IO_buf_end = 0x4353000 <Address 0x4353000 out of bounds>, 
  _IO_save_base = 0x0, 
  _IO_backup_base = 0x0, 
  _IO_save_end = 0x0, 
  _markers = 0x0, 
  _chain = 0x79c580, 
  _fileno = 3, 
  _flags2 = 0, 
  _old_offset = 0, 
  _cur_column = 0, 
  _vtable_offset = 0 '\000', 
  _shortbuf = "", 
  _lock = 0x43dc0c0, 
  _offset = -1, 
  __pad1 = 0x0, 
  __pad2 = 0x43dc0cc, 
  __pad3 = 0x0, 
  __pad4 = 0x0, 
  __pad5 = 0, 
  _mode = -1, 
  _unused2 = '\000' <repeats 39 times>
}

There is no MCVE because I'm still not sure about what the problem is, I'm counting on experts to help me tackle that.

So, my question is, why is ch empty even after fread() assignment? Is this a portability issue between Solaris and Linux? Is this the problem or am I missing something?

UPDATE: File has been opened and checked for not null.

#elif LINUX
    {
        char name[FILENAME_MAX];
    FILE *proc_file;
    sprintf(name,"/proc/%d/cmdline",(int)getpid());
    proc_file=fopen (name,"r");
    if ( proc_file != NULL )
    {
        int c;
        /* read in the programs name */
        for(c=0; ((fread(&buffer[c],1,1,proc_file)== 1) && (buffer[c]!=0)); c++);

        /* print out the program */
        (void)fprintf(stderr,"%s ", buffer);

        /* and the program arguments , not efficient but it works....*/
        fprintf(stderr," ");
        while ( ! feof(proc_file) && ! ferror(proc_file))
        {
            char ch;
            test *t;
            t = fread(&ch,1,1,proc_file);
            if ( ch != 0 )
            fprintf(stderr,"%c",ch);
            else
            fprintf(stderr," ");
        }
        (void) fprintf(stderr,"\n\n");
    }
    }
#endif
1

There are 1 answers

1
Sourav Ghosh On BEST ANSWER

Q 1. why is ch empty even after fread() assignment?

(Most probably) because fread() failed. See the detailed answer below.

Q 2.Is this a portability issue between Solaris and Linux?

No, there is a possible issue with your code itself, which is correctly reported by valgrind.


I cannot quite tell the below approach will solve your problem, but you should consider the below points to improve your code, e.g.,