uninitialized memory read

P

parag_paul

For the following c file,
#include <stdio.h>


#define U unsigned int
#define FULL_MASK 0xffffffff

int main(){
U mask = 0;
int g;
int bit = 5;
mask = (U)((5&31) ? ~(FULL_MASK << (5&31)) : FULL_MASK);
printf("%d and the value is maskt \n", mask);
g = mask;

}


I find that the in purify , the statement mask = (U)((5&31) ? ~
(FULL_MASK << (5&31)) : FULL_MASK);
basically assigns a uninitialized and unallocated value to the
variable mask.

Sorry if it is a purify specific question,. I did nto find any group
mathching that, so I believe that the next most suitable group is this
one.

Could this be a bug in purify,
 
M

Mark Wooding

#include <stdio.h>


#define U unsigned int
#define FULL_MASK 0xffffffff

int main(){
U mask = 0;
int g;
int bit = 5;
mask = (U)((5&31) ? ~(FULL_MASK << (5&31)) : FULL_MASK);
printf("%d and the value is maskt \n", mask);
g = mask;

}

Comments:

* Important style: Use a typedef rather than #define for making type
synonyms.

* Indentation is nice.

* You never read the values of `bit' or `g'.

* `mask' has type `unsigned int' but you're passing it to `printf'
with a `%d' format specifier which expects a signed `int'. If
`mask' is actually representable as an `int' then all will be well;
if not, you have undefined behaviour.

* The constant FULL_MASK may have signed type. If it has, then
FULL_MASK << n may overflow causing undefined behaviour. You
probably mean to define FULL_MASK to be 0xffffffffu, but, in fact...

* It looks to me as if you're better off including <limits.h> and
using UINT_MAX rather than guessing FULL_MASK, which may be either
too large to fit in unsigned int, or too small to cover all of the
bits. Of course, I don't actually know what you're trying to
achieve, so this might be wrong.
I find that the in purify , the statement mask = (U)((5&31) ? ~
(FULL_MASK << (5&31)) : FULL_MASK);
basically assigns a uninitialized and unallocated value to the
variable mask.

I'll assume that FULL_MASK either has unsigned type or is capable of
representing all of the values necessary.

5 & 31 = 5 /= 0, so the consequent expression is evaluated.

~(FULL_MASK << (5 & 31)) = ~(FULL_MASK << 5)

= ~0x1fffffffe0

= -0x1fffffffdf

This is then reduced modulo 2^n (maybe it helps to think of this as a
2-adic value, but probably not...), where n is the width of the smaller
of unsigned int and whatever type 0xffffffff happens to have on your
platform. The result will end 0x...1f; there may or may not be higher-
order set bits, depending on the widths of the types involved.

So it looks as if all of the bits of mask are properly initialized,
though maybe not with what you expected them to be initialized to. So
to me it sounds like (a) Purify is wrong, and (b) so is your code.

For the record, Valgrind didn't find anything to complain about.

-- [mdw]
 
E

Eric Sosman

For the following c file,
#include <stdio.h>


#define U unsigned int
#define FULL_MASK 0xffffffff

int main(){
U mask = 0;
int g;
int bit = 5;
mask = (U)((5&31) ? ~(FULL_MASK << (5&31)) : FULL_MASK);
printf("%d and the value is maskt \n", mask);
g = mask;

}


I find that the in purify , the statement mask = (U)((5&31) ? ~
(FULL_MASK << (5&31)) : FULL_MASK);
basically assigns a uninitialized and unallocated value to the
variable mask.

That seems odd. Stripped of obfuscation, the line
is merely

unsigned int mask = (unsigned int)~(0xffffffff << 5);

It is conceivable that the arithmetic in this initialization
would be undefined (for example, on a 36-bit system), but on
the far more common 32-bit machines it's just

unsigned int mask = 0x1fu;

.... which should be unobjectionable.

However, the next two line is suspect. The "%d" specifier
requires a plain `int' value to convert, and you're feeding it
an `unsigned int' instead. This produces undefined behavior,
which on most systems nowadays turns out to be nothing worse
than bad-looking output. But under a debugging environment
like Purify, perhaps the consequences are more severe. Are
you sure you've correctly identified the line Purify is unhappy
about? Might it be complaining about the printf() and not the
initialization that immediately precedes it?
Sorry if it is a purify specific question,. I did nto find any group
mathching that, so I believe that the next most suitable group is this
one.

Could this be a bug in purify,

Possibly. What does your IBM Support person think?
 
P

parag

#include <stdio.h>
#define U unsigned int
#define FULL_MASK 0xffffffff
int main(){
U mask = 0;
int g;
int bit = 5;
mask =  (U)((5&31) ? ~(FULL_MASK << (5&31)) : FULL_MASK);
printf("%d and the value is maskt \n", mask);
g = mask;

Comments:

  * Important style: Use a typedef rather than #define for making type
    synonyms.

  * Indentation is nice.

  * You never read the values of `bit' or `g'.

  * `mask' has type `unsigned int' but you're passing it to `printf'
    with a `%d' format specifier which expects a signed `int'.  If
    `mask' is actually representable as an `int' then all will be well;
    if not, you have undefined behaviour.

  * The constant FULL_MASK may have signed type.  If it has, then
    FULL_MASK << n may overflow causing undefined behaviour.  You
    probably mean to define FULL_MASK to be 0xffffffffu, but, in fact....

  * It looks to me as if you're better off including <limits.h> and
    using UINT_MAX rather than guessing FULL_MASK, which may be either
    too large to fit in unsigned int, or too small to cover all of the
    bits.  Of course, I don't actually know what you're trying to
    achieve, so this might be wrong.
I find that the in purify , the statement mask =  (U)((5&31) ? ~
(FULL_MASK << (5&31)) : FULL_MASK);
basically assigns a uninitialized and unallocated value to the
variable mask.

I'll assume that FULL_MASK either has unsigned type or is capable of
representing all of the values necessary.

5 & 31 = 5 /= 0, so the consequent expression is evaluated.

        ~(FULL_MASK << (5 & 31)) = ~(FULL_MASK << 5)

                                 = ~0x1fffffffe0

                                 = -0x1fffffffdf

This is then reduced modulo 2^n (maybe it helps to think of this as a
2-adic value, but probably not...), where n is the width of the smaller
of unsigned int and whatever type 0xffffffff happens to have on your
platform.  The result will end 0x...1f; there may or may not be higher-
order set bits, depending on the widths of the types involved.

So it looks as if all of the bits of mask are properly initialized,
though maybe not with what you expected them to be initialized to.  So
to me it sounds like (a) Purify is wrong, and (b) so is your code.

For the record, Valgrind didn't find anything to complain about.

-- [mdw]

Nope, My Valgrind output did not find anything
Valgrind version (
valgrind-3.2.0
)
output
valgrind --tool=memcheck --show-reachable=yes --undef-value-
errors=yes ./a.out
==31752== Memcheck, a memory error detector.
==31752== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et
al.
==31752== Using LibVEX rev 1606, a library for dynamic binary
translation.
==31752== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
==31752== Using valgrind-3.2.0, a dynamic binary instrumentation
framework.
==31752== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et
al.
==31752== For more details, rerun with: -v
==31752==
31 and the value is maskt
==31752==
==31752== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from
5)
==31752== malloc/free: in use at exit: 0 bytes in 0 blocks.
==31752== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
==31752== For counts of detected errors, rerun with: -v
==31752== All heap blocks were freed -- no leaks are possible.

looks like nothing
 
K

Keith Thompson

Mark Wooding said:
#define U unsigned int
[...]
Comments:

* Important style: Use a typedef rather than #define for making type
synonyms.
[...]

Also important style: Don't use type synonyms unless they make the
code clearer. In this case, referring to unsigned int as U doesn't
help anything. Just call it unsigned int.
 
K

Kenny McCormack

Mark Wooding said:
#define U unsigned int
[...]
Comments:

* Important style: Use a typedef rather than #define for making type
synonyms.
[...]

Also important style: Don't use type synonyms unless they make the
code clearer. In this case, referring to unsigned int as U doesn't
help anything. Just call it unsigned int.

Also, important MYOB point: "clearer" is in the eye of the beholder.
 
G

Guest

Mark Wooding said:
#define U unsigned int
[...]
Comments:

  * Important style: Use a typedef rather than #define for making type
    synonyms.

[...]

Also important style: Don't use type synonyms unless they make the
code clearer.  In this case, referring to unsigned int as U doesn't
help anything.  Just call it unsigned int.

or even unsigned
I confess I quite like Uint as its shorter, though U is overdoing it a
bit
and I use Byte or Octet when I want to be clear that I'm handling
8-bit quantities.
 
K

Keith Thompson

Mark Wooding said:
#define U unsigned int [...]
Comments:

  * Important style: Use a typedef rather than #define for making type
    synonyms.

[...]

Also important style: Don't use type synonyms unless they make the
code clearer.  In this case, referring to unsigned int as U doesn't
help anything.  Just call it unsigned int.

or even unsigned
I confess I quite like Uint as its shorter, though U is overdoing it a
bit
and I use Byte or Octet when I want to be clear that I'm handling
8-bit quantities.

Byte and Octet make sense, since they add some actual information
(but keep in mind that a byte isn't necessarily an octet, though a
given piece of code might be intended only for environments where
it is). I suggest that Uint:

typedef unsigned int Uint;

doesn't add anything useful, and there's no real possiblity that Uint
could be defined as anything other than unsigned int. Worse yet,
someone might later change the definition to, say,

typedef unsigned long Uint; /* ugh! */

which is a sure sign that Uint was the wrong name in the first place.
 
G

Guest

or even unsigned[.] I confess I quite like Uint as its shorter,
though U is overdoing it a bit and I use Byte or Octet when I want
to be clear that I'm handling 8-bit quantities.

Byte and Octet make sense, since they add some actual information
(but keep in mind that a byte isn't necessarily an octet, though a
given piece of code might be intended only for environments where
it is).

People seem to find Octet odd as if you being mindlessly pedantic.
They *think* they know what a byte is.

 I suggest that Uint:

    typedef unsigned int Uint;

doesn't add anything useful, and there's no real possiblity that Uint
could be defined as anything other than unsigned int.  Worse yet,
someone might later change the definition to, say,

    typedef unsigned long Uint; /* ugh! */

eek! This is a bit like some of Microsoft's Hungarian Atrocities
which is a sure sign that Uint was the wrong name in the first place.

yes. I've been on projects that mandated these things and the project
checkin rejected ints and other C types!
 
R

Richard Bos

Keith Thompson said:
I suggest that Uint:

typedef unsigned int Uint;

doesn't add anything useful, and there's no real possiblity that Uint
could be defined as anything other than unsigned int. Worse yet,
someone might later change the definition to, say,

typedef unsigned long Uint; /* ugh! */

which is a sure sign that Uint was the wrong name in the first place.

See also the M$ Windows API. For example, what _should_ be the
difference, according to their names, between a WPARAM and an LPARAM?
And what is the actual difference? Between a PSTR, an LPSTR, and a PCH?

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,999
Messages
2,570,246
Members
46,839
Latest member
MartinaBur

Latest Threads

Top